Updated with latest version changes to original source by Politecnico di Torino.
authorRobert Dickenson <robd@reactos.org>
Tue, 24 Sep 2002 15:08:14 +0000 (15:08 +0000)
committerRobert Dickenson <robd@reactos.org>
Tue, 24 Sep 2002 15:08:14 +0000 (15:08 +0000)
svn path=/trunk/; revision=3551

reactos/lib/packet/Packet32.c
reactos/lib/packet/include/packet32.h
reactos/lib/packet/makefile
reactos/lib/packet/packet.def
reactos/lib/packet/trace.c [new file with mode: 0644]
reactos/lib/packet/trace.h [new file with mode: 0644]

index fd371f4..5f0a06d 100644 (file)
 
 #include <packet32.h>
 #include <windows.h>
-#include <windowsx.h>
+//#include <windowsx.h>
 #include <ntddndis.h>
 
+#include "trace.h"
+
+
+/****** KERNEL Macro APIs ******************************************************/
+
+#define GetInstanceModule(hInst)                (HMODULE)(hInst)
+#define GlobalPtrHandle(lp)                     ((HGLOBAL)GlobalHandle(lp))
+#define GlobalLockPtr(lp)                       ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
+#define GlobalUnlockPtr(lp)                     GlobalUnlock(GlobalPtrHandle(lp))
+#define GlobalAllocPtr(flags, cb)               (GlobalLock(GlobalAlloc((flags), (cb))))
+#define GlobalReAllocPtr(lp, cbNew, flags)      (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
+#define GlobalFreePtr(lp)                       (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
+
+#undef GMEM_MOVEABLE
+#define GMEM_MOVEABLE 0
+
+
 
 /// Title of error windows
 TCHAR   szWindowTitle[] = TEXT("PACKET.DLL");
 
-#if _DBG
+#if DBG
 #define ODS(_x) OutputDebugString(TEXT(_x))
-#define ODSEx(_x, _y)
+//#define ODSEx(_x, _y)
+#define ODSEx TRACE
 #else
 #ifdef _DEBUG_TO_FILE
 #include <stdio.h>
-// Macro to print a debug string. The behavior differs depending on the debug level
+/*! 
+  \brief Macro to print a debug string. The behavior differs depending on the debug level
+*/
 #define ODS(_x) { \
        FILE *f; \
        f = fopen("winpcap_debug.txt", "a"); \
        fprintf(f, "%s", _x); \
        fclose(f); \
 }
-// Macro to print debug data with the printf convention. The behavior differs depending on */
+/*! 
+  \brief Macro to print debug data with the printf convention. The behavior differs depending on 
+  the debug level
+*/
 #define ODSEx(_x, _y) { \
        FILE *f; \
        f = fopen("winpcap_debug.txt", "a"); \
@@ -64,11 +87,15 @@ SC_HANDLE srvHandle = NULL;
 LPCTSTR NPFServiceName = TEXT("NPF");
 LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
 LPCTSTR NPFDriverName = TEXT("\\npf.sys");
-LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\CurrentControlSet\\Services\\NPF");
+LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
 
 
 //---------------------------------------------------------------------------
 
+/*! 
+  \brief The main dll function.
+*/
+
 BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
 {
     BOOLEAN Status=TRUE;
@@ -81,13 +108,13 @@ BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
                
 #ifdef _DEBUG_TO_FILE
                // dump a bunch of registry keys useful for debug to file
-               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
+               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
                        "adapters.reg");
-               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip",
+               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
                        "tcpip.reg");
-               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\NPF",
+               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
                        "npf.reg");
-               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services",
+               PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
                        "services.reg");
 #endif
                break;
@@ -102,7 +129,11 @@ BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
     return Status;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
+  \param string The string to convert.
+  \return The converted string.
+*/
 
 WCHAR* SChar2WChar(char* string)
 {
@@ -114,7 +145,14 @@ WCHAR* SChar2WChar(char* string)
        return TmpStr;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
+  \param AdapterObject Handle to the service control manager.
+  \return If the function succeeds, the return value is nonzero.
+
+  The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
+  without performing a copy. This function tries to increase the size of that buffer.
+*/
 
 BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
 {
@@ -138,12 +176,20 @@ BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
     return Status;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Retrieves the event associated in the driver with a capture instance and stores it in an 
+   _ADAPTER structure.
+  \param AdapterObject Handle to the service control manager.
+  \return If the function succeeds, the return value is nonzero.
+
+  This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
+  call and set it in the _ADAPTER structure pointed by AdapterObject.
+*/
 
 BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
 {
        DWORD BytesReturned;
-       TCHAR EventName[39];
+       WCHAR EventName[39];
 
        // this tells the terminal service to retrieve the event from the global namespace
        wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
@@ -154,7 +200,7 @@ BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
        EventName[20]=0; // terminate the string
 
        // open the shared event
-       AdapterObject->ReadEvent=CreateEvent(NULL,
+       AdapterObject->ReadEvent=CreateEventW(NULL,
                                                                                 TRUE,
                                                                                 FALSE,
                                                                                 EventName);
@@ -165,7 +211,7 @@ BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
                        CloseHandle(AdapterObject->ReadEvent);
                
                // open the shared event
-               AdapterObject->ReadEvent=CreateEvent(NULL,
+               AdapterObject->ReadEvent=CreateEventW(NULL,
                        TRUE,
                        FALSE,
                        EventName+7);
@@ -182,14 +228,22 @@ BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
 
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Installs the NPF device driver.
+  \param ascmHandle Handle to the service control manager.
+  \param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
+  \param driverPath The full path of the .sys file to load.
+  \return If the function succeeds, the return value is nonzero.
+
+  This function installs the driver's service in the system using the CreateService function.
+*/
 
-BOOL PacketInstallDriver(SC_HANDLE ascmHandle,SC_HANDLE *srvHandle,TCHAR *driverPath)
+BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
 {
        BOOL result = FALSE;
        ULONG err;
        
-       ODS("installdriver\n")
+       ODS("installdriver\n");
        
        if (GetFileAttributes(driverPath) != 0xffffffff) {
                *srvHandle = CreateService(ascmHandle, 
@@ -206,26 +260,35 @@ BOOL PacketInstallDriver(SC_HANDLE ascmHandle,SC_HANDLE *srvHandle,TCHAR *driver
                                //npf.sys already existed
                                result = TRUE;
                        }
-               }
-               else {
+               } else {
                        //Created service for npf.sys
                        result = TRUE;
                }
        }
-       if (result == TRUE) 
-               if (*srvHandle != NULL)
+       if (result == TRUE) {
+               if (*srvHandle != NULL) {
                        CloseServiceHandle(*srvHandle);
+               }
+       }
 
-       if(result == FALSE){
+       if (result == FALSE){
                err = GetLastError();
-               if(err != 2)
+               if (err != 2) {
                        ODSEx("PacketInstallDriver failed, Error=%d\n",err);
+               }
        }
        return result;
        
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Convert a Unicode dotted-quad to a 32-bit IP address.
+  \param cp A string containing the address.
+  \return the converted 32-bit numeric address.
+
+   Doesn't check to make sure the address is valid.
+*/
+
 
 ULONG inet_addrU(const WCHAR *cp)
 {
@@ -255,7 +318,14 @@ ULONG inet_addrU(const WCHAR *cp)
        return val;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Dumps a registry key to disk in text format. Uses regedit.
+  \param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
+  \param FileName Name of the file that will contain the dump.
+  \return If the function succeeds, the return value is nonzero.
+
+  For debugging purposes, we use this function to obtain some registry keys from the user's machine.
+*/
 
 #ifdef _DEBUG_TO_FILE
 
@@ -279,17 +349,41 @@ LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
 // PUBLIC API
 //---------------------------------------------------------------------------
 
+/** @ingroup packetapi
+ *  @{
+ */
+
+/** @defgroup packet32 Packet.dll exported functions and variables
+ *  @{
+ */
+
 /// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
 char PacketLibraryVersion[] = "2.3"; 
 
-//---------------------------------------------------------------------------
-
+/*! 
+  \brief Returns a string with the dll version.
+  \return A char pointer to the version of the library.
+*/
 PCHAR PacketGetVersion(){
        return PacketLibraryVersion;
 }
 
-//---------------------------------------------------------------------------
-
+/*! 
+  \brief Returns information about the MAC type of an adapter.
+  \param AdapterObject The adapter on which information is needed.
+  \param type Pointer to a NetType structure that will be filled by the function.
+  \return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
+
+  This function return the link layer technology and the speed (in bps) of an opened adapter.
+  The LinkType field of the type parameter can have one of the following values:
+
+  - NdisMedium802_3: Ethernet (802.3) 
+  - NdisMediumWan: WAN 
+  - NdisMedium802_5: Token Ring (802.5) 
+  - NdisMediumFddi: FDDI 
+  - NdisMediumAtm: ATM 
+  - NdisMediumArcnet878_2: ARCNET (878.2) 
+*/
 BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
 {
     BOOLEAN    Status;
@@ -320,8 +414,14 @@ BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
     return Status;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Stops and unloads the WinPcap device driver.
+  \return If the function succeeds, the return value is nonzero, otherwise it is zero.
 
+  This function can be used to unload the driver from memory when the application no more needs it.
+  Note that the driver is physically stopped and unloaded only when all the files on its devices 
+  are closed, i.e. when all the applications that use WinPcap close all their adapters.
+*/
 BOOL PacketStopDriver()
 {
        SC_HANDLE               scmHandle;
@@ -361,8 +461,28 @@ BOOL PacketStopDriver()
 
 }
 
-//---------------------------------------------------------------------------
-
+/*! 
+  \brief Opens an adapter.
+  \param AdapterName A string containing the name of the device to open. 
+   Use the PacketGetAdapterNames() function to retrieve the list of available devices.
+  \return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
+   otherwise the return value is NULL.
+
+  This function tries to load and start the packet driver at the first invocation. In this way, 
+  the management of the driver is transparent to the application, that simply needs to open an adapter to start
+  WinPcap.
+  
+  \note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT 
+  version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE 
+  string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained 
+  through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format.
+  Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they 
+  use the ASCII format. Since this could be a relevant problem during the porting of command-line applications 
+  from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and
+  convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT 
+  accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE 
+  by PACKET.DLL before being passed to the driver.
+*/
 LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
 {
     LPADAPTER lpAdapter;
@@ -377,20 +497,18 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
        HKEY PathKey;
        SERVICE_STATUS SStat;
        BOOLEAN QuerySStat;
+       WCHAR SymbolicLink[128];
 
-    ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName)
+    ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName);
 
        scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
-       
        if(scmHandle == NULL){
                error = GetLastError();
                ODSEx("OpenSCManager failed! Error=%d\n", error);
-       }
-       else{
+       } else {
                *driverPath = 0;
                GetCurrentDirectory(512, driverPath);
-               wsprintf(driverPath + wcslen(driverPath), 
-                       NPFDriverName);
+               wsprintf(driverPath + wcslen(driverPath), NPFDriverName);
                
                // check if the NPF registry key is already present
                // this means that the driver is already installed and that we don't need to call PacketInstallDriver
@@ -402,8 +520,7 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
                
                if(KeyRes != ERROR_SUCCESS){
                        Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
-               }
-               else{
+               } else {
                        Result = TRUE;
                        RegCloseKey(PathKey);
                }
@@ -416,11 +533,11 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
                                QuerySStat = QueryServiceStatus(srvHandle, &SStat);
                                ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
                                
-                               if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
+                               if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
                                        ODS("Calling startservice\n");
                                        if (StartService(srvHandle, 0, NULL)==0){ 
                                                error = GetLastError();
-                                               if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
+                                               if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
                                                        SetLastError(error);
                                                        if (scmHandle != NULL) CloseServiceHandle(scmHandle);
                                                        error = GetLastError();
@@ -429,38 +546,31 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
                                                }
                                        }                               
                                }
-                       }
-                       else{
+                       } else {
                                error = GetLastError();
                                ODSEx("OpenService failed! Error=%d", error);
                        }
-               }
-               else{
-                       if( GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) return FALSE;
-                       wsprintf(driverPath,
-                               TEXT("%s\\drivers%s"), 
-                               WinPath,NPFDriverName);
+               } else {
+                       if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) {
+                               return FALSE;
+                       }
+                       wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName);
                        
-                       if(KeyRes != ERROR_SUCCESS)
+                       if (KeyRes != ERROR_SUCCESS) {
                                Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
-                       else
+                       } else {
                                Result = TRUE;
-                       
+                       }
                        if (Result) {
-                               
                                srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
-                               if (srvHandle != NULL){
-                                       
+                               if (srvHandle != NULL) {
                                        QuerySStat = QueryServiceStatus(srvHandle, &SStat);
                                        ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
-                                       
-                                       if(!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
-                                               
+                                       if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) {
                                                ODS("Calling startservice\n");
-                                               
-                                               if (StartService(srvHandle, 0, NULL)==0){ 
+                                               if (StartService(srvHandle, 0, NULL) == 0) { 
                                                        error = GetLastError();
-                                                       if(error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
+                                                       if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) {
                                                                SetLastError(error);
                                                                if (scmHandle != NULL) CloseServiceHandle(scmHandle);
                                                                ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
@@ -468,48 +578,49 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
                                                        }
                                                }
                                        }
-                               }
-                               else{
+                               } else {
                                        error = GetLastError();
                                        ODSEx("OpenService failed! Error=%d", error);
                                }
                        }
                }
        }
-
     if (scmHandle != NULL) CloseServiceHandle(scmHandle);
 
-       AdapterNameA=(char*)AdapterName;
-       if(AdapterNameA[1]!=0){ //ASCII
-               AdapterNameU=SChar2WChar(AdapterNameA);
-               AdapterName=AdapterNameU;
-       } else {                        //Unicode
-               AdapterNameU=NULL;
+       AdapterNameA = (char*)AdapterName;
+       if (AdapterNameA[1] != 0) {  // ASCII
+               AdapterNameU = SChar2WChar(AdapterNameA);
+               AdapterName = AdapterNameU;
+       } else {                                 // Unicode
+               AdapterNameU = NULL;
        }
        
-       lpAdapter=(LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
-       if (lpAdapter==NULL)
-       {
+       lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
+       if (lpAdapter == NULL) {
                ODS("PacketOpenAdapter: GlobalAlloc Failed\n");
-               error=GetLastError();
+               error = GetLastError();
                if (AdapterNameU != NULL) free(AdapterNameU);
                //set the error to the one on which we failed
                SetLastError(error);
            ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n");
                return NULL;
        }
-       lpAdapter->NumWrites=1;
+       lpAdapter->NumWrites = 1;
 
-       wsprintf(lpAdapter->SymbolicLink,TEXT("\\\\.\\%s%s"),DOSNAMEPREFIX,&AdapterName[8]);
+       wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]);
        
+       // Copy  only the bytes that fit in the adapter structure.
+       // Note that lpAdapter->SymbolicLink is present for backward compatibility but will
+       // never be used by the apps
+       memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
+
        //try if it is possible to open the adapter immediately
-       lpAdapter->hFile=CreateFile(lpAdapter->SymbolicLink,GENERIC_WRITE | GENERIC_READ,
-               0,NULL,OPEN_EXISTING,0,0);
+       lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
        
        if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
-
-               if(PacketSetReadEvt(lpAdapter)==FALSE){
-                       error=GetLastError();
+           ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink);
+               if (PacketSetReadEvt(lpAdapter) == FALSE) {
+                       error = GetLastError();
                        ODS("PacketOpenAdapter: Unable to open the read event\n");
                        if (AdapterNameU != NULL)
                                free(AdapterNameU);
@@ -527,18 +638,20 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
        }
        //this is probably the first request on the packet driver. 
        //We must create the dos device and set the access rights on it
-       else{
-               Result=DefineDosDevice(DDD_RAW_TARGET_PATH,&lpAdapter->SymbolicLink[4],AdapterName);
-               if (Result)
-               {
+       else {
+               Result = DefineDosDevice(DDD_RAW_TARGET_PATH,
+                                 &SymbolicLink[4],
+                                 AdapterName);
+               if (Result) {
 
-                       lpAdapter->hFile=CreateFile(lpAdapter->SymbolicLink,GENERIC_WRITE | GENERIC_READ,
-                               0,NULL,OPEN_EXISTING,0,0);
-                       if (lpAdapter->hFile != INVALID_HANDLE_VALUE)
-                       {               
-                               
-                               if(PacketSetReadEvt(lpAdapter)==FALSE){
-                                       error=GetLastError();
+                   ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink);
+                       
+                       lpAdapter->hFile = CreateFile(
+                                 SymbolicLink,
+                                 GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
+                       if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {         
+                               if (PacketSetReadEvt(lpAdapter) == FALSE) {
+                                       error = GetLastError();
                                        ODS("PacketOpenAdapter: Unable to open the read event\n");
                                        if (AdapterNameU != NULL)
                                                free(AdapterNameU);
@@ -548,16 +661,18 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
                                    ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error);
                                        return NULL;                                    
                                }
-
                                PacketSetMaxLookaheadsize(lpAdapter);
                                if (AdapterNameU != NULL)
                                    free(AdapterNameU);
                                return lpAdapter;
+                       } else {
+                   ODS("PacketOpenAdapter: CreateFile failed\n");
                        }
+               } else {
+           ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]);
                }
        }
-
-       error=GetLastError();
+       error = GetLastError();
        if (AdapterNameU != NULL)
            free(AdapterNameU);
        GlobalFreePtr(lpAdapter);
@@ -568,8 +683,12 @@ LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
 
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Closes an adapter.
+  \param lpAdapter the pointer to the adapter to close. 
 
+  PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
+*/
 VOID PacketCloseAdapter(LPADAPTER lpAdapter)
 {
     CloseHandle(lpAdapter->hFile);
@@ -578,29 +697,58 @@ VOID PacketCloseAdapter(LPADAPTER lpAdapter)
     GlobalFreePtr(lpAdapter);
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Allocates a _PACKET structure.
+  \return On succeess, the return value is the pointer to a _PACKET structure otherwise the 
+   return value is NULL.
+
+  The structure returned will be passed to the PacketReceivePacket() function to receive the
+  packets from the driver.
 
+  \warning The Buffer field of the _PACKET structure is not set by this function. 
+  The buffer \b must be allocated by the application, and associated to the PACKET structure 
+  with a call to PacketInitPacket.
+*/
 LPPACKET PacketAllocatePacket(void)
 {
 
-    LPPACKET    lpPacket;
-    lpPacket=(LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
-    if (lpPacket==NULL)
-    {
+    LPPACKET lpPacket;
+    lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
+    if (lpPacket == NULL) {
         ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
         return NULL;
     }
     return lpPacket;
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Frees a _PACKET structure.
+  \param lpPacket The structure to free. 
+
+  \warning the user-allocated buffer associated with the _PACKET structure is not deallocated 
+  by this function and \b must be explicitly deallocated by the programmer.
 
+*/
 VOID PacketFreePacket(LPPACKET lpPacket)
 {
     GlobalFreePtr(lpPacket);
 }
 
-//---------------------------------------------------------------------------
+/*! 
+  \brief Initializes a _PACKET structure.
+  \param lpPacket The structure to initialize. 
+  \param Buffer A pointer to a user-allocated buffer that will contain the captured data.
+  \param Length the length of the buffer. This is the maximum buffer size that will be 
+   transferred from the driver to the application using a single read.
+
+  \note the size of the buffer associated with the PACKET structure is a parameter that can sensibly 
+  influence the performance of the capture process, since this buffer will contain the packets received
+  from the the driver. The driver is able to return several packets using a single read call 
+  (see the PacketReceivePacket() function for details), and the number of packets transferable to the 
+  application in a call is limited only by the size of the buffer associated with the PACKET structure
+  passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably 
+  decrease the number of system calls, reducing the impcat of the capture process on the processor.
+*/
 
 VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
 {
@@ -610,8 +758,36 @@ VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
        lpPacket->bIoComplete = FALSE;
 }
 
-//---------------------------------------------------------------------------
-
+/*! 
+  \brief Read data (packets or statistics) from the NPF driver.
+  \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which 
+   the data is received.
+  \param lpPacket Pointer to a PACKET structure that will contain the data.
+  \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with 
+   older applications.
+  \return If the function succeeds, the return value is nonzero.
+
+  The data received with this function can be a group of packets or a static on the network traffic, 
+  depending on the working mode of the driver. The working mode can be set with the PacketSetMode() 
+  function. Give a look at that function if you are interested in the format used to return statistics 
+  values, here only the normal capture mode will be described.
+
+  The number of packets received with this function is variable. It depends on the number of packets 
+  currently stored in the driver\92s buffer, on the size of these packets and on the size of the buffer 
+  associated to the lpPacket parameter. The following figure shows the format used by the driver to pass 
+  packets to the application. 
+
+  \image html encoding.gif "method used to encode the packets"
+
+  Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
+  that structure is updated with the amount of data copied in the buffer. Each packet has a header
+  consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field 
+  is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen 
+  and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer. 
+  
+  Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
+  in the developer's pack, or in the pcap_read() function of wpcap.
+*/
 BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
 {
        BOOLEAN res;
@@ -620,24 +796,141 @@ BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sy
     res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
        return res;
 }
-/* 
-ReadFile(
-        HANDLE hFile,
-        LPVOID lpBuffer,
-        DWORD nNumberOfBytesToRead,
-        LPDWORD lpNumberOfBytesRead,
-        LPOVERLAPPED lpOverlapped
-        );
- */
-//---------------------------------------------------------------------------
 
+/*! 
+  \brief Sends one (or more) copies of a packet to the network.
+  \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will 
+   send the packets.
+  \param lpPacket Pointer to a PACKET structure with the packet to send.
+  \param Sync This parameter is deprecated and will be ignored. It is present for compatibility with 
+   older applications.
+  \return If the function succeeds, the return value is nonzero.
+
+  This function is used to send a raw packet to the network. 'Raw packet' means that the programmer 
+  will have to include the protocol headers, since the packet is sent to the network 'as is'. 
+  The CRC needs not to be calculated and put at the end of the packet, because it will be transparently 
+  added by the network interface.
+
+  The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
+  it is possible to change the number of times a single write must be repeated. The default is 1, 
+  i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
+  greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on 
+  the network. This feature mitigates the overhead of the context switches and therefore can be used to generate 
+  high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need 
+  to obtain high network loads.
+  The optimized sending process is still limited to one packet at a time: for the moment it cannot be used 
+  to send a buffer with multiple packets.
+
+  \note The ability to write multiple packets is currently present only in the Windows NTx version of the 
+  packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
+  that uses the multiple write method will run in Windows 9x as well, but its performance will be very low 
+  compared to the one of WindowsNTx.
+*/
 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
 {
     DWORD BytesTransfered;
     return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
 }
 
-//---------------------------------------------------------------------------
+
+/*! 
+  \brief Sends a buffer of packets to the network.
+  \param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will 
+   send the packets.
+  \param PacketBuff Pointer to buffer with the packets to send.
+  \param Size Size of the buffer pointed by the PacketBuff argument.
+  \param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
+         fast as possible
+  \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+          error occurred during the send. The error can be caused by a driver/adapter problem or by an
+                 inconsistent/bogus packet buffer.
+
+  This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
+  number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
+  by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
+  'Raw packets' means that the sending application will have to include the protocol headers, since every packet 
+  is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be 
+  transparently added by the network interface.
+
+  \note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
+  buffered in the kernel driver, so the number of context switches is reduced.
+
+  \note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
+  This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
+  (depending on the precision of the performance counter of the machine). Such a precision cannot be reached 
+  sending the packets separately with PacketSendPacket().
+*/
+INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
+{
+    BOOLEAN                    Res;
+    DWORD                      BytesTransfered, TotBytesTransfered=0;
+       struct timeval  BufStartTime;
+       LARGE_INTEGER   StartTicks, CurTicks, TargetTicks, TimeFreq;
+
+
+       ODS("PacketSendPackets");
+
+       // Obtain starting timestamp of the buffer
+       BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
+       BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
+
+       // Retrieve the reference time counters
+       QueryPerformanceCounter(&StartTicks);
+       QueryPerformanceFrequency(&TimeFreq);
+
+       CurTicks.QuadPart = StartTicks.QuadPart;
+
+       do{
+               // Send the data to the driver
+               Res = DeviceIoControl(AdapterObject->hFile,
+                       (Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
+                       (PCHAR)PacketBuff + TotBytesTransfered,
+                       Size - TotBytesTransfered,
+                       NULL,
+                       0,
+                       &BytesTransfered,
+                       NULL);
+
+               TotBytesTransfered += BytesTransfered;
+
+               // calculate the time interval to wait before sending the next packet
+               TargetTicks.QuadPart = StartTicks.QuadPart +
+               (LONGLONG)
+               ((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
+               (((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
+               (TimeFreq.QuadPart) / 1000000;
+
+               // Exit from the loop on termination or error
+               if(TotBytesTransfered >= Size || Res != TRUE)
+                       break;
+               
+               // Wait until the time interval has elapsed
+               while( CurTicks.QuadPart <= TargetTicks.QuadPart )
+                       QueryPerformanceCounter(&CurTicks);
+
+       }
+       while(TRUE);
+
+       return TotBytesTransfered;
+}
+
+/*! 
+  \brief Defines the minimum amount of data that will be received in a read.
+  \param AdapterObject Pointer to an _ADAPTER structure
+  \param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
+   release a read on this adapter.
+  \return If the function succeeds, the return value is nonzero.
+
+  In presence of a large value for nbytes, the kernel waits for the arrival of several packets before 
+  copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage, 
+  i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value 
+  means that the kernel will copy the packets as soon as the application is ready to receive them. This is 
+  suggested for real time applications (like, for example, a bridge) that need the better responsiveness from 
+  the kernel.
+
+  \b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer 
+  this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
+*/
 
 BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
 {
@@ -645,31 +938,213 @@ BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
     return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
-
+/*!
+  \brief Sets the working mode of an adapter.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param mode The new working mode of the adapter.
+  \return If the function succeeds, the return value is nonzero.
+
+  The device driver of WinPcap has 4 working modes:
+  - Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
+   to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
+  - Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
+   precise intervals, statics values on the network traffic. The interval between the statistic samples is 
+   by default 1 second but it can be set to any other value (with a 1 ms precision) with the 
+   PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
+   mode is shown in the following figure:<p>
+        \image html stats.gif "data structure returned by statistical mode"
+   Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter 
+   previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are 
+   encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a 
+   very low impact on system performance compared to capture mode. 
+  - Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
+   method is much faster than saving the packets after having captured them. No data is returned 
+   by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
+   this filter are dumped to disk.
+  - Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap 
+   format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the 
+   network traffic and on the amount of data saved to file, in a way similar to statistical mode.
+   The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in 
+   the following figure:<p>   
+        \image html dump.gif "data structure returned by statistical dump mode"
+   Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the 
+   effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are 
+   dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly 
+   by wpcap.
+   Look at the NetMeter example in the 
+   WinPcap developer's pack to see how to use statistics mode.
+*/
 BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
 {
        DWORD BytesReturned;
     return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param name the file name, in ASCII or UNICODE.
+  \param len the length of the buffer containing the name, in bytes.
+  \return If the function succeeds, the return value is nonzero.
+
+  This function defines the file name that the driver will open to store the packets on disk when 
+  it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
+  called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
+  If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver 
+  closes the old file and opens the new one.
+*/
+
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
+{
+       DWORD           BytesReturned;
+       WCHAR   *FileName;
+       BOOLEAN res;
+       WCHAR   NameWithPath[1024];
+       int             TStrLen;
+       WCHAR   *NamePos;
+
+       if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
+               FileName=SChar2WChar(name);
+               len*=2;
+       } 
+       else {  //Unicode
+               FileName=name;
+       }
+
+       TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
+
+       len=TStrLen*2+2;  //add the terminating null character
 
+       // Try to catch malformed strings
+       if(len>2048){
+               if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
+               return FALSE;
+       }
+
+    res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
+       free(FileName);
+       return res;
+}
+
+/*!
+  \brief Set the dump mode limits.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
+  \param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
+  \return If the function succeeds, the return value is nonzero.
+
+  This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
+  is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
+  very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
+  the first of the two is reached.
+
+  \note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush 
+  correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
+*/
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
+{
+       DWORD           BytesReturned;
+       UINT valbuff[2];
+
+       valbuff[0] = maxfilesize;
+       valbuff[1] = maxnpacks;
+
+    return DeviceIoControl(AdapterObject->hFile,
+               pBIOCSETDUMPLIMITS,
+               valbuff,
+               sizeof valbuff,
+               NULL,
+               0,
+               &BytesReturned,
+               NULL);  
+}
+
+/*!
+  \brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
+  \return TRUE if the dump is ended, FALSE otherwise.
+
+  PacketIsDumpEnded() informs the user about the limits that were set with a previous call to 
+  PacketSetDumpLimits().
+
+  \warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits 
+  (i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
+  block the application on this call forever.
+*/
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
+{
+       DWORD           BytesReturned;
+       int             IsDumpEnded;
+       BOOLEAN res;
+
+       if(sync)
+               WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
+
+    res = DeviceIoControl(AdapterObject->hFile,
+               pBIOCISDUMPENDED,
+               NULL,
+               0,
+               &IsDumpEnded,
+               4,
+               &BytesReturned,
+               NULL);
+
+       if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
+
+       return (BOOLEAN)IsDumpEnded;
+}
+
+/*!
+  \brief Returns the notification event associated with the read calls on an adapter.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \return The handle of the event that the driver signals when some data is available in the kernel buffer.
+
+  The event returned by this function is signaled by the driver if:
+  - The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal 
+  than the one set with the PacketSetMinToCopy() function is received from the network.
+  - the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
+   but the the timeout set with the PacketSetReadTimeout() function has elapsed.
+  - the adapter pointed by AdapterObject is in statics mode and the the timeout set with the 
+   PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
+
+  In every case, a call to PacketReceivePacket() will return immediately.
+  The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects) 
+  to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that 
+  need to wait concurrently on several events.
+
+*/
 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
 {
     return AdapterObject->ReadEvent;
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param nwrites Number of copies of a packet that will be physically sent by the interface.
+  \return If the function succeeds, the return value is nonzero.
 
+       See PacketSendPacket() for details.
+*/
 BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
 {
        DWORD BytesReturned;
     return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
-
+/*!
+  \brief Sets the timeout after which a read on an adapter returns.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on 
+  the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver. 
+  Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.  
+  A timeout of -1 causes PacketReceivePacket() to always return immediately.
+  \return If the function succeeds, the return value is nonzero.
+
+  \note This function works also if the adapter is working in statistics mode, and can be used to set the 
+  time interval between two statistic reports.
+*/
 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
 {
        DWORD BytesReturned;
@@ -680,32 +1155,136 @@ BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
     return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
-
+/*!
+  \brief Sets the size of the kernel-level buffer associated with a capture.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param dim New size of the buffer, in \b kilobytes.
+  \return The function returns TRUE if successfully completed, FALSE if there is not enough memory to 
+   allocate the new buffer.
+
+  When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are 
+  lost. 
+  
+  Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
+  An adequate buffer in the driver is able to keep the packets while the application is busy, compensating 
+  the delays of the application and avoiding the loss of packets during bursts or high network activity. 
+  The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to 
+  set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
+*/
 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
 {
        DWORD BytesReturned;
     return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
-
+/*!
+  \brief Sets a kernel-level packet filter.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param fp Pointer to a filtering program that will be associated with this capture or monitoring 
+  instance and that will be executed on every incoming packet.
+  \return This function returns TRUE if the filter is set successfully, FALSE if an error occurs 
+   or if the filter program is not accepted after a safeness check by the driver.  The driver performs 
+   the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
+   conformat filters.
+
+  This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a 
+  set of bpf_insn instructions.
+
+  A filter can be automatically created by using the pcap_compile() function of wpcap. This function 
+  converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at 
+  http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but 
+  you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd 
+  flags to obtain the pseudocode.
+
+*/
 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp)
 {
        DWORD BytesReturned;
     return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Returns a couple of statistic values about the current capture session.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
+  \return If the function succeeds, the return value is nonzero.
+
+  With this function, the programmer can know the value of two internal variables of the driver:
 
+  - the number of packets that have been received by the adapter AdapterObject, starting at the 
+   time in which it was opened with PacketOpenAdapter. 
+  - the number of packets that have been dropped by the driver. A packet is dropped when the kernel
+   buffer associated with the adapter is full. 
+*/
 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
 {
+       BOOLEAN Res;
        DWORD BytesReturned;
-       return DeviceIoControl(AdapterObject->hFile,pBIOCGSTATS,NULL,0,s,sizeof(struct bpf_stat),&BytesReturned,NULL);
+       struct bpf_stat tmpstat;        // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
+
+       Res = DeviceIoControl(AdapterObject->hFile,
+               pBIOCGSTATS,
+               NULL,
+               0,
+               &tmpstat,
+               sizeof(struct bpf_stat),
+               &BytesReturned,
+               NULL);
+
+       // Copy only the first two values retrieved from the driver
+       s->bs_recv = tmpstat.bs_recv;
+       s->bs_drop = tmpstat.bs_drop;
+
+       return Res;
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param s Pointer to a user provided bpf_stat structure that will be filled by the function.
+  \return If the function succeeds, the return value is nonzero.
+
+  With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
+
+  - the number of drops by interface (not yet supported, always 0). 
+  - the number of packets that reached the application, i.e that were accepted by the kernel filter and
+  that fitted in the kernel buffer. 
+*/
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
+{
+       BOOLEAN Res;
+       DWORD BytesReturned;
+       struct bpf_stat tmpstat;        // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
+
+       Res = DeviceIoControl(AdapterObject->hFile,
+               pBIOCGSTATS,
+               NULL,
+               0,
+               &tmpstat,
+               sizeof(struct bpf_stat),
+               &BytesReturned,
+               NULL);
+
+       s->bs_recv = tmpstat.bs_recv;
+       s->bs_drop = tmpstat.bs_drop;
+       s->ps_ifdrop = tmpstat.ps_ifdrop;
+       s->bs_capt = tmpstat.bs_capt;
+
+       return Res;
+}
 
+/*!
+  \brief Performs a query/set operation on an internal variable of the network card driver.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
+  \param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
+  \return If the function succeeds, the return value is nonzero.
+
+  \note not all the network adapters implement all the query/set functions. There is a set of mandatory 
+  OID functions that is granted to be present on all the adapters, and a set of facultative functions, not 
+  provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a 
+  facultative function, be careful to enclose it in an if statement to check the result.
+*/
 BOOLEAN PacketRequest(LPADAPTER  AdapterObject,BOOLEAN Set,PPACKET_OID_DATA  OidData)
 {
        DWORD BytesReturned;
@@ -724,8 +1303,22 @@ BOOLEAN PacketRequest(LPADAPTER  AdapterObject,BOOLEAN Set,PPACKET_OID_DATA  Oid
        return Result;
 }
 
-//---------------------------------------------------------------------------
-
+/*!
+  \brief Sets a hardware filter on the incoming packets.
+  \param AdapterObject Pointer to an _ADAPTER structure.
+  \param Filter The identifier of the filter.
+  \return If the function succeeds, the return value is nonzero.
+
+  The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
+  device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
+
+  - NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter. 
+  - NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted. 
+  - NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted. 
+  - NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted. 
+  - NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted. 
+  - NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST 
+*/
 BOOLEAN PacketSetHwFilter(LPADAPTER  AdapterObject,ULONG Filter)
 {
     BOOLEAN    Status;
@@ -745,74 +1338,98 @@ BOOLEAN PacketSetHwFilter(LPADAPTER  AdapterObject,ULONG Filter)
     return Status;
 }
 
-//---------------------------------------------------------------------------
-
-BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG  BufferSize)
+/*!
+  \brief Retrieve the list of available network adapters and their description.
+  \param pStr User allocated string that will be filled with the names of the adapters.
+  \param BufferSize Length of the buffer pointed by pStr.
+  \return If the function succeeds, the return value is nonzero.
+
+  Usually, this is the first function that should be used to communicate with the driver.
+  It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>. 
+  After the names of the adapters, pStr contains a string that describes each of them.
+
+  \b Warning: 
+  the result of this function is obtained querying the registry, therefore the format 
+  of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII
+  encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames 
+  in Windows 95x, pStr contains, in succession:
+  - a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
+  - a double "\0"
+  - a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number 
+   of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
+   so on.
+  - a double "\0". 
+
+  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".
+  - a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0"
+  - a double UNICODE "\0"
+  - a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0".
+  - a double ASCII "\0". 
+*/
+
+BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)
 {
-    HKEY       LinkageKey,AdapKey;
-       DWORD      RegKeySize=0;
+    HKEY       LinkageKey, AdapKey;
+       DWORD      RegKeySize = 0;
     LONG       Status;
        ULONG      Result;
        PTSTR      BpStr;
-       char       *TTpStr,*DpStr,*DescBuf;
+       char       *TTpStr;
+       char       *DpStr;
+       char       *DescBuf;
        LPADAPTER  adapter;
-    PPACKET_OID_DATA  OidData;
-       int                i=0,k,rewind;
+    PPACKET_OID_DATA OidData;
+       int                i = 0, k, rewind;
     DWORD      dim;
        TCHAR      AdapName[256];
 
     ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize);
 
-    OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,512);
+    OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512);
     if (OidData == NULL) {
         ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
         return FALSE;
     }
 
-    Status=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                               TEXT("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
-                                               0,
-                                               KEY_READ,
-                                               &AdapKey);
+    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                                 TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
+                                                 0, KEY_READ, &AdapKey);
 
        // Get the size to allocate for the original device names
-       while((Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2))==ERROR_SUCCESS)
-       {
-               Status=RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
-               Status=RegOpenKeyEx(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
-        Status=RegQueryValueEx(LinkageKey,L"Export",NULL,NULL,NULL,&dim);
+       while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
+               Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey);
+               Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey);
+        Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim);
                i++;
-               if(Status!=ERROR_SUCCESS) continue;
-               RegKeySize+=dim;
+               if (Status!=ERROR_SUCCESS) continue;
+               RegKeySize += dim;
        }
        
        // Allocate the memory for the original device names
        ODSEx("Need %d bytes for the names\n", RegKeySize+2);
-       BpStr=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,RegKeySize+2);
+       BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
        if (BpStr == NULL || RegKeySize > *BufferSize) {
         ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
                GlobalFreePtr(OidData);
                return FALSE;
        }
-
-       k=0;
-       i=0;
+       k = 0;
+       i = 0;
 
     ODS("PacketGetAdapterNames: Cycling through the adapters:\n");
 
        // Copy the names to the buffer
-       while((Result=RegEnumKey(AdapKey,i,AdapName,sizeof(AdapName)/2))==ERROR_SUCCESS)
-       {
+       while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
                WCHAR UpperBindStr[64];
 
                i++;
                ODSEx(" %d) ", i);
 
-               Status=RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
-               Status=RegOpenKeyEx(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
+               Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
+               Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
 
                dim=sizeof(UpperBindStr);
-        Status=RegQueryValueEx(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
+        Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
                
                ODSEx("UpperBind=%S ", UpperBindStr);
 
@@ -822,7 +1439,7 @@ BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG  BufferSize)
                }
 
                dim=RegKeySize-k;
-        Status=RegQueryValueEx(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
+        Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
                if(Status!=ERROR_SUCCESS){
                        ODS("Name = SKIPPED (error reading the key)\n");
                        continue;
@@ -875,9 +1492,9 @@ BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG  BufferSize)
                        // Create the device name
                        rewind=k;
                        memcpy(pStr+k,BpStr+i,16);
-                       memcpy(pStr+k+8,TEXT("Packet_"),14);
+                       memcpy(pStr+k+8,TEXT("NPF_"),8);
                        i+=8;
-                       k+=15;
+                       k+=12;
                        while(BpStr[i-1]!=0){
                                pStr[k++]=BpStr[i++];
                        }
@@ -912,134 +1529,146 @@ BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG  BufferSize)
                        PacketCloseAdapter(adapter);
                        
                }
-               *DpStr=0;
+               *DpStr = 0;
 
-               pStr[k++]=0;
-               pStr[k]=0;
+               pStr[k++] = 0;
+               pStr[k] = 0;
 
-               if((ULONG)(DpStr-DescBuf+k) < *BufferSize)
-                       memcpy(pStr+k,DescBuf,DpStr-DescBuf);
-               else{
+               if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
+                       memcpy(pStr + k, DescBuf, DpStr - DescBuf);
+               } else {
                    GlobalFreePtr(OidData);
-                       GlobalFreePtr (BpStr);
-                       GlobalFreePtr (DescBuf);
+                       GlobalFreePtr(BpStr);
+                       GlobalFreePtr(DescBuf);
                        ODS("\nPacketGetAdapterNames: ended with failure\n");
                        return FALSE;
                }
 
            GlobalFreePtr(OidData);
-               GlobalFreePtr (BpStr);
-               GlobalFreePtr (DescBuf);
+               GlobalFreePtr(BpStr);
+               GlobalFreePtr(DescBuf);
                ODS("\nPacketGetAdapterNames: ended correctly\n");
                return TRUE;
        }
        else{
-           DWORD      RegType;
-
-               ODS("Adapters not found under SYSTEM\\CurrentControlSet\\Control\\Class. Using the TCP/IP bindings.\n");
+           DWORD RegType;
 
-               GlobalFreePtr (BpStr);
+               ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n");
 
-               Status=RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage"),0,KEY_READ,&LinkageKey);
-               if (Status == ERROR_SUCCESS)
-               {
+               GlobalFreePtr(BpStr);
+               Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                                               TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"),
+                                               0, KEY_READ, &LinkageKey);
+               if (Status == ERROR_SUCCESS) {
                        // Retrieve the length of the key
-                       Status=RegQueryValueEx(LinkageKey,TEXT("bind"),NULL,&RegType,NULL,&RegKeySize);
+                       Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize);
                        // Allocate the buffer
-                       BpStr=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,RegKeySize+2);
+                       BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2);
                        if (BpStr == NULL || RegKeySize > *BufferSize) {
                                GlobalFreePtr(OidData);
                                return FALSE;
                        }
-                       Status=RegQueryValueEx(LinkageKey,TEXT("bind"),NULL,&RegType,(LPBYTE)BpStr,&RegKeySize);
+                       Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize);
                        RegCloseKey(LinkageKey);
+               } else {
+            //ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n");
+            ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n");
                }
-               
-               if (Status==ERROR_SUCCESS){
-                       
-                       DescBuf=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
+               if (Status == ERROR_SUCCESS) {
+                       DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
                        if (DescBuf == NULL) {
-                               GlobalFreePtr (BpStr);
+                               GlobalFreePtr(BpStr);
                                GlobalFreePtr(OidData);
                                return FALSE;
                        }
-                       DpStr=DescBuf;
-                       
-                       for(i=0,k=0;BpStr[i]!=0 || BpStr[i+1]!=0;){
-                               
-                               if(k+wcslen(BpStr+i)+30 > *BufferSize){
+                       DpStr = DescBuf;
+                       for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) {
+                               if (k + wcslen(BpStr + i) + 30 > *BufferSize) {
                                        // Input buffer too small
                                        GlobalFreePtr(OidData);
-                                       GlobalFreePtr (BpStr);
-                                       GlobalFreePtr (DescBuf);
+                                       GlobalFreePtr(BpStr);
+                                       GlobalFreePtr(DescBuf);
                                        return FALSE;
                                }
-                               
+
+                               ODS("\tCreating a device name - started.\n");
+
                                // Create the device name
-                               rewind=k;
-                               memcpy(pStr+k,BpStr+i,16);
-                               memcpy(pStr+k+8,TEXT("Packet_"),14);
-                               i+=8;
-                               k+=15;
-                               while(BpStr[i-1]!=0){
-                                       pStr[k++]=BpStr[i++];
+                               rewind = k;
+                               memcpy(pStr + k,BpStr + i,16);
+                               memcpy(pStr + k + 8, TEXT("NPF_"), 8);
+                               i += 8;
+                               k += 12;
+                               while (BpStr[i - 1] != 0) {
+                                       pStr[k++] = BpStr[i++];
                                }
-                               
                                // Open the adapter
-                               adapter=PacketOpenAdapter(pStr+rewind);
-                               if(adapter==NULL){
-                                       k=rewind;
+                               adapter = PacketOpenAdapter(pStr+rewind);
+                               if (adapter == NULL) {
+                                       k = rewind;
                                        continue;
                                }
-                               
                                // Retrieve the description
                                OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
                                OidData->Length = 256;
-                               Status = PacketRequest(adapter,FALSE,OidData);
-                               if(Status==0 || ((char*)OidData->Data)[0]==0){
-                                       k=rewind;
+                               Status = PacketRequest(adapter, FALSE, OidData);
+                               if (Status == 0 || ((char*)OidData->Data)[0] == 0) {
+                                       k = rewind;
+                               ODS("\tCreating a device name - Retrieve the description.\n");
                                        continue;
                                }
                                
                                // Copy the description
-                               TTpStr=(char*)(OidData->Data);
-                               while(*TTpStr!=0){
-                                       *DpStr++=*TTpStr++;
+                               TTpStr = (char*)(OidData->Data);
+                               while (*TTpStr != 0){
+                                       *DpStr++ = *TTpStr++;
                                }
-                               *DpStr++=*TTpStr++;
-                               
+                               *DpStr++ = *TTpStr++;
                                // Close the adapter
                                PacketCloseAdapter(adapter);
-                               
+
+                               ODS("\tCreating a device name - completed.\n");
                        }
-                       *DpStr=0;
+                       *DpStr = 0;
                        
-                       pStr[k++]=0;
-                       pStr[k]=0;
+                       pStr[k++] = 0;
+                       pStr[k] = 0;
                        
-                       if((ULONG)(DpStr-DescBuf+k) < *BufferSize)
-                               memcpy(pStr+k,DescBuf,DpStr-DescBuf);
-                       else{
+                       if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
+                               memcpy(pStr + k, DescBuf, DpStr-DescBuf);
+                       } else {
                                GlobalFreePtr(OidData);
-                               GlobalFreePtr (BpStr);
-                               GlobalFreePtr (DescBuf);
+                               GlobalFreePtr(BpStr);
+                               GlobalFreePtr(DescBuf);
                                return FALSE;
                        }
                        
                        GlobalFreePtr(OidData);
-                       GlobalFreePtr (BpStr);
-                       GlobalFreePtr (DescBuf);
+                       GlobalFreePtr(BpStr);
+                       GlobalFreePtr(DescBuf);
+                       ODS("PacketGetAdapterNames() returning TRUE\n");
                        return TRUE;
-               }
-               else{
+               } else {
                        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);
-                       ODS("Cannot find the TCP/IP bindings");
+                       ODS("Cannot find the TCP/IP bindings\n");
                        return FALSE;
                }
        }
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Returns comprehensive information the addresses of an adapter.
+  \param AdapterName String that contain _ADAPTER structure.
+  \param buffer A user allocated array of npf_if_addr that will be filled by the function.
+  \param NEntries Size of the array (in npf_if_addr).
+  \return If the function succeeds, the return value is nonzero.
+
+  This function grabs from the registry information like the IP addresses, the netmasks 
+  and the broadcast addresses of an interface. The buffer passed by the user is filled with 
+  npf_if_addr structures, each of which contains the data for a single address. If the buffer
+  is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
+  if you want only the first address.
+*/
 
 BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
 {
@@ -1067,17 +1696,19 @@ BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntri
        } else {                                //Unicode
                AdapterNameU = NULL;
        }
-       ifname = wcsrchr(AdapterName, '\\');
+    ifname = wcsrchr(AdapterName, '\\');
        if (ifname == NULL)
                ifname = AdapterName;
        else
                ifname++;
-       if (wcsncmp(ifname, L"Packet_", 7) == 0)
-               ifname += 7;
+       if (wcsncmp(ifname, L"NPF_", 4) == 0)
+               ifname += 4;
 
-       if(     RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces"), 0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
+       if(     RegOpenKeyEx(HKEY_LOCAL_MACHINE, 
+                                               TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"),
+                                               0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
        {
-               status = RegOpenKeyEx(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
+               status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
                if (status != ERROR_SUCCESS) {
                        RegCloseKey(UnderTcpKey);
                        goto fail;
@@ -1087,10 +1718,12 @@ BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntri
        {
                
                // Query the registry key with the interface's adresses
-               status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SYSTEM\\CurrentControlSet"),0,KEY_READ,&SystemKey);
+               status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                                               TEXT("SYSTEM\\ControlSet001\\Services"),
+                                               0,KEY_READ,&SystemKey);
                if (status != ERROR_SUCCESS)
                        goto fail;
-               status = RegOpenKeyEx(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
+               status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
                if (status != ERROR_SUCCESS) {
                        RegCloseKey(SystemKey);
                        goto fail;
@@ -1277,7 +1910,15 @@ fail:
     return FALSE;
 }
 
-//---------------------------------------------------------------------------
+/*!
+  \brief Returns the IP address and the netmask of an adapter.
+  \param AdapterName String that contain _ADAPTER structure.
+  \param netp Pointer to a variable that will receive the IP address of the adapter.
+  \param maskp Pointer to a variable that will receive the netmask of the adapter.
+  \return If the function succeeds, the return value is nonzero.
+
+  \note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead. 
+*/
 
 BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
 {
@@ -1307,12 +1948,14 @@ BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
                ifname = AdapterName;
        else
                ifname++;
-       if (wcsncmp(ifname, L"Packet_", 7) == 0)
-               ifname += 7;
-       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("SYSTEM\\CurrentControlSet\\Services"),0,KEY_READ,&SystemKey);
+       if (wcsncmp(ifname, L"NPF_", 4) == 0)
+               ifname += 4;
+       status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                                               TEXT("SYSTEM\\ControlSet001\\Services"),
+                                               0,KEY_READ,&SystemKey);
        if (status != ERROR_SUCCESS)
                goto fail;
-       status = RegOpenKeyEx(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
+       status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
        if (status != ERROR_SUCCESS) {
                RegCloseKey(SystemKey);
                goto fail;
@@ -1409,3 +2052,5 @@ fail:
                free(AdapterNameU);
     return FALSE;
 }
+
+/* @} */
index 5431091..bcb167a 100644 (file)
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+/** @ingroup packetapi
+ *  @{ 
+ */
+
+/** @defgroup packet32h Packet.dll definitions and data structures
+ *  Packet32.h contains the data structures and the definitions used by packet.dll.
+ *  The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
+ *  by the applications that use the functions of this library
+ *  @{
+ */
+
 #ifndef __PACKET32
 #define __PACKET32
 
 #define IOCTL_OPEN                  CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
 #define IOCTL_CLOSE                 CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
 
-#define         pBIOCSETBUFFERSIZE 9592
-#define         pBIOCSETF 9030
-#define  pBIOCGSTATS 9031
-#define         pBIOCSRTIMEOUT 7416
-#define         pBIOCSMODE 7412
-#define         pBIOCSWRITEREP 7413
-#define         pBIOCSMINTOCOPY 7414
-#define         pBIOCSETOID 2147483648
-#define         pBIOCQUERYOID 2147483652
-#define         pATTACHPROCESS 7117
-#define         pDETACHPROCESS 7118
-#define  pBIOCSETDUMPFILENAME 9029
-#define  pBIOCEVNAME 7415
-
-#define  pBIOCSTIMEZONE 7471
-
-// Alignment macros.  Packet_WORDALIGN rounds up to the next 
-// even multiple of Packet_ALIGNMENT. 
+#define         pBIOCSETBUFFERSIZE 9592                ///< IOCTL code: set kernel buffer size.
+#define         pBIOCSETF 9030                                 ///< IOCTL code: set packet filtering program.
+#define  pBIOCGSTATS 9031                              ///< IOCTL code: get the capture stats.
+#define         pBIOCSRTIMEOUT 7416                    ///< IOCTL code: set the read timeout.
+#define         pBIOCSMODE 7412                                ///< IOCTL code: set working mode.
+#define         pBIOCSWRITEREP 7413                    ///< IOCTL code: set number of physical repetions of every packet written by the app.
+#define         pBIOCSMINTOCOPY 7414                   ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call.
+#define         pBIOCSETOID 2147483648                 ///< IOCTL code: set an OID value.
+#define         pBIOCQUERYOID 2147483652               ///< IOCTL code: get an OID value.
+#define         pATTACHPROCESS 7117                    ///< IOCTL code: attach a process to the driver. Used in Win9x only.
+#define         pDETACHPROCESS 7118                    ///< IOCTL code: detach a process from the driver. Used in Win9x only.
+#define  pBIOCSETDUMPFILENAME 9029             ///< IOCTL code: set the name of a the file used by kernel dump mode.
+#define  pBIOCEVNAME 7415                              ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer.
+#define  pBIOCSENDPACKETSNOSYNC 9032   ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets.
+#define  pBIOCSENDPACKETSSYNC 9033             ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets.
+#define  pBIOCSETDUMPLIMITS 9034               ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function.
+#define  pBIOCISDUMPENDED 7411                 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function.
+
+#define  pBIOCSTIMEZONE 7471                   ///< IOCTL code: set time zone. Used in Win9x only.
+
+
+/// Alignment macro. Defines the alignment size.
 #define Packet_ALIGNMENT sizeof(int)
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT. 
 #define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
 
+/*!
+  \brief Network type structure.
+
+  This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
+*/
 typedef struct NetType
 {
-       UINT LinkType;  
-       UINT LinkSpeed;
+       UINT LinkType;  ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
+       UINT LinkSpeed; ///< The speed of the network in bits per second
 }NetType;
 
 
@@ -74,75 +95,160 @@ typedef struct NetType
 
 #ifndef BPF_MAJOR_VERSION
 
+/*!
+  \brief A BPF pseudo-assembly program.
+
+  The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet. 
+*/
 struct bpf_program {
-       UINT bf_len;                            
-       struct bpf_insn *bf_insns;      
+       UINT bf_len;                            ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
+       struct bpf_insn *bf_insns;      ///< A pointer to the first instruction of the program.
 };
 
+/*!
+  \brief A single BPF pseudo-instruction.
+
+  bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
+*/
 struct bpf_insn {
-       USHORT  code;           
-       UCHAR   jt;                     
-       UCHAR   jf;                     
-       int k;                          
+       USHORT  code;           ///< Instruction type and addressing mode.
+       UCHAR   jt;                     ///< Jump if true
+       UCHAR   jf;                     ///< Jump if false
+       int k;                          ///< Generic field used for various purposes.
 };
 
+/*!
+  \brief Structure that contains a couple of statistics values on the current capture.
+
+  It is used by packet.dll to return statistics about a capture session.
+*/
 struct bpf_stat {
-       UINT bs_recv;           
+       UINT bs_recv;           ///< Number of packets that the driver received from the network adapter 
+                                               ///< from the beginning of the current capture. This value includes the packets 
+                                               ///< lost by the driver.
+       UINT bs_drop;           ///< number of packets that the driver lost from the beginning of a capture. 
+                                               ///< Basically, a packet is lost when the the buffer of the driver is full. 
+                                               ///< In this situation the packet cannot be stored and the driver rejects it.
+       UINT ps_ifdrop;         ///< drops by interface. XXX not yet supported
+       UINT bs_capt;           ///< number of packets that pass the filter, find place in the kernel buffer and
+                                               ///< thus reach the application.
+};
                                                
+/*!
+  \brief Packet header.
                                                
-       UINT bs_drop;           
+  This structure defines the header associated with every packet delivered to the application.
+*/
+struct bpf_hdr {
+       struct timeval  bh_tstamp;      ///< The timestamp associated with the captured packet. 
+                                                               ///< It is stored in a TimeVal structure.
+       UINT    bh_caplen;                      ///< Length of captured portion. The captured portion <b>can be different</b>
+                                                               ///< from the original packet, because it is possible (with a proper filter)
+                                                               ///< to instruct the driver to capture only a portion of the packets.
+       UINT    bh_datalen;                     ///< Original length of packet
+       USHORT          bh_hdrlen;              ///< Length of bpf header (this struct plus alignment padding). In some cases,
+                                                               ///< a padding could be added between the end of this structure and the packet
+                                                               ///< data for performance reasons. This filed can be used to retrieve the actual data 
+                                                               ///< of the packet.
+};
                                                
+/*!
+  \brief Dump packet header.
                                                
+  This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
+  It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
+  packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
+*/
+struct dump_bpf_hdr{
+    struct timeval     ts;                     ///< Time stamp of the packet
+    UINT                       caplen;         ///< Length of captured portion. The captured portion can smaller than the 
+                                                               ///< the original packet, because it is possible (with a proper filter) to 
+                                                               ///< instruct the driver to capture only a portion of the packets. 
+    UINT                       len;            ///< Length of the original packet (off wire).
 };
 
-struct bpf_hdr {
-       struct timeval  bh_tstamp;      
-       UINT    bh_caplen;                      
-       UINT    bh_datalen;                     
-       USHORT          bh_hdrlen;                                                                              
-};
 
 #endif
 
-#define        DOSNAMEPREFIX   TEXT("Packet_")
-#define        MAX_LINK_NAME_LENGTH   64
+#define        DOSNAMEPREFIX   TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
+#define        MAX_LINK_NAME_LENGTH    64                      //< Maximum length of the devices symbolic links
 #define        NMAX_PACKET 65535  
 
+/*!
+  \brief Describes a network adapter.
+
+  This structure is the most important for the functioning of packet.dll, but the great part of its fields
+  should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
+*/
 typedef struct _ADAPTER  { 
-       HANDLE hFile;                           
-       TCHAR  SymbolicLink[MAX_LINK_NAME_LENGTH]; 
-       int NumWrites;                          
-       HANDLE ReadEvent;                       
-       UINT ReadTimeOut;                       
+       HANDLE hFile;                           ///< \internal Handle to an open instance of the NPF driver.
+       CHAR  SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
+       int NumWrites;                          ///< \internal Number of times a packets written on this adapter will be repeated 
+                                                               ///< on the wire.
+       HANDLE ReadEvent;                       ///< A notification event associated with the read calls on the adapter.
+                                                               ///< It can be passed to standard Win32 functions (like WaitForSingleObject
+                                                               ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some 
+                                                               ///< data. It is particularly useful in GUI applications that need to wait 
+                                                               ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
+                                                               ///< function can be used to define the minimum amount of data in the kernel buffer
+                                                               ///< that will cause the event to be signalled. 
+       
+       UINT ReadTimeOut;                       ///< \internal The amount of time after which a read on the driver will be released and 
+                                                               ///< ReadEvent will be signaled, also if no packets were captured
 }  ADAPTER, *LPADAPTER;
 
+/*!
+  \brief Structure that contains a group of packets coming from the driver.
+
+  This structure defines the header associated with every packet delivered to the application.
+*/
 typedef struct _PACKET {  
-       HANDLE       hEvent;            
-       OVERLAPPED   OverLapped;        
-       PVOID        Buffer;                                                                            
-       UINT         Length;            
-       UINT         ulBytesReceived;                                                                           
-       BOOLEAN      bIoComplete;       
+       HANDLE       hEvent;            ///< \deprecated Still present for compatibility with old applications.
+       OVERLAPPED   OverLapped;        ///< \deprecated Still present for compatibility with old applications.
+       PVOID        Buffer;            ///< Buffer with containing the packets. See the PacketReceivePacket() for
+                                                               ///< details about the organization of the data in this buffer
+       UINT         Length;            ///< Length of the buffer
+       DWORD        ulBytesReceived;   ///< Number of valid bytes present in the buffer, i.e. amount of data
+                                                                       ///< received by the last call to PacketReceivePacket()
+       BOOLEAN      bIoComplete;       ///< \deprecated Still present for compatibility with old applications.
 }  PACKET, *LPPACKET;
 
-struct _PACKET_OID_DATA {
-    ULONG Oid;                                 
-    ULONG Length;                              
-    UCHAR Data[1];                             
+/*!
+  \brief Structure containing an OID request.
                                                                
+  It is used by the PacketRequest() function to send an OID to the interface card driver. 
+  It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address, 
+  the list of the multicast groups defined on it, and so on.
+*/
+struct _PACKET_OID_DATA {
+    ULONG Oid;                                 ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+                                                               ///< for a complete list of valid codes.
+    ULONG Length;                              ///< Length of the data field
+    UCHAR Data[1];                             ///< variable-lenght field that contains the information passed to or received 
+                                                               ///< from the adapter.
 }; 
 typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
 
+/*!
+  \brief Addresses of a network adapter.
+
+  This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with 
+  an adapter.
+*/
 typedef struct npf_if_addr {
-       struct sockaddr IPAddress;      
-       struct sockaddr SubnetMask;     
-       struct sockaddr Broadcast;      
+       struct sockaddr IPAddress;      ///< IP address.
+       struct sockaddr SubnetMask;     ///< Netmask for that address.
+       struct sockaddr Broadcast;      ///< Broadcast address.
 }npf_if_addr;
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/**
+ *  @}
+ */
+
 //---------------------------------------------------------------------------
 // FUNCTIONS
 //---------------------------------------------------------------------------
@@ -154,10 +260,12 @@ BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
 BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
 BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
 BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
 BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
 BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
 LPADAPTER PacketOpenAdapter(LPTSTR AdapterName);
 BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
 LPPACKET PacketAllocatePacket(void);
 VOID PacketInitPacket(LPPACKET lpPacket,PVOID  Buffer,UINT  Length);
 VOID PacketFreePacket(LPPACKET lpPacket);
@@ -169,6 +277,8 @@ BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntri
 BOOLEAN PacketRequest(LPADAPTER  AdapterObject,BOOLEAN Set,PPACKET_OID_DATA  OidData);
 HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
 BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
 BOOL PacketStopDriver();
 VOID PacketCloseAdapter(LPADAPTER lpAdapter);
 
index ac38a9a..2717e16 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: makefile,v 1.2 2002/08/17 15:58:38 robd Exp $
+# $Id: makefile,v 1.3 2002/09/24 15:08:14 robd Exp $
 
 PATH_TO_TOP = ../..
 
@@ -8,12 +8,13 @@ TARGET_NAME = packet
 
 TARGET_BASE = 0x77780000
 
-TARGET_CFLAGS = -I./include -DUNICODE -DLE -DDBG
+TARGET_CFLAGS = -I./include -DUNICODE -D_UNICODE -DLE -DDBG -D_DEBUG
 
 TARGET_SDKLIBS = ntdll.a kernel32.a advapi32.a
 
 TARGET_OBJECTS = \
-    Packet32.o
+       Packet32.o \
+       trace.o
 
 TARGET_CLEAN = $(TARGET_OBJECTS)
 
index f761908..bba1a4c 100644 (file)
@@ -3,27 +3,32 @@ LIBRARY packet
 DESCRIPTION 'Packet driver dll'
 
 EXPORTS
-PacketLibraryVersion
-PacketGetVersion
-PacketOpenAdapter
-PacketSendPacket
-PacketAllocatePacket
-PacketInitPacket
-PacketFreePacket
-PacketReceivePacket
-PacketCloseAdapter
-PacketSetHwFilter
-PacketGetAdapterNames
-PacketRequest
-PacketSetBuff
-PacketSetBpf
-PacketGetStats
-PacketGetNetType
-PacketSetReadTimeout
-PacketSetMode
-PacketSetNumWrites
-PacketGetNetInfo
-PacketGetNetInfoEx
-PacketSetMinToCopy
-PacketGetReadEvent
-PacketStopDriver
+               PacketLibraryVersion
+               PacketGetVersion
+               PacketOpenAdapter
+               PacketSendPacket
+               PacketSendPackets
+               PacketAllocatePacket
+               PacketInitPacket
+               PacketFreePacket
+               PacketReceivePacket
+               PacketCloseAdapter
+               PacketSetHwFilter
+               PacketGetAdapterNames
+               PacketRequest
+               PacketSetBuff
+               PacketSetBpf
+               PacketGetStats
+               PacketGetStatsEx
+               PacketGetNetType
+               PacketSetReadTimeout
+               PacketSetMode
+               PacketSetNumWrites
+               PacketGetNetInfo
+               PacketGetNetInfoEx
+               PacketSetMinToCopy
+               PacketGetReadEvent
+               PacketStopDriver
+               PacketSetDumpName
+               PacketSetDumpLimits
+               PacketIsDumpEnded
diff --git a/reactos/lib/packet/trace.c b/reactos/lib/packet/trace.c
new file mode 100644 (file)
index 0000000..8104ebc
--- /dev/null
@@ -0,0 +1,53 @@
+/////////////////////////////////////////////////////////////////////////////
+// Diagnostic Trace
+//
+#include <stdio.h> 
+#include <stdarg.h>
+#include <windows.h>
+//#include <tchar.h>
+#include "trace.h"
+
+#ifdef _DEBUG
+
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+
+void _DebugBreak(void)
+{
+    DebugBreak();
+}
+
+//void Trace(TCHAR* lpszFormat, ...)
+void Trace(char* lpszFormat, ...)
+{
+    va_list args;
+    int nBuf;
+    char szBuffer[512];
+
+    va_start(args, lpszFormat);
+    nBuf = _vsnprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR), lpszFormat, args);
+    OutputDebugStringA(szBuffer);
+    // was there an error? was the expanded string too long?
+    //ASSERT(nBuf >= 0);
+    va_end(args);
+}
+
+void Assert(void* assert, const char* file, int line, void* msg)
+{
+    if (msg == NULL) {
+        printf("ASSERT -- %s occured on line %u of file %s.\n",
+               assert, line, file);
+    } else {
+        printf("ASSERT -- %s occured on line %u of file %s: Message = %s.\n",
+               assert, line, file, msg);
+    }
+}
+
+#else
+
+//void Trace(TCHAR* lpszFormat, ...) { };
+void Trace(char* lpszFormat, ...) { };
+void Assert(void* assert, const char* file, int line, void* msg) { };
+
+#endif //_DEBUG
+/////////////////////////////////////////////////////////////////////////////
diff --git a/reactos/lib/packet/trace.h b/reactos/lib/packet/trace.h
new file mode 100644 (file)
index 0000000..a227b16
--- /dev/null
@@ -0,0 +1,62 @@
+/////////////////////////////////////////////////////////////////////////////
+// Diagnostic Trace
+//
+#ifndef __TRACE_H__
+#define __TRACE_H__
+
+#ifdef _DEBUG
+
+#ifdef _X86_
+#define BreakPoint()        _asm { int 3h }
+#else
+#define BreakPoint()        _DebugBreak()
+#endif
+
+#ifndef ASSERT
+#define ASSERT(exp)                                 \
+{                                                   \
+    if (!(exp)) {                                   \
+        Assert(#exp, __FILE__, __LINE__, NULL);     \
+        BreakPoint();                               \
+    }                                               \
+}                                                   \
+
+#define ASSERTMSG(exp, msg)                         \
+{                                                   \
+    if (!(exp)) {                                   \
+        Assert(#exp, __FILE__, __LINE__, msg);      \
+        BreakPoint();                               \
+    }                                               \
+}
+#endif
+
+//=============================================================================
+//  MACRO: TRACE()
+//=============================================================================
+
+#define TRACE  Trace
+
+
+#else   // _DEBUG
+
+//=============================================================================
+//  Define away MACRO's ASSERT() and TRACE() in non debug builds
+//=============================================================================
+
+#ifndef ASSERT
+#define ASSERT(exp)
+#define ASSERTMSG(exp, msg)
+#endif
+
+#define TRACE 0 ? (void)0 : Trace
+
+#endif // !_DEBUG
+
+
+void Assert(void* assert, const char* file, int line, void* msg);
+//void Trace(TCHAR* lpszFormat, ...);
+void Trace(char* lpszFormat, ...);
+
+
+#endif // __TRACE_H__
+/////////////////////////////////////////////////////////////////////////////