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