5f0a06d3cb8e79207fc8c8a82b119daabc35d43d
[reactos.git] / lib / packet / Packet32.c
1 /*
2  * Copyright (c) 1999, 2000
3  *      Politecnico di Torino.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the Politecnico
13  * di Torino, and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #define UNICODE 1
23
24 #include <packet32.h>
25 #include <windows.h>
26 //#include <windowsx.h>
27 #include <ntddndis.h>
28
29 #include "trace.h"
30
31
32 /****** KERNEL Macro APIs ******************************************************/
33
34 #define GetInstanceModule(hInst)                (HMODULE)(hInst)
35 #define GlobalPtrHandle(lp)                     ((HGLOBAL)GlobalHandle(lp))
36 #define GlobalLockPtr(lp)                       ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
37 #define GlobalUnlockPtr(lp)                     GlobalUnlock(GlobalPtrHandle(lp))
38 #define GlobalAllocPtr(flags, cb)               (GlobalLock(GlobalAlloc((flags), (cb))))
39 #define GlobalReAllocPtr(lp, cbNew, flags)      (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
40 #define GlobalFreePtr(lp)                       (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
41
42 #undef GMEM_MOVEABLE
43 #define GMEM_MOVEABLE 0
44
45
46
47 /// Title of error windows
48 TCHAR   szWindowTitle[] = TEXT("PACKET.DLL");
49
50 #if DBG
51 #define ODS(_x) OutputDebugString(TEXT(_x))
52 //#define ODSEx(_x, _y)
53 #define ODSEx TRACE
54 #else
55 #ifdef _DEBUG_TO_FILE
56 #include <stdio.h>
57 /*! 
58   \brief Macro to print a debug string. The behavior differs depending on the debug level
59 */
60 #define ODS(_x) { \
61         FILE *f; \
62         f = fopen("winpcap_debug.txt", "a"); \
63         fprintf(f, "%s", _x); \
64         fclose(f); \
65 }
66 /*! 
67   \brief Macro to print debug data with the printf convention. The behavior differs depending on 
68   the debug level
69 */
70 #define ODSEx(_x, _y) { \
71         FILE *f; \
72         f = fopen("winpcap_debug.txt", "a"); \
73         fprintf(f, _x, _y); \
74         fclose(f); \
75 }
76
77 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
78 #else
79 #define ODS(_x)         
80 #define ODSEx(_x, _y)
81 #endif
82 #endif
83
84 //service handles
85 SC_HANDLE scmHandle = NULL;
86 SC_HANDLE srvHandle = NULL;
87 LPCTSTR NPFServiceName = TEXT("NPF");
88 LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
89 LPCTSTR NPFDriverName = TEXT("\\npf.sys");
90 LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
91
92
93 //---------------------------------------------------------------------------
94
95 /*! 
96   \brief The main dll function.
97 */
98
99 BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
100 {
101     BOOLEAN Status=TRUE;
102
103     switch ( Reason )
104     {
105         case DLL_PROCESS_ATTACH:
106                 
107                 ODS("\n************Packet32: DllMain************\n");
108                 
109 #ifdef _DEBUG_TO_FILE
110                 // dump a bunch of registry keys useful for debug to file
111                 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
112                         "adapters.reg");
113                 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
114                         "tcpip.reg");
115                 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
116                         "npf.reg");
117                 PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
118                         "services.reg");
119 #endif
120                 break;
121
122         case DLL_PROCESS_DETACH:
123                         break;
124
125                 default:
126             break;
127     }
128
129     return Status;
130 }
131
132 /*! 
133   \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
134   \param string The string to convert.
135   \return The converted string.
136 */
137
138 WCHAR* SChar2WChar(char* string)
139 {
140         WCHAR* TmpStr;
141         TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
142
143         MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
144
145         return TmpStr;
146 }
147
148 /*! 
149   \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
150   \param AdapterObject Handle to the service control manager.
151   \return If the function succeeds, the return value is nonzero.
152
153   The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
154   without performing a copy. This function tries to increase the size of that buffer.
155 */
156
157 BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
158 {
159     BOOLEAN    Status;
160     ULONG      IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
161     PPACKET_OID_DATA  OidData;
162
163     OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
164     if (OidData == NULL) {
165         ODS("PacketSetMaxLookaheadsize failed\n");
166         return FALSE;
167     }
168
169         //set the size of the lookahead buffer to the maximum available by the the NIC driver
170     OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
171     OidData->Length=sizeof(ULONG);
172     Status=PacketRequest(AdapterObject,FALSE,OidData);
173     OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
174     Status=PacketRequest(AdapterObject,TRUE,OidData);
175     GlobalFreePtr(OidData);
176     return Status;
177 }
178
179 /*! 
180   \brief Retrieves the event associated in the driver with a capture instance and stores it in an 
181    _ADAPTER structure.
182   \param AdapterObject Handle to the service control manager.
183   \return If the function succeeds, the return value is nonzero.
184
185   This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
186   call and set it in the _ADAPTER structure pointed by AdapterObject.
187 */
188
189 BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
190 {
191         DWORD BytesReturned;
192         WCHAR EventName[39];
193
194         // this tells the terminal service to retrieve the event from the global namespace
195         wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
196
197         // retrieve the name of the shared event from the driver
198         if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
199
200         EventName[20]=0; // terminate the string
201
202         // open the shared event
203         AdapterObject->ReadEvent=CreateEventW(NULL,
204                                                                                  TRUE,
205                                                                                  FALSE,
206                                                                                  EventName);
207
208         // in NT4 "Global\" is not automatically ignored: try to use simply the event name
209         if(GetLastError()!=ERROR_ALREADY_EXISTS){
210                 if(AdapterObject->ReadEvent != NULL)
211                         CloseHandle(AdapterObject->ReadEvent);
212                 
213                 // open the shared event
214                 AdapterObject->ReadEvent=CreateEventW(NULL,
215                         TRUE,
216                         FALSE,
217                         EventName+7);
218         }       
219
220         if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
221         ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
222                 return FALSE;
223         }
224
225         AdapterObject->ReadTimeOut=0;
226
227         return TRUE;
228
229 }
230
231 /*! 
232   \brief Installs the NPF device driver.
233   \param ascmHandle Handle to the service control manager.
234   \param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
235   \param driverPath The full path of the .sys file to load.
236   \return If the function succeeds, the return value is nonzero.
237
238   This function installs the driver's service in the system using the CreateService function.
239 */
240
241 BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
242 {
243         BOOL result = FALSE;
244         ULONG err;
245         
246         ODS("installdriver\n");
247         
248         if (GetFileAttributes(driverPath) != 0xffffffff) {
249                 *srvHandle = CreateService(ascmHandle, 
250                         NPFServiceName,
251                         NPFServiceDesc,
252                         SERVICE_ALL_ACCESS,
253                         SERVICE_KERNEL_DRIVER,
254                         SERVICE_DEMAND_START,
255                         SERVICE_ERROR_NORMAL,
256                         driverPath,
257                         NULL, NULL, NULL, NULL, NULL);
258                 if (*srvHandle == NULL) {
259                         if (GetLastError() == ERROR_SERVICE_EXISTS) {
260                                 //npf.sys already existed
261                                 result = TRUE;
262                         }
263                 } else {
264                         //Created service for npf.sys
265                         result = TRUE;
266                 }
267         }
268         if (result == TRUE) {
269                 if (*srvHandle != NULL) {
270                         CloseServiceHandle(*srvHandle);
271                 }
272         }
273
274         if (result == FALSE){
275                 err = GetLastError();
276                 if (err != 2) {
277                         ODSEx("PacketInstallDriver failed, Error=%d\n",err);
278                 }
279         }
280         return result;
281         
282 }
283
284 /*! 
285   \brief Convert a Unicode dotted-quad to a 32-bit IP address.
286   \param cp A string containing the address.
287   \return the converted 32-bit numeric address.
288
289    Doesn't check to make sure the address is valid.
290 */
291
292
293 ULONG inet_addrU(const WCHAR *cp)
294 {
295         ULONG val, part;
296         WCHAR c;
297         int i;
298
299         val = 0;
300         for (i = 0; i < 4; i++) {
301                 part = 0;
302                 while ((c = *cp++) != '\0' && c != '.') {
303                         if (c < '0' || c > '9')
304                                 return -1;
305                         part = part*10 + (c - '0');
306                 }
307                 if (part > 255)
308                         return -1;      
309                 val = val | (part << i*8);
310                 if (i == 3) {
311                         if (c != '\0')
312                                 return -1;      // extra gunk at end of string 
313                 } else {
314                         if (c == '\0')
315                                 return -1;      // string ends early 
316                 }
317         }
318         return val;
319 }
320
321 /*! 
322   \brief Dumps a registry key to disk in text format. Uses regedit.
323   \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
324   \param FileName Name of the file that will contain the dump.
325   \return If the function succeeds, the return value is nonzero.
326
327   For debugging purposes, we use this function to obtain some registry keys from the user's machine.
328 */
329
330 #ifdef _DEBUG_TO_FILE
331
332 LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
333 {
334         CHAR Command[256];
335
336         strcpy(Command, "regedit /e ");
337         strcat(Command, FileName);
338         strcat(Command, " ");
339         strcat(Command, KeyName);
340
341         /// Let regedit do the dirt work for us
342         system(Command);
343
344         return TRUE;
345 }
346 #endif
347
348 //---------------------------------------------------------------------------
349 // PUBLIC API
350 //---------------------------------------------------------------------------
351
352 /** @ingroup packetapi
353  *  @{
354  */
355
356 /** @defgroup packet32 Packet.dll exported functions and variables
357  *  @{
358  */
359
360 /// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
361 char PacketLibraryVersion[] = "2.3"; 
362
363 /*! 
364   \brief Returns a string with the dll version.
365   \return A char pointer to the version of the library.
366 */
367 PCHAR PacketGetVersion(){
368         return PacketLibraryVersion;
369 }
370
371 /*! 
372   \brief Returns information about the MAC type of an adapter.
373   \param AdapterObject The adapter on which information is needed.
374   \param type Pointer to a NetType structure that will be filled by the function.
375   \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
376
377   This function return the link layer technology and the speed (in bps) of an opened adapter.
378   The LinkType field of the type parameter can have one of the following values:
379
380   - NdisMedium802_3: Ethernet (802.3) 
381   - NdisMediumWan: WAN 
382   - NdisMedium802_5: Token Ring (802.5) 
383   - NdisMediumFddi: FDDI 
384   - NdisMediumAtm: ATM 
385   - NdisMediumArcnet878_2: ARCNET (878.2) 
386 */
387 BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
388 {
389     BOOLEAN    Status;
390     ULONG      IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
391     PPACKET_OID_DATA  OidData;
392
393     OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
394     if (OidData == NULL) {
395         ODS("PacketGetNetType failed\n");
396         return FALSE;
397     }
398         //get the link-layer type
399     OidData->Oid = OID_GEN_MEDIA_IN_USE;
400     OidData->Length = sizeof (ULONG);
401     Status = PacketRequest(AdapterObject,FALSE,OidData);
402     type->LinkType=*((UINT*)OidData->Data);
403
404         //get the link-layer speed
405     OidData->Oid = OID_GEN_LINK_SPEED;
406     OidData->Length = sizeof (ULONG);
407     Status = PacketRequest(AdapterObject,FALSE,OidData);
408         type->LinkSpeed=*((UINT*)OidData->Data)*100;
409     GlobalFreePtr (OidData);
410
411         ODSEx("Media:%d ",type->LinkType);
412         ODSEx("Speed=%d\n",type->LinkSpeed);
413
414     return Status;
415 }
416
417 /*! 
418   \brief Stops and unloads the WinPcap device driver.
419   \return If the function succeeds, the return value is nonzero, otherwise it is zero.
420
421   This function can be used to unload the driver from memory when the application no more needs it.
422   Note that the driver is physically stopped and unloaded only when all the files on its devices 
423   are closed, i.e. when all the applications that use WinPcap close all their adapters.
424 */
425 BOOL PacketStopDriver()
426 {
427         SC_HANDLE               scmHandle;
428     SC_HANDLE       schService;
429     BOOL            ret;
430     SERVICE_STATUS  serviceStatus;
431
432         scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
433         
434         if(scmHandle != NULL){
435                 
436                 schService = OpenService (scmHandle,
437                         NPFServiceName,
438                         SERVICE_ALL_ACCESS
439                         );
440                 
441                 if (schService != NULL)
442                 {
443                         
444                         ret = ControlService (schService,
445                                 SERVICE_CONTROL_STOP,
446                                 &serviceStatus
447                                 );
448                         if (!ret)
449                         {
450                         }
451                         
452                         CloseServiceHandle (schService);
453                         
454                         CloseServiceHandle(scmHandle);
455                         
456                         return ret;
457                 }
458         }
459         
460         return FALSE;
461
462 }
463
464 /*! 
465   \brief Opens an adapter.
466   \param AdapterName A string containing the name of the device to open. 
467    Use the PacketGetAdapterNames() function to retrieve the list of available devices.
468   \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
469    otherwise the return value is NULL.
470
471   This function tries to load and start the packet driver at the first invocation. In this way, 
472   the management of the driver is transparent to the application, that simply needs to open an adapter to start
473   WinPcap.
474   
475   \note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT 
476   version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE 
477   string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained 
478   through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format.
479   Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they 
480   use the ASCII format. Since this could be a relevant problem during the porting of command-line applications 
481   from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and
482   convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT 
483   accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE 
484   by PACKET.DLL before being passed to the driver.
485 */
486 LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
487 {
488     LPADAPTER lpAdapter;
489     BOOLEAN Result;
490         char *AdapterNameA;
491         WCHAR *AdapterNameU;
492         DWORD error;
493         SC_HANDLE svcHandle = NULL;
494         TCHAR driverPath[512];
495         TCHAR WinPath[256];
496         LONG KeyRes;
497         HKEY PathKey;
498         SERVICE_STATUS SStat;
499         BOOLEAN QuerySStat;
500         WCHAR SymbolicLink[128];
501
502     ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName);
503
504         scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
505         if(scmHandle == NULL){
506                 error = GetLastError();
507                 ODSEx("OpenSCManager failed! Error=%d\n", error);
508         } else {
509                 *driverPath = 0;
510                 GetCurrentDirectory(512, driverPath);
511                 wsprintf(driverPath + wcslen(driverPath), NPFDriverName);
512                 
513                 // check if the NPF registry key is already present
514                 // this means that the driver is already installed and that we don't need to call PacketInstallDriver
515                 KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
516                         NPFRegistryLocation,
517                         0,
518                         KEY_READ,
519                         &PathKey);
520                 
521                 if(KeyRes != ERROR_SUCCESS){
522                         Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
523                 } else {
524                         Result = TRUE;
525                         RegCloseKey(PathKey);
526                 }
527                 
528                 if (Result) {
529                         
530                         srvHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS );
531                         if (srvHandle != NULL){
532                                 
533                                 QuerySStat = QueryServiceStatus(srvHandle, &SStat);
534                                 ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
535                                 
536                                 if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
537                                         ODS("Calling startservice\n");
538                                         if (StartService(srvHandle, 0, NULL)==0){ 
539                                                 error = GetLastError();
540                                                 if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
541                                                         SetLastError(error);
542                                                         if (scmHandle != NULL) CloseServiceHandle(scmHandle);
543                                                         error = GetLastError();
544                                                         ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
545                                                         return NULL;
546                                                 }
547                                         }                               
548                                 }
549                         } else {
550                                 error = GetLastError();
551                                 ODSEx("OpenService failed! Error=%d", error);
552                         }
553                 } else {
554                         if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) {
555                                 return FALSE;
556                         }
557                         wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName);
558                         
559                         if (KeyRes != ERROR_SUCCESS) {
560                                 Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
561                         } else {
562                                 Result = TRUE;
563                         }
564                         if (Result) {
565                                 srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
566                                 if (srvHandle != NULL) {
567                                         QuerySStat = QueryServiceStatus(srvHandle, &SStat);
568                                         ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
569                                         if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) {
570                                                 ODS("Calling startservice\n");
571                                                 if (StartService(srvHandle, 0, NULL) == 0) { 
572                                                         error = GetLastError();
573                                                         if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) {
574                                                                 SetLastError(error);
575                                                                 if (scmHandle != NULL) CloseServiceHandle(scmHandle);
576                                                                 ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
577                                                                 return NULL;
578                                                         }
579                                                 }
580                                         }
581                                 } else {
582                                         error = GetLastError();
583                                         ODSEx("OpenService failed! Error=%d", error);
584                                 }
585                         }
586                 }
587         }
588     if (scmHandle != NULL) CloseServiceHandle(scmHandle);
589
590         AdapterNameA = (char*)AdapterName;
591         if (AdapterNameA[1] != 0) {  // ASCII
592                 AdapterNameU = SChar2WChar(AdapterNameA);
593                 AdapterName = AdapterNameU;
594         } else {                                 // Unicode
595                 AdapterNameU = NULL;
596         }
597         
598         lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
599         if (lpAdapter == NULL) {
600                 ODS("PacketOpenAdapter: GlobalAlloc Failed\n");
601                 error = GetLastError();
602                 if (AdapterNameU != NULL) free(AdapterNameU);
603                 //set the error to the one on which we failed
604                 SetLastError(error);
605             ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n");
606                 return NULL;
607         }
608         lpAdapter->NumWrites = 1;
609
610         wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]);
611         
612         // Copy  only the bytes that fit in the adapter structure.
613         // Note that lpAdapter->SymbolicLink is present for backward compatibility but will
614         // never be used by the apps
615         memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
616
617         //try if it is possible to open the adapter immediately
618         lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
619         
620         if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
621             ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink);
622                 if (PacketSetReadEvt(lpAdapter) == FALSE) {
623                         error = GetLastError();
624                         ODS("PacketOpenAdapter: Unable to open the read event\n");
625                         if (AdapterNameU != NULL)
626                                 free(AdapterNameU);
627                         GlobalFreePtr(lpAdapter);
628                         //set the error to the one on which we failed
629                         SetLastError(error);
630                     ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=%d\n",error);
631                         return NULL;
632                 }               
633                 
634                 PacketSetMaxLookaheadsize(lpAdapter);
635                 if (AdapterNameU != NULL)
636                     free(AdapterNameU);
637                 return lpAdapter;
638         }
639         //this is probably the first request on the packet driver. 
640         //We must create the dos device and set the access rights on it
641         else {
642                 Result = DefineDosDevice(DDD_RAW_TARGET_PATH,
643                                  &SymbolicLink[4],
644                                  AdapterName);
645                 if (Result) {
646
647                     ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink);
648                         
649                         lpAdapter->hFile = CreateFile(
650                                  SymbolicLink,
651                                  GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
652                         if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {         
653                                 if (PacketSetReadEvt(lpAdapter) == FALSE) {
654                                         error = GetLastError();
655                                         ODS("PacketOpenAdapter: Unable to open the read event\n");
656                                         if (AdapterNameU != NULL)
657                                                 free(AdapterNameU);
658                                         GlobalFreePtr(lpAdapter);
659                                         //set the error to the one on which we failed
660                                         SetLastError(error);
661                                     ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error);
662                                         return NULL;                                    
663                                 }
664                                 PacketSetMaxLookaheadsize(lpAdapter);
665                                 if (AdapterNameU != NULL)
666                                     free(AdapterNameU);
667                                 return lpAdapter;
668                         } else {
669                     ODS("PacketOpenAdapter: CreateFile failed\n");
670                         }
671                 } else {
672             ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]);
673                 }
674         }
675         error = GetLastError();
676         if (AdapterNameU != NULL)
677             free(AdapterNameU);
678         GlobalFreePtr(lpAdapter);
679         //set the error to the one on which we failed
680         SetLastError(error);
681     ODSEx("PacketOpenAdapter: CreateFile failed, Error=2,%d\n",error);
682         return NULL;
683
684 }
685
686 /*! 
687   \brief Closes an adapter.
688   \param lpAdapter the pointer to the adapter to close. 
689
690   PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
691 */
692 VOID PacketCloseAdapter(LPADAPTER lpAdapter)
693 {
694     CloseHandle(lpAdapter->hFile);
695         SetEvent(lpAdapter->ReadEvent);
696     CloseHandle(lpAdapter->ReadEvent);
697     GlobalFreePtr(lpAdapter);
698 }
699
700 /*! 
701   \brief Allocates a _PACKET structure.
702   \return On succeess, the return value is the pointer to a _PACKET structure otherwise the 
703    return value is NULL.
704
705   The structure returned will be passed to the PacketReceivePacket() function to receive the
706   packets from the driver.
707
708   \warning The Buffer field of the _PACKET structure is not set by this function. 
709   The buffer \b must be allocated by the application, and associated to the PACKET structure 
710   with a call to PacketInitPacket.
711 */
712 LPPACKET PacketAllocatePacket(void)
713 {
714
715     LPPACKET lpPacket;
716     lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
717     if (lpPacket == NULL) {
718         ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
719         return NULL;
720     }
721     return lpPacket;
722 }
723
724 /*! 
725   \brief Frees a _PACKET structure.
726   \param lpPacket The structure to free. 
727
728   \warning the user-allocated buffer associated with the _PACKET structure is not deallocated 
729   by this function and \b must be explicitly deallocated by the programmer.
730
731 */
732 VOID PacketFreePacket(LPPACKET lpPacket)
733 {
734     GlobalFreePtr(lpPacket);
735 }
736
737 /*! 
738   \brief Initializes a _PACKET structure.
739   \param lpPacket The structure to initialize. 
740   \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
741   \param Length the length of the buffer. This is the maximum buffer size that will be 
742    transferred from the driver to the application using a single read.
743
744   \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly 
745   influence the performance of the capture process, since this buffer will contain the packets received
746   from the the driver. The driver is able to return several packets using a single read call 
747   (see the PacketReceivePacket() function for details), and the number of packets transferable to the 
748   application in a call is limited only by the size of the buffer associated with the PACKET structure
749   passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably 
750   decrease the number of system calls, reducing the impcat of the capture process on the processor.
751 */
752
753 VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
754 {
755     lpPacket->Buffer = Buffer;
756     lpPacket->Length = Length;
757         lpPacket->ulBytesReceived = 0;
758         lpPacket->bIoComplete = FALSE;
759 }
760
761 /*! 
762   \brief Read data (packets or statistics) from the NPF driver.
763   \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which 
764    the data is received.
765   \param lpPacket Pointer to a PACKET structure that will contain the data.
766   \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with 
767    older applications.
768   \return If the function succeeds, the return value is nonzero.
769
770   The data received with this function can be a group of packets or a static on the network traffic, 
771   depending on the working mode of the driver. The working mode can be set with the PacketSetMode() 
772   function. Give a look at that function if you are interested in the format used to return statistics 
773   values, here only the normal capture mode will be described.
774
775   The number of packets received with this function is variable. It depends on the number of packets 
776   currently stored in the driver\92s buffer, on the size of these packets and on the size of the buffer 
777   associated to the lpPacket parameter. The following figure shows the format used by the driver to pass 
778   packets to the application. 
779
780   \image html encoding.gif "method used to encode the packets"
781
782   Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
783   that structure is updated with the amount of data copied in the buffer. Each packet has a header
784   consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field 
785   is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen 
786   and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer. 
787   
788   Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
789   in the developer's pack, or in the pcap_read() function of wpcap.
790 */
791 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
792 {
793         BOOLEAN res;
794         if ((int)AdapterObject->ReadTimeOut != -1)
795                 WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
796     res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
797         return res;
798 }
799
800 /*! 
801   \brief Sends one (or more) copies of a packet to the network.
802   \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will 
803    send the packets.
804   \param lpPacket Pointer to a PACKET structure with the packet to send.
805   \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with 
806    older applications.
807   \return If the function succeeds, the return value is nonzero.
808
809   This function is used to send a raw packet to the network. 'Raw packet' means that the programmer 
810   will have to include the protocol headers, since the packet is sent to the network 'as is'. 
811   The CRC needs not to be calculated and put at the end of the packet, because it will be transparently 
812   added by the network interface.
813
814   The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
815   it is possible to change the number of times a single write must be repeated. The default is 1, 
816   i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
817   greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on 
818   the network. This feature mitigates the overhead of the context switches and therefore can be used to generate 
819   high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need 
820   to obtain high network loads.
821   The optimized sending process is still limited to one packet at a time: for the moment it cannot be used 
822   to send a buffer with multiple packets.
823
824   \note The ability to write multiple packets is currently present only in the Windows NTx version of the 
825   packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
826   that uses the multiple write method will run in Windows 9x as well, but its performance will be very low 
827   compared to the one of WindowsNTx.
828 */
829 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
830 {
831     DWORD BytesTransfered;
832     return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
833 }
834
835
836 /*! 
837   \brief Sends a buffer of packets to the network.
838   \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will 
839    send the packets.
840   \param PacketBuff Pointer to buffer with the packets to send.
841   \param Size Size of the buffer pointed by the PacketBuff argument.
842   \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
843          fast as possible
844   \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
845           error occurred during the send. The error can be caused by a driver/adapter problem or by an
846                   inconsistent/bogus packet buffer.
847
848   This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
849   number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
850   by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
851   'Raw packets' means that the sending application will have to include the protocol headers, since every packet 
852   is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be 
853   transparently added by the network interface.
854
855   \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
856   buffered in the kernel driver, so the number of context switches is reduced.
857
858   \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
859   This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
860   (depending on the precision of the performance counter of the machine). Such a precision cannot be reached 
861   sending the packets separately with PacketSendPacket().
862 */
863 INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
864 {
865     BOOLEAN                     Res;
866     DWORD                       BytesTransfered, TotBytesTransfered=0;
867         struct timeval  BufStartTime;
868         LARGE_INTEGER   StartTicks, CurTicks, TargetTicks, TimeFreq;
869
870
871         ODS("PacketSendPackets");
872
873         // Obtain starting timestamp of the buffer
874         BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
875         BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
876
877         // Retrieve the reference time counters
878         QueryPerformanceCounter(&StartTicks);
879         QueryPerformanceFrequency(&TimeFreq);
880
881         CurTicks.QuadPart = StartTicks.QuadPart;
882
883         do{
884                 // Send the data to the driver
885                 Res = DeviceIoControl(AdapterObject->hFile,
886                         (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
887                         (PCHAR)PacketBuff + TotBytesTransfered,
888                         Size - TotBytesTransfered,
889                         NULL,
890                         0,
891                         &BytesTransfered,
892                         NULL);
893
894                 TotBytesTransfered += BytesTransfered;
895
896                 // calculate the time interval to wait before sending the next packet
897                 TargetTicks.QuadPart = StartTicks.QuadPart +
898                 (LONGLONG)
899                 ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
900                 (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
901                 (TimeFreq.QuadPart) / 1000000;
902
903                 // Exit from the loop on termination or error
904                 if(TotBytesTransfered >= Size || Res != TRUE)
905                         break;
906                 
907                 // Wait until the time interval has elapsed
908                 while( CurTicks.QuadPart <= TargetTicks.QuadPart )
909                         QueryPerformanceCounter(&CurTicks);
910
911         }
912         while(TRUE);
913
914         return TotBytesTransfered;
915 }
916
917 /*! 
918   \brief Defines the minimum amount of data that will be received in a read.
919   \param AdapterObject Pointer to an _ADAPTER structure
920   \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
921    release a read on this adapter.
922   \return If the function succeeds, the return value is nonzero.
923
924   In presence of a large value for nbytes, the kernel waits for the arrival of several packets before 
925   copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, 
926   i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value 
927   means that the kernel will copy the packets as soon as the application is ready to receive them. This is 
928   suggested for real time applications (like, for example, a bridge) that need the better responsiveness from 
929   the kernel.
930
931   \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer 
932   this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
933 */
934
935 BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
936 {
937         DWORD BytesReturned;
938     return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
939 }
940
941 /*!
942   \brief Sets the working mode of an adapter.
943   \param AdapterObject Pointer to an _ADAPTER structure.
944   \param mode The new working mode of the adapter.
945   \return If the function succeeds, the return value is nonzero.
946
947   The device driver of WinPcap has 4 working modes:
948   - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
949    to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
950   - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
951    precise intervals, statics values on the network traffic. The interval between the statistic samples is 
952    by default 1 second but it can be set to any other value (with a 1 ms precision) with the 
953    PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
954    mode is shown in the following figure:<p>
955          \image html stats.gif "data structure returned by statistical mode"
956    Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter 
957    previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are 
958    encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a 
959    very low impact on system performance compared to capture mode. 
960   - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
961    method is much faster than saving the packets after having captured them. No data is returned 
962    by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
963    this filter are dumped to disk.
964   - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap 
965    format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the 
966    network traffic and on the amount of data saved to file, in a way similar to statistical mode.
967    The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in 
968    the following figure:<p>   
969          \image html dump.gif "data structure returned by statistical dump mode"
970    Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the 
971    effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are 
972    dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly 
973    by wpcap.
974    Look at the NetMeter example in the 
975    WinPcap developer's pack to see how to use statistics mode.
976 */
977 BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
978 {
979         DWORD BytesReturned;
980     return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
981 }
982
983 /*!
984   \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
985   \param AdapterObject Pointer to an _ADAPTER structure.
986   \param name the file name, in ASCII or UNICODE.
987   \param len the length of the buffer containing the name, in bytes.
988   \return If the function succeeds, the return value is nonzero.
989
990   This function defines the file name that the driver will open to store the packets on disk when 
991   it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
992   called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
993   If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver 
994   closes the old file and opens the new one.
995 */
996
997 BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
998 {
999         DWORD           BytesReturned;
1000         WCHAR   *FileName;
1001         BOOLEAN res;
1002         WCHAR   NameWithPath[1024];
1003         int             TStrLen;
1004         WCHAR   *NamePos;
1005
1006         if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
1007                 FileName=SChar2WChar(name);
1008                 len*=2;
1009         } 
1010         else {  //Unicode
1011                 FileName=name;
1012         }
1013
1014         TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
1015
1016         len=TStrLen*2+2;  //add the terminating null character
1017
1018         // Try to catch malformed strings
1019         if(len>2048){
1020                 if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
1021                 return FALSE;
1022         }
1023
1024     res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
1025         free(FileName);
1026         return res;
1027 }
1028
1029 /*!
1030   \brief Set the dump mode limits.
1031   \param AdapterObject Pointer to an _ADAPTER structure.
1032   \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
1033   \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
1034   \return If the function succeeds, the return value is nonzero.
1035
1036   This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
1037   is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
1038   very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
1039   the first of the two is reached.
1040
1041   \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush 
1042   correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
1043 */
1044 BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
1045 {
1046         DWORD           BytesReturned;
1047         UINT valbuff[2];
1048
1049         valbuff[0] = maxfilesize;
1050         valbuff[1] = maxnpacks;
1051
1052     return DeviceIoControl(AdapterObject->hFile,
1053                 pBIOCSETDUMPLIMITS,
1054                 valbuff,
1055                 sizeof valbuff,
1056                 NULL,
1057                 0,
1058                 &BytesReturned,
1059                 NULL);  
1060 }
1061
1062 /*!
1063   \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
1064   \param AdapterObject Pointer to an _ADAPTER structure.
1065   \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
1066   \return TRUE if the dump is ended, FALSE otherwise.
1067
1068   PacketIsDumpEnded() informs the user about the limits that were set with a previous call to 
1069   PacketSetDumpLimits().
1070
1071   \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits 
1072   (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
1073   block the application on this call forever.
1074 */
1075 BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
1076 {
1077         DWORD           BytesReturned;
1078         int             IsDumpEnded;
1079         BOOLEAN res;
1080
1081         if(sync)
1082                 WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
1083
1084     res = DeviceIoControl(AdapterObject->hFile,
1085                 pBIOCISDUMPENDED,
1086                 NULL,
1087                 0,
1088                 &IsDumpEnded,
1089                 4,
1090                 &BytesReturned,
1091                 NULL);
1092
1093         if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
1094
1095         return (BOOLEAN)IsDumpEnded;
1096 }
1097
1098 /*!
1099   \brief Returns the notification event associated with the read calls on an adapter.
1100   \param AdapterObject Pointer to an _ADAPTER structure.
1101   \return The handle of the event that the driver signals when some data is available in the kernel buffer.
1102
1103   The event returned by this function is signaled by the driver if:
1104   - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal 
1105   than the one set with the PacketSetMinToCopy() function is received from the network.
1106   - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
1107    but the the timeout set with the PacketSetReadTimeout() function has elapsed.
1108   - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the 
1109    PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
1110
1111   In every case, a call to PacketReceivePacket() will return immediately.
1112   The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects) 
1113   to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that 
1114   need to wait concurrently on several events.
1115
1116 */
1117 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
1118 {
1119     return AdapterObject->ReadEvent;
1120 }
1121
1122 /*!
1123   \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
1124   \param AdapterObject Pointer to an _ADAPTER structure.
1125   \param nwrites Number of copies of a packet that will be physically sent by the interface.
1126   \return If the function succeeds, the return value is nonzero.
1127
1128         See PacketSendPacket() for details.
1129 */
1130 BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
1131 {
1132         DWORD BytesReturned;
1133     return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
1134 }
1135
1136 /*!
1137   \brief Sets the timeout after which a read on an adapter returns.
1138   \param AdapterObject Pointer to an _ADAPTER structure.
1139   \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on 
1140   the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver. 
1141   Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.  
1142   A timeout of -1 causes PacketReceivePacket() to always return immediately.
1143   \return If the function succeeds, the return value is nonzero.
1144
1145   \note This function works also if the adapter is working in statistics mode, and can be used to set the 
1146   time interval between two statistic reports.
1147 */
1148 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
1149 {
1150         DWORD BytesReturned;
1151         int DriverTimeOut=-1;
1152
1153         AdapterObject->ReadTimeOut=timeout;
1154
1155     return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
1156 }
1157
1158 /*!
1159   \brief Sets the size of the kernel-level buffer associated with a capture.
1160   \param AdapterObject Pointer to an _ADAPTER structure.
1161   \param dim New size of the buffer, in \b kilobytes.
1162   \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to 
1163    allocate the new buffer.
1164
1165   When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are 
1166   lost. 
1167   
1168   Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
1169   An adequate buffer in the driver is able to keep the packets while the application is busy, compensating 
1170   the delays of the application and avoiding the loss of packets during bursts or high network activity. 
1171   The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to 
1172   set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
1173 */
1174 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
1175 {
1176         DWORD BytesReturned;
1177     return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
1178 }
1179
1180 /*!
1181   \brief Sets a kernel-level packet filter.
1182   \param AdapterObject Pointer to an _ADAPTER structure.
1183   \param fp Pointer to a filtering program that will be associated with this capture or monitoring 
1184   instance and that will be executed on every incoming packet.
1185   \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs 
1186    or if the filter program is not accepted after a safeness check by the driver.  The driver performs 
1187    the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
1188    conformat filters.
1189
1190   This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a 
1191   set of bpf_insn instructions.
1192
1193   A filter can be automatically created by using the pcap_compile() function of wpcap. This function 
1194   converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at 
1195   http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but 
1196   you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd 
1197   flags to obtain the pseudocode.
1198
1199 */
1200 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp)
1201 {
1202         DWORD BytesReturned;
1203     return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
1204 }
1205
1206 /*!
1207   \brief Returns a couple of statistic values about the current capture session.
1208   \param AdapterObject Pointer to an _ADAPTER structure.
1209   \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1210   \return If the function succeeds, the return value is nonzero.
1211
1212   With this function, the programmer can know the value of two internal variables of the driver:
1213
1214   - the number of packets that have been received by the adapter AdapterObject, starting at the 
1215    time in which it was opened with PacketOpenAdapter. 
1216   - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
1217    buffer associated with the adapter is full. 
1218 */
1219 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
1220 {
1221         BOOLEAN Res;
1222         DWORD BytesReturned;
1223         struct bpf_stat tmpstat;        // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1224
1225         Res = DeviceIoControl(AdapterObject->hFile,
1226                 pBIOCGSTATS,
1227                 NULL,
1228                 0,
1229                 &tmpstat,
1230                 sizeof(struct bpf_stat),
1231                 &BytesReturned,
1232                 NULL);
1233
1234         // Copy only the first two values retrieved from the driver
1235         s->bs_recv = tmpstat.bs_recv;
1236         s->bs_drop = tmpstat.bs_drop;
1237
1238         return Res;
1239 }
1240
1241 /*!
1242   \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
1243   \param AdapterObject Pointer to an _ADAPTER structure.
1244   \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
1245   \return If the function succeeds, the return value is nonzero.
1246
1247   With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
1248
1249   - the number of drops by interface (not yet supported, always 0). 
1250   - the number of packets that reached the application, i.e that were accepted by the kernel filter and
1251   that fitted in the kernel buffer. 
1252 */
1253 BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
1254 {
1255         BOOLEAN Res;
1256         DWORD BytesReturned;
1257         struct bpf_stat tmpstat;        // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
1258
1259         Res = DeviceIoControl(AdapterObject->hFile,
1260                 pBIOCGSTATS,
1261                 NULL,
1262                 0,
1263                 &tmpstat,
1264                 sizeof(struct bpf_stat),
1265                 &BytesReturned,
1266                 NULL);
1267
1268         s->bs_recv = tmpstat.bs_recv;
1269         s->bs_drop = tmpstat.bs_drop;
1270         s->ps_ifdrop = tmpstat.ps_ifdrop;
1271         s->bs_capt = tmpstat.bs_capt;
1272
1273         return Res;
1274 }
1275
1276 /*!
1277   \brief Performs a query/set operation on an internal variable of the network card driver.
1278   \param AdapterObject Pointer to an _ADAPTER structure.
1279   \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
1280   \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
1281   \return If the function succeeds, the return value is nonzero.
1282
1283   \note not all the network adapters implement all the query/set functions. There is a set of mandatory 
1284   OID functions that is granted to be present on all the adapters, and a set of facultative functions, not 
1285   provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a 
1286   facultative function, be careful to enclose it in an if statement to check the result.
1287 */
1288 BOOLEAN PacketRequest(LPADAPTER  AdapterObject,BOOLEAN Set,PPACKET_OID_DATA  OidData)
1289 {
1290         DWORD BytesReturned;
1291     BOOLEAN Result;
1292
1293     Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? pBIOCSETOID : pBIOCQUERYOID,
1294                            OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
1295                            sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);
1296     
1297         // output some debug info
1298         ODSEx("PacketRequest, OID=%d ", OidData->Oid);
1299     ODSEx("Length=%d ", OidData->Length);
1300     ODSEx("Set=%d ", Set);
1301     ODSEx("Res=%d\n", Result);
1302
1303         return Result;
1304 }
1305
1306 /*!
1307   \brief Sets a hardware filter on the incoming packets.
1308   \param AdapterObject Pointer to an _ADAPTER structure.
1309   \param Filter The identifier of the filter.
1310   \return If the function succeeds, the return value is nonzero.
1311
1312   The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
1313   device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
1314
1315   - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter. 
1316   - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted. 
1317   - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted. 
1318   - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted. 
1319   - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted. 
1320   - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST 
1321 */
1322 BOOLEAN PacketSetHwFilter(LPADAPTER  AdapterObject,ULONG Filter)
1323 {
1324     BOOLEAN    Status;
1325     ULONG      IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
1326     PPACKET_OID_DATA  OidData;
1327
1328     OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
1329     if (OidData == NULL) {
1330         ODS("PacketSetHwFilter: GlobalAlloc Failed\n");
1331         return FALSE;
1332     }
1333     OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
1334     OidData->Length=sizeof(ULONG);
1335     *((PULONG)OidData->Data)=Filter;
1336     Status=PacketRequest(AdapterObject,TRUE,OidData);
1337     GlobalFreePtr(OidData);
1338     return Status;
1339 }
1340
1341 /*!
1342   \brief Retrieve the list of available network adapters and their description.
1343   \param pStr User allocated string that will be filled with the names of the adapters.
1344   \param BufferSize Length of the buffer pointed by pStr.
1345   \return If the function succeeds, the return value is nonzero.
1346
1347   Usually, this is the first function that should be used to communicate with the driver.
1348   It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>. 
1349   After the names of the adapters, pStr contains a string that describes each of them.
1350
1351   \b Warning: 
1352   the result of this function is obtained querying the registry, therefore the format 
1353   of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII
1354   encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames 
1355   in Windows 95x, pStr contains, in succession:
1356   - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
1357   - a double "\0"
1358   - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number 
1359    of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
1360    so on.
1361   - a double "\0". 
1362
1363   In Windows NTx, pStr contains: the names of the adapters, in UNICODE format, separated by a single UNICODE "\0" (i.e. 2 ASCII "\0"), a double UNICODE "\0", followed by the descriptions of the adapters, in ASCII format, separated by a single ASCII "\0" . The string is terminated by a double ASCII "\0".
1364   - a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0"
1365   - a double UNICODE "\0"
1366   - a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0".
1367   - a double ASCII "\0". 
1368 */
1369
1370 BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)
1371 {
1372     HKEY       LinkageKey, AdapKey;
1373         DWORD      RegKeySize = 0;
1374     LONG       Status;
1375         ULONG      Result;
1376         PTSTR      BpStr;
1377         char       *TTpStr;
1378         char       *DpStr;
1379         char       *DescBuf;
1380         LPADAPTER  adapter;
1381     PPACKET_OID_DATA OidData;
1382         int                i = 0, k, rewind;
1383     DWORD      dim;
1384         TCHAR      AdapName[256];
1385
1386     ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize);
1387
1388     OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512);
1389     if (OidData == NULL) {
1390         ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1391         return FALSE;
1392     }
1393
1394     Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1395                                   TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
1396                                                   0, KEY_READ, &AdapKey);
1397
1398         // Get the size to allocate for the original device names
1399         while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1400                 Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey);
1401                 Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey);
1402         Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim);
1403                 i++;
1404                 if (Status!=ERROR_SUCCESS) continue;
1405                 RegKeySize += dim;
1406         }
1407         
1408         // Allocate the memory for the original device names
1409         ODSEx("Need %d bytes for the names\n", RegKeySize+2);
1410         BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
1411         if (BpStr == NULL || RegKeySize > *BufferSize) {
1412         ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
1413                 GlobalFreePtr(OidData);
1414                 return FALSE;
1415         }
1416         k = 0;
1417         i = 0;
1418
1419     ODS("PacketGetAdapterNames: Cycling through the adapters:\n");
1420
1421         // Copy the names to the buffer
1422         while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
1423                 WCHAR UpperBindStr[64];
1424
1425                 i++;
1426                 ODSEx(" %d) ", i);
1427
1428                 Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
1429                 Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
1430
1431                 dim=sizeof(UpperBindStr);
1432         Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
1433                 
1434                 ODSEx("UpperBind=%S ", UpperBindStr);
1435
1436                 if( Status!=ERROR_SUCCESS || _wcsicmp(UpperBindStr,L"NdisWan")==0 ){
1437                         ODS("Name = SKIPPED\n");
1438                         continue;
1439                 }
1440
1441                 dim=RegKeySize-k;
1442         Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
1443                 if(Status!=ERROR_SUCCESS){
1444                         ODS("Name = SKIPPED (error reading the key)\n");
1445                         continue;
1446                 }
1447
1448                 ODSEx("Name = %S\n", (LPBYTE)BpStr+k);
1449
1450                 k+=dim-2;
1451         }
1452
1453         CloseHandle(AdapKey);
1454
1455 #ifdef _DEBUG_TO_FILE
1456         //dump BpStr for debug purposes
1457         ODS("Dumping BpStr:");
1458         {
1459                 FILE *f;
1460                 f = fopen("winpcap_debug.txt", "a");
1461                 for(i=0;i<k;i++){
1462                         if(!(i%32))fprintf(f, "\n ");
1463                         fprintf(f, "%c " , *((LPBYTE)BpStr+i));
1464                 }
1465                 fclose(f);
1466         }
1467         ODS("\n");
1468 #endif
1469
1470         
1471         if (k != 0){
1472                 
1473                 DescBuf=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1474                 if (DescBuf == NULL) {
1475                         GlobalFreePtr (BpStr);
1476                     GlobalFreePtr(OidData);
1477                         return FALSE;
1478                 }
1479                 DpStr=DescBuf;
1480                                 
1481                 for(i=0,k=0;BpStr[i]!=0 || BpStr[i+1]!=0;){
1482                         
1483                         if(k+wcslen(BpStr+i)+30 > *BufferSize){
1484                                 // Input buffer too small
1485                             GlobalFreePtr(OidData);
1486                                 GlobalFreePtr (BpStr);
1487                                 GlobalFreePtr (DescBuf);
1488                                 ODS("PacketGetAdapterNames: Input buffer too small!\n");
1489                                 return FALSE;
1490                         }
1491
1492                         // Create the device name
1493                         rewind=k;
1494                         memcpy(pStr+k,BpStr+i,16);
1495                         memcpy(pStr+k+8,TEXT("NPF_"),8);
1496                         i+=8;
1497                         k+=12;
1498                         while(BpStr[i-1]!=0){
1499                                 pStr[k++]=BpStr[i++];
1500                         }
1501
1502                         // Open the adapter
1503                         adapter=PacketOpenAdapter(pStr+rewind);
1504                         if(adapter==NULL){
1505                                 k=rewind;
1506                                 continue;
1507                         }
1508
1509                         // Retrieve the description
1510                         OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1511                         OidData->Length = 256;
1512                         ZeroMemory(OidData->Data,256);
1513                         Status = PacketRequest(adapter,FALSE,OidData);
1514                         if(Status==0 || ((char*)OidData->Data)[0]==0){
1515                                 k=rewind;
1516                                 continue;
1517                         }
1518
1519                         ODSEx("Adapter Description=%s\n\n",OidData->Data);
1520
1521                         // Copy the description
1522                         TTpStr=(char*)(OidData->Data);
1523                         while(*TTpStr!=0){
1524                                 *DpStr++=*TTpStr++;
1525                         }
1526                         *DpStr++=*TTpStr++;
1527                         
1528                         // Close the adapter
1529                         PacketCloseAdapter(adapter);
1530                         
1531                 }
1532                 *DpStr = 0;
1533
1534                 pStr[k++] = 0;
1535                 pStr[k] = 0;
1536
1537                 if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1538                         memcpy(pStr + k, DescBuf, DpStr - DescBuf);
1539                 } else {
1540                     GlobalFreePtr(OidData);
1541                         GlobalFreePtr(BpStr);
1542                         GlobalFreePtr(DescBuf);
1543                         ODS("\nPacketGetAdapterNames: ended with failure\n");
1544                         return FALSE;
1545                 }
1546
1547             GlobalFreePtr(OidData);
1548                 GlobalFreePtr(BpStr);
1549                 GlobalFreePtr(DescBuf);
1550                 ODS("\nPacketGetAdapterNames: ended correctly\n");
1551                 return TRUE;
1552         }
1553         else{
1554             DWORD RegType;
1555
1556                 ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n");
1557
1558                 GlobalFreePtr(BpStr);
1559                 Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1560                                                 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"),
1561                                                 0, KEY_READ, &LinkageKey);
1562                 if (Status == ERROR_SUCCESS) {
1563                         // Retrieve the length of the key
1564                         Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize);
1565                         // Allocate the buffer
1566                         BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2);
1567                         if (BpStr == NULL || RegKeySize > *BufferSize) {
1568                                 GlobalFreePtr(OidData);
1569                                 return FALSE;
1570                         }
1571                         Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize);
1572                         RegCloseKey(LinkageKey);
1573                 } else {
1574             //ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n");
1575             ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n");
1576                 }
1577                 if (Status == ERROR_SUCCESS) {
1578                         DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
1579                         if (DescBuf == NULL) {
1580                                 GlobalFreePtr(BpStr);
1581                                 GlobalFreePtr(OidData);
1582                                 return FALSE;
1583                         }
1584                         DpStr = DescBuf;
1585                         for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) {
1586                                 if (k + wcslen(BpStr + i) + 30 > *BufferSize) {
1587                                         // Input buffer too small
1588                                         GlobalFreePtr(OidData);
1589                                         GlobalFreePtr(BpStr);
1590                                         GlobalFreePtr(DescBuf);
1591                                         return FALSE;
1592                                 }
1593
1594                                 ODS("\tCreating a device name - started.\n");
1595
1596                                 // Create the device name
1597                                 rewind = k;
1598                                 memcpy(pStr + k,BpStr + i,16);
1599                                 memcpy(pStr + k + 8, TEXT("NPF_"), 8);
1600                                 i += 8;
1601                                 k += 12;
1602                                 while (BpStr[i - 1] != 0) {
1603                                         pStr[k++] = BpStr[i++];
1604                                 }
1605                                 // Open the adapter
1606                                 adapter = PacketOpenAdapter(pStr+rewind);
1607                                 if (adapter == NULL) {
1608                                         k = rewind;
1609                                         continue;
1610                                 }
1611                                 // Retrieve the description
1612                                 OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
1613                                 OidData->Length = 256;
1614                                 Status = PacketRequest(adapter, FALSE, OidData);
1615                                 if (Status == 0 || ((char*)OidData->Data)[0] == 0) {
1616                                         k = rewind;
1617                                 ODS("\tCreating a device name - Retrieve the description.\n");
1618                                         continue;
1619                                 }
1620                                 
1621                                 // Copy the description
1622                                 TTpStr = (char*)(OidData->Data);
1623                                 while (*TTpStr != 0){
1624                                         *DpStr++ = *TTpStr++;
1625                                 }
1626                                 *DpStr++ = *TTpStr++;
1627                                 // Close the adapter
1628                                 PacketCloseAdapter(adapter);
1629
1630                                 ODS("\tCreating a device name - completed.\n");
1631                         }
1632                         *DpStr = 0;
1633                         
1634                         pStr[k++] = 0;
1635                         pStr[k] = 0;
1636                         
1637                         if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
1638                                 memcpy(pStr + k, DescBuf, DpStr-DescBuf);
1639                         } else {
1640                                 GlobalFreePtr(OidData);
1641                                 GlobalFreePtr(BpStr);
1642                                 GlobalFreePtr(DescBuf);
1643                                 return FALSE;
1644                         }
1645                         
1646                         GlobalFreePtr(OidData);
1647                         GlobalFreePtr(BpStr);
1648                         GlobalFreePtr(DescBuf);
1649                         ODS("PacketGetAdapterNames() returning TRUE\n");
1650                         return TRUE;
1651                 } else {
1652                         MessageBox(NULL,TEXT("Can not find TCP/IP bindings.\nIn order to run the packet capture driver you must install TCP/IP."),szWindowTitle,MB_OK);
1653                         ODS("Cannot find the TCP/IP bindings\n");
1654                         return FALSE;
1655                 }
1656         }
1657 }
1658
1659 /*!
1660   \brief Returns comprehensive information the addresses of an adapter.
1661   \param AdapterName String that contain _ADAPTER structure.
1662   \param buffer A user allocated array of npf_if_addr that will be filled by the function.
1663   \param NEntries Size of the array (in npf_if_addr).
1664   \return If the function succeeds, the return value is nonzero.
1665
1666   This function grabs from the registry information like the IP addresses, the netmasks 
1667   and the broadcast addresses of an interface. The buffer passed by the user is filled with 
1668   npf_if_addr structures, each of which contains the data for a single address. If the buffer
1669   is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
1670   if you want only the first address.
1671 */
1672
1673 BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
1674 {
1675         char    *AdapterNameA;
1676         WCHAR   *AdapterNameU;
1677         WCHAR   *ifname;
1678         HKEY    SystemKey;
1679         HKEY    InterfaceKey;
1680         HKEY    ParametersKey;
1681         HKEY    TcpIpKey;
1682         HKEY    UnderTcpKey;
1683         LONG    status;
1684         WCHAR   String[1024+1];
1685         DWORD   RegType;
1686         ULONG   BufLen;
1687         DWORD   DHCPEnabled;
1688         struct  sockaddr_in *TmpAddr, *TmpBroad;
1689         LONG    naddrs,nmasks,StringPos;
1690         DWORD   ZeroBroadcast;
1691
1692         AdapterNameA = (char*)AdapterName;
1693         if(AdapterNameA[1] != 0) {      //ASCII
1694                 AdapterNameU = SChar2WChar(AdapterNameA);
1695                 AdapterName = AdapterNameU;
1696         } else {                                //Unicode
1697                 AdapterNameU = NULL;
1698         }
1699     ifname = wcsrchr(AdapterName, '\\');
1700         if (ifname == NULL)
1701                 ifname = AdapterName;
1702         else
1703                 ifname++;
1704         if (wcsncmp(ifname, L"NPF_", 4) == 0)
1705                 ifname += 4;
1706
1707         if(     RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
1708                                                 TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"),
1709                                                 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
1710         {
1711                 status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
1712                 if (status != ERROR_SUCCESS) {
1713                         RegCloseKey(UnderTcpKey);
1714                         goto fail;
1715                 }
1716         }
1717         else
1718         {
1719                 
1720                 // Query the registry key with the interface's adresses
1721                 status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1722                                                 TEXT("SYSTEM\\ControlSet001\\Services"),
1723                                                 0,KEY_READ,&SystemKey);
1724                 if (status != ERROR_SUCCESS)
1725                         goto fail;
1726                 status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1727                 if (status != ERROR_SUCCESS) {
1728                         RegCloseKey(SystemKey);
1729                         goto fail;
1730                 }
1731                 RegCloseKey(SystemKey);
1732                 status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1733                 if (status != ERROR_SUCCESS) {
1734                         RegCloseKey(InterfaceKey);
1735                         goto fail;
1736                 }
1737                 RegCloseKey(InterfaceKey);
1738                 status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1739                 if (status != ERROR_SUCCESS) {
1740                         RegCloseKey(ParametersKey);
1741                         goto fail;
1742                 }
1743                 RegCloseKey(ParametersKey);
1744                 BufLen = sizeof String;
1745         }
1746
1747         BufLen = 4;
1748         /* Try to detect if the interface has a zero broadcast addr */
1749         status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen);
1750         if (status != ERROR_SUCCESS)
1751                 ZeroBroadcast=0;
1752         
1753         BufLen = 4;
1754         /* See if DHCP is used by this system */
1755         status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1756         if (status != ERROR_SUCCESS)
1757                 DHCPEnabled=0;
1758         
1759         
1760         /* Retrieve the adrresses */
1761         if(DHCPEnabled){
1762                 
1763                 BufLen = sizeof String;
1764                 // Open the key with the addresses
1765                 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1766                 if (status != ERROR_SUCCESS) {
1767                         RegCloseKey(TcpIpKey);
1768                         goto fail;
1769                 }
1770
1771                 // scan the key to obtain the addresses
1772                 StringPos = 0;
1773                 for(naddrs = 0;naddrs <* NEntries;naddrs++){
1774                         TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1775                         
1776                         if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1777                                 TmpAddr->sin_family = AF_INET;
1778                                 
1779                                 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1780                                 TmpBroad->sin_family = AF_INET;
1781                                 if(ZeroBroadcast==0)
1782                                         TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1783                                 else
1784                                         TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1785
1786                                 while(*(String + StringPos) != 0)StringPos++;
1787                                 StringPos++;
1788                                 
1789                                 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1790                                         break;                          
1791                         }
1792                         else break;
1793                 }               
1794                 
1795                 BufLen = sizeof String;
1796                 // Open the key with the netmasks
1797                 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1798                 if (status != ERROR_SUCCESS) {
1799                         RegCloseKey(TcpIpKey);
1800                         goto fail;
1801                 }
1802                 
1803                 // scan the key to obtain the masks
1804                 StringPos = 0;
1805                 for(nmasks = 0;nmasks < *NEntries;nmasks++){
1806                         TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1807                         
1808                         if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1809                                 TmpAddr->sin_family = AF_INET;
1810                                 
1811                                 while(*(String + StringPos) != 0)StringPos++;
1812                                 StringPos++;
1813                                                                 
1814                                 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1815                                         break;
1816                         }
1817                         else break;
1818                 }               
1819                 
1820                 // The number of masks MUST be equal to the number of adresses
1821                 if(nmasks != naddrs){
1822                         RegCloseKey(TcpIpKey);
1823                         goto fail;
1824                 }
1825                                 
1826         }
1827         else{
1828                 
1829                 BufLen = sizeof String;
1830                 // Open the key with the addresses
1831                 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1832                 if (status != ERROR_SUCCESS) {
1833                         RegCloseKey(TcpIpKey);
1834                         goto fail;
1835                 }
1836                 
1837                 // scan the key to obtain the addresses
1838                 StringPos = 0;
1839                 for(naddrs = 0;naddrs < *NEntries;naddrs++){
1840                         TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
1841                         
1842                         if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1843                                 TmpAddr->sin_family = AF_INET;
1844
1845                                 TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
1846                                 TmpBroad->sin_family = AF_INET;
1847                                 if(ZeroBroadcast==0)
1848                                         TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
1849                                 else
1850                                         TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
1851                                 
1852                                 while(*(String + StringPos) != 0)StringPos++;
1853                                 StringPos++;
1854                                 
1855                                 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1856                                         break;
1857                         }
1858                         else break;
1859                 }               
1860                 
1861                 BufLen = sizeof String;
1862                 // Open the key with the netmasks
1863                 status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
1864                 if (status != ERROR_SUCCESS) {
1865                         RegCloseKey(TcpIpKey);
1866                         goto fail;
1867                 }
1868                 
1869                 // scan the key to obtain the masks
1870                 StringPos = 0;
1871                 for(nmasks = 0;nmasks <* NEntries;nmasks++){
1872                         TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
1873                         
1874                         if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
1875                                 TmpAddr->sin_family = AF_INET;
1876                                 
1877                                 while(*(String + StringPos) != 0)StringPos++;
1878                                 StringPos++;
1879                                 
1880                                 if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
1881                                         break;
1882                         }
1883                         else break;
1884                 }               
1885                 
1886                 // The number of masks MUST be equal to the number of adresses
1887                 if(nmasks != naddrs){
1888                         RegCloseKey(TcpIpKey);
1889                         goto fail;
1890                 }
1891                                 
1892         }
1893         
1894         *NEntries = naddrs + 1;
1895
1896         RegCloseKey(TcpIpKey);
1897         
1898         if (status != ERROR_SUCCESS) {
1899                 goto fail;
1900         }
1901         
1902         
1903         if (AdapterNameU != NULL)
1904                 free(AdapterNameU);
1905         return TRUE;
1906         
1907 fail:
1908         if (AdapterNameU != NULL)
1909                 free(AdapterNameU);
1910     return FALSE;
1911 }
1912
1913 /*!
1914   \brief Returns the IP address and the netmask of an adapter.
1915   \param AdapterName String that contain _ADAPTER structure.
1916   \param netp Pointer to a variable that will receive the IP address of the adapter.
1917   \param maskp Pointer to a variable that will receive the netmask of the adapter.
1918   \return If the function succeeds, the return value is nonzero.
1919
1920   \note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead. 
1921 */
1922
1923 BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
1924 {
1925         char    *AdapterNameA;
1926         WCHAR   *AdapterNameU;
1927         WCHAR   *ifname;
1928         HKEY    SystemKey;
1929         HKEY    InterfaceKey;
1930         HKEY    ParametersKey;
1931         HKEY    TcpIpKey;
1932         LONG    status;
1933         WCHAR   String[1024+1];
1934         DWORD   RegType;
1935         ULONG   BufLen;
1936         DWORD   DHCPEnabled;
1937         ULONG   TAddr,i;
1938
1939         AdapterNameA = (char*)AdapterName;
1940         if(AdapterNameA[1] != 0) {      //ASCII
1941                 AdapterNameU = SChar2WChar(AdapterNameA);
1942                 AdapterName = AdapterNameU;
1943         } else {                                //Unicode
1944                 AdapterNameU = NULL;
1945         }
1946         ifname = wcsrchr(AdapterName, '\\');
1947         if (ifname == NULL)
1948                 ifname = AdapterName;
1949         else
1950                 ifname++;
1951         if (wcsncmp(ifname, L"NPF_", 4) == 0)
1952                 ifname += 4;
1953         status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
1954                                                 TEXT("SYSTEM\\ControlSet001\\Services"),
1955                                                 0,KEY_READ,&SystemKey);
1956         if (status != ERROR_SUCCESS)
1957                 goto fail;
1958         status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
1959         if (status != ERROR_SUCCESS) {
1960                 RegCloseKey(SystemKey);
1961                 goto fail;
1962         }
1963         RegCloseKey(SystemKey);
1964         status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
1965         if (status != ERROR_SUCCESS) {
1966                 RegCloseKey(InterfaceKey);
1967                 goto fail;
1968         }
1969         RegCloseKey(InterfaceKey);
1970         status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
1971         if (status != ERROR_SUCCESS) {
1972                 RegCloseKey(ParametersKey);
1973                 goto fail;
1974         }
1975         RegCloseKey(ParametersKey);
1976                 
1977         BufLen = 4;
1978         /* See if DHCP is used by this system */
1979         status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
1980         if (status != ERROR_SUCCESS)
1981                 DHCPEnabled=0;
1982
1983         
1984         /* Retrieve the netmask */
1985         if(DHCPEnabled){
1986                 
1987                 BufLen = sizeof String;
1988                 status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
1989                 if (status != ERROR_SUCCESS) {
1990                         RegCloseKey(TcpIpKey);
1991                         goto fail;
1992                 }
1993
1994                 TAddr = inet_addrU(String);
1995                 // swap bytes for backward compatibility
1996                 for(i=0;i<4;i++){
1997                         *((char*)netp+i) = *((char*)&TAddr+3-i);
1998                 }
1999                 
2000                 BufLen = sizeof String;
2001                 status=RegQueryValueEx(TcpIpKey,TEXT("DHCPSubnetMask"),NULL,&RegType,
2002                         (LPBYTE)String,&BufLen);
2003                 
2004                 TAddr = inet_addrU(String);
2005                 // swap bytes for backward compatibility
2006                 for(i=0;i<4;i++){
2007                         *((char*)maskp+i) = *((char*)&TAddr+3-i);
2008                 }
2009                 
2010                 
2011         }
2012         else{
2013
2014                 BufLen = sizeof String;
2015                 status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
2016                 if (status != ERROR_SUCCESS) {
2017                         RegCloseKey(TcpIpKey);
2018                         goto fail;
2019                 }
2020
2021                 TAddr = inet_addrU(String);
2022                 // swap bytes for backward compatibility
2023                 for(i=0;i<4;i++){
2024                         *((char*)netp+i) = *((char*)&TAddr+3-i);
2025                 }
2026                 
2027                 BufLen = sizeof String;
2028                 status=RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,
2029                         (LPBYTE)String,&BufLen);
2030                 
2031                 TAddr = inet_addrU(String);
2032                 // swap bytes for backward compatibility
2033                 for(i=0;i<4;i++){
2034                         *((char*)maskp+i) = *((char*)&TAddr+3-i);
2035                 }
2036
2037
2038         }
2039         
2040         if (status != ERROR_SUCCESS) {
2041                 RegCloseKey(TcpIpKey);
2042                 goto fail;
2043         }
2044         
2045                 
2046         if (AdapterNameU != NULL)
2047                 free(AdapterNameU);
2048         return TRUE;
2049         
2050 fail:
2051         if (AdapterNameU != NULL)
2052                 free(AdapterNameU);
2053     return FALSE;
2054 }
2055
2056 /* @} */