#define UNICODE 1
#define _DBG 0
#define _DEBUG_TO_FILE 0
#define _DEBUGFILE "winpcap_debug.txt"
#include "packet32.h"
#include "stdio.h"
#include "winsock2.h"
#include "windowsx.h"
#include "psapi.h"
//#include <ntddndis.h>
#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
#define OID_GEN_LINK_SPEED 0x00010107
#define OID_GEN_MEDIA_IN_USE 0x00010104
/// Title of error windows
TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
#if _DBG
//#define ODS(_x) OutputDebugString(TEXT(_x))
#define ODS(_x) printf("%s",_x);
#define ODSEx(_x, _y) printf(_x,_y);
#else
#if _DEBUG_TO_FILE
#define ODS(_x) { \
FILE *f; \
f = fopen(_DEBUGFILE, "a"); \
fprintf(f, "%s", _x); \
fclose(f); \
}
#define ODSEx(_x, _y) { \
FILE *f; \
f = fopen(_DEBUGFILE, "a"); \
fprintf(f, _x, _y); \
fclose(f); \
}
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
#else
#define ODS(_x)
#define ODSEx(_x, _y)
#endif
#endif
//service handles
SC_HANDLE scmHandle = NULL;
SC_HANDLE srvHandle = NULL;
LPCTSTR NPFServiceName = TEXT("NPF");
LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\CurrentControlSet\\Services\\NPF");
LPCTSTR NPFDriverPath = TEXT("system32\\drivers\\npf.sys");
//---------------------------------------------------------------------------
/*!
\brief The main dll function.
*/
/*!
\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)
{
WCHAR* TmpStr;
TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
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)
{
BOOLEAN Status;
ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
PPACKET_OID_DATA OidData;
OidData=(PPACKET_OID_DATA)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
if (OidData == NULL) {
ODS("PacketSetMaxLookaheadsize failed\n");
return FALSE;
}
//set the size of the lookahead buffer to the maximum available by the the NIC driver
OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
OidData->Length=sizeof(ULONG);
Status=PacketRequest(AdapterObject,FALSE,OidData);
OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
Status=PacketRequest(AdapterObject,TRUE,OidData);
GlobalFreePtr(OidData);
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];
// this tells the terminal service to retrieve the event from the global namespace
wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
// retrieve the name of the shared event from the driver
if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
EventName[20]=0; // terminate the string
// open the shared event
AdapterObject->ReadEvent=CreateEvent(NULL,
TRUE,
FALSE,
EventName);
// in NT4 "Global\" is not automatically ignored: try to use simply the event name
if(GetLastError()!=ERROR_ALREADY_EXISTS){
if(AdapterObject->ReadEvent != NULL)
CloseHandle(AdapterObject->ReadEvent);
// open the shared event
AdapterObject->ReadEvent=CreateEvent(NULL,
TRUE,
FALSE,
EventName+7);
}
if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
return FALSE;
}
AdapterObject->ReadTimeOut=0;
return TRUE;
}
/*!
\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.
\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)
{
BOOL result = FALSE;
ULONG err;
ODS("installdriver\n");
//原来的程序在服务存在的时候就直接返回TRUE,而不管注册表里是否存在,现在改为先删除原来的服务
SC_HANDLE hSrv = OpenService(scmHandle, NPFServiceName, SERVICE_ALL_ACCESS);
if(hSrv)
{
DeleteService(hSrv);
CloseServiceHandle(hSrv);
}
//////////////////////////
*srvHandle = CreateService(ascmHandle,
NPFServiceName,
NPFServiceDesc,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
NPFDriverPath,
NULL, NULL, NULL, NULL, NULL);
if (*srvHandle == NULL)
{
if (GetLastError() == ERROR_SERVICE_EXISTS)
{
//npf.sys already existed
result = TRUE;
}
}
else
{
//Created service for npf.sys
result = TRUE;
}
if (result == TRUE)
if (*srvHandle != NULL)
CloseServiceHandle(*srvHandle);
if(result == FALSE){
err = GetLastError();
// 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)
{
ULONG val, part;
WCHAR c;
int i;
val = 0;
for (i = 0; i < 4; i++) {
part = 0;
while ((c = *cp++) != '\0' && c != '.') {
if (c < '0' || c > '9')
return -1;
part = part*10 + (c - '0');
}
if (part > 255)
return -1;
val = val | (part << i*8);
if (i == 3) {
if (c != '\0')
return -1; // extra gunk at end of string
} else {
if (c == '\0')
return -1; // string ends early
}
}
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
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
{
CHAR Command[256];
strcpy(Command, "regedit /e ");
strcat(Command, FileName);
strcat(Command, " ");
strcat(Command, KeyName);
/// Let regedit do the dirt work for us
system(Command);
return TRUE;
}
#endif
//---------------------------------------------------------------------------
// PUBLIC API
//---------------------------------------------------------------------------
/** @ingroup packetapi
* @{
*/
/** @defgroup packe