📄 wanpacket.cpp
字号:
HRESULT hResult;
DWORD i;
if ( g_hModule == NULL)
{
g_hModule = LoadLibrary("npp\\ndisnpp.dll");
}
if ( g_hModule == NULL)
{
return NULL;
}
hResult = CoInitialize(NULL);
//
// if the calling thread has already initialized COM with a
// different threading model, we have this error
// however, we are able to support another threading model,
// so we try to initialize COM with another threading model.
// This new call should succeed with S_FALSE.
//
if (hResult == RPC_E_CHANGED_MODE)
{
hResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
//MULTITHREADED threading is only supported on Windows 2000
if (hResult == RPC_E_CHANGED_MODE && IsWindows2000())
{
hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
}
if (hResult != S_OK && hResult != S_FALSE)
return NULL;
pWanAdapter = (PWAN_ADAPTER)GlobalAlloc(GPTR, sizeof (WAN_ADAPTER));
if ( pWanAdapter == NULL )
goto error;
memset(pWanAdapter, 0, sizeof(WAN_ADAPTER));
if ( CreateBlob(&hFilterBlob) != NMERR_SUCCESS )
{
goto error;
}
if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_CONFIG, TAG_INTERFACE_REALTIME_CAPTURE, TRUE) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
goto error;
}
if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_LOCATION, TAG_RAS, TRUE) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
goto error;
}
if ( GetNPPBlobTable(hFilterBlob, &pBlobTable) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
goto error;
}
DestroyBlob (hFilterBlob);
if ( pBlobTable->dwNumBlobs == 0 || pBlobTable->dwNumBlobs > 1)
{
///fixme.....
for ( i = 0 ; i < pBlobTable->dwNumBlobs ; i++ )
DestroyBlob(pBlobTable->hBlobs[i]);
GlobalFree(pBlobTable);
goto error;
}
pWanAdapter->hCaptureBlob = pBlobTable->hBlobs[0];
GlobalFree(pBlobTable);
InitializeCriticalSection(&pWanAdapter->CriticalSection);
pWanAdapter->hReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if ( pWanAdapter->hReadEvent == NULL )
goto error;
pWanAdapter->MemEx.buffer = (PUCHAR)GlobalAlloc(GPTR, DEFAULT_MEM_EX_SIZE);
if (pWanAdapter->MemEx.buffer == NULL)
goto error;
pWanAdapter->MemEx.size = DEFAULT_MEM_EX_SIZE;
pWanAdapter->Tme.active = TME_NONE_ACTIVE;
if (CreateNPPInterface(pWanAdapter->hCaptureBlob, IID_IRTC, (void**) &pWanAdapter->pIRTC) == NMERR_SUCCESS && pWanAdapter->pIRTC != NULL)
{
//create OK
if (pWanAdapter->pIRTC->Connect(pWanAdapter->hCaptureBlob, NULL, WanPacketReceiverCallback, (LPVOID)pWanAdapter , NULL) == NMERR_SUCCESS)
{
//connect OK
if (pWanAdapter->pIRTC->Start() == NMERR_SUCCESS)
{
return pWanAdapter;
}
else
{
pWanAdapter->pIRTC->Disconnect();
pWanAdapter->pIRTC->Release();
goto error;
}
}
else
{
pWanAdapter->pIRTC->Release();
goto error;
}
}
else
{
goto error;
}
//awfully never reached
// return NULL;
error:
if (pWanAdapter != NULL)
{
if (pWanAdapter->hReadEvent != NULL)
CloseHandle(pWanAdapter->hReadEvent);
DeleteCriticalSection(&pWanAdapter->CriticalSection);
if (pWanAdapter->hCaptureBlob)
DestroyBlob(pWanAdapter->hCaptureBlob);
GlobalFree(pWanAdapter);
}
CoUninitialize();
return NULL;
}
/*!
\brief Closes a wan (dialup, vpn...) adapter.
\param lpWanAdapter the pointer to the wan adapter to close.
WanPacketCloseAdapter closes the given adapter and frees the associated WAN_ADAPTER structure
*/
BOOLEAN WanPacketCloseAdapter(PWAN_ADAPTER pWanAdapter)
{
if (pWanAdapter->pIRTC->Stop() != NMERR_SUCCESS)
OutputDebugString("WanPacketCloseAdapter: Severe error, IRTC::Stop failed\n");
if (pWanAdapter->pIRTC->Disconnect() != NMERR_SUCCESS)
OutputDebugString("WanPacketCloseAdapter: Severe error, IRTC::Disconnect failed\n");
if (pWanAdapter->pIRTC->Release() != NMERR_SUCCESS)
OutputDebugString("WanPacketCloseAdapter: Severe error, IRTC::Release failed\n");
Sleep(0); //Just a stupid hack to make all the stuff work. I don't why it's necessary.
//setting a NULL filter will actually deallocate the in-use filter
WanPacketSetBpfFilter(pWanAdapter, NULL, 0);
//setting a zero-sized buffer will deallocate any in-use ring buffer
WanPacketSetBufferSize(pWanAdapter, 0);
CloseHandle(pWanAdapter->hReadEvent);
//destroy the BLOB used to capture
DestroyBlob(pWanAdapter->hCaptureBlob);
DeleteCriticalSection(&pWanAdapter->CriticalSection);
//deallocate the extended memory, if any.
if (pWanAdapter->MemEx.size > 0)
GlobalFree(pWanAdapter->MemEx.buffer);
GlobalFree(pWanAdapter);
//uninitialize COM
CoUninitialize();
return TRUE;
}
/*!
\brief Sets the working mode of a wan (dialup, vpn...) adapter.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param mode The new working mode of the adapter.
\return If the function succeeds, the return value is true.
For more information, see the documentation of PacketSetMode
*/
BOOLEAN WanPacketSetMode(PWAN_ADAPTER pWanAdapter, DWORD Mode)
{
if (Mode != PACKET_MODE_CAPT && Mode != PACKET_MODE_STAT && Mode != PACKET_MODE_MON)
return FALSE;
pWanAdapter->Mode = Mode;
return TRUE;
}
/*!
\brief Sets the bpf packet filter.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param FilterCode Pointer to the BPF filtering code that will be associated with this capture or monitoring
instance and that will be executed on every incoming packet.
\param Length Length, in bytes, of the BPF filter code.
\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. This API
performs the check in order to avoid unexpected behavior due to buggy or malicious filters, and it rejects non
conformant filters.
For more information, see the documentation of PacketSetBpf
*/
BOOLEAN WanPacketSetBpfFilter(PWAN_ADAPTER pWanAdapter, PUCHAR FilterCode, DWORD Length)
{
PUCHAR NewFilterCode = NULL;
DWORD NumberOfInstructions;
DWORD Counter;
struct bpf_insn *InitializationCode;
struct time_conv TimeConv;
if ( Length < 0)
return FALSE;
EnterCriticalSection(&pWanAdapter->CriticalSection);
if (Length > 0)
{
NumberOfInstructions = Length/sizeof(struct bpf_insn);
for(Counter = 0;
Counter < NumberOfInstructions && ((struct bpf_insn*)FilterCode)[Counter].code != BPF_SEPARATION ;
Counter++);
if ( Counter != NumberOfInstructions &&
NumberOfInstructions != Counter + 1 &&
((struct bpf_insn*)FilterCode)[Counter].code == BPF_SEPARATION )
{
//we need to initialize the TME
InitializationCode = &((struct bpf_insn*)FilterCode)[Counter+1];
//FIXME, just an hack, this structure is never used here.
TimeConv.start[0].tv_sec = 0;
TimeConv.start[0].tv_usec = 0;
if ( bpf_filter_init(InitializationCode,
&pWanAdapter->MemEx,
&pWanAdapter->Tme,
&TimeConv) != INIT_OK )
{
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return FALSE;
}
}
NumberOfInstructions = Counter;
if ( bpf_validate((struct bpf_insn*)FilterCode, Counter, pWanAdapter->MemEx.size) == 0)
{
//filter not validated
//FIXME: the machine has been initialized(?), but the operative code is wrong.
//we have to reset the machine!
//something like: reallocate the mem_ex, and reset the tme_core
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return FALSE;
}
NewFilterCode = (PUCHAR)GlobalAlloc( GMEM_FIXED, Counter * sizeof(struct bpf_insn) );
if (NewFilterCode == NULL)
{
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return FALSE;
}
RtlCopyMemory(NewFilterCode, FilterCode, Counter * sizeof(struct bpf_insn));
}
if ( pWanAdapter->FilterCode != NULL )
GlobalFree(pWanAdapter->FilterCode);
pWanAdapter->FilterCode = (struct bpf_insn*)NewFilterCode;
//we reset all the ring buffer related counters.
pWanAdapter->C = 0;
pWanAdapter->P = 0;
pWanAdapter->Free = pWanAdapter->Size;
pWanAdapter->Accepted = 0;
pWanAdapter->Dropped = 0;
pWanAdapter->Received = 0;
pWanAdapter->Nbytes.QuadPart = 0;
pWanAdapter->Npackets.QuadPart = 0;
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return TRUE;
}
/*!
\brief Sets the size of the ring buffer associated with this instance.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param BufferSize 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.
For more information, see the documentation of PacketSetBuff
*/
BOOLEAN WanPacketSetBufferSize(PWAN_ADAPTER pWanAdapter, DWORD BufferSize)
{
PUCHAR NewBuffer = NULL;
if ( BufferSize < 0 || ( BufferSize > 0 && BufferSize < sizeof (struct bpf_hdr) ) )
return FALSE;
if ( BufferSize > 0 )
{
NewBuffer = (PUCHAR)GlobalAlloc( GMEM_FIXED, BufferSize );
if (NewBuffer == NULL)
return FALSE;
}
EnterCriticalSection(&pWanAdapter->CriticalSection);
if ( pWanAdapter->Buffer != NULL )
GlobalFree(pWanAdapter->Buffer);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -