193 lines
5.9 KiB
C
193 lines
5.9 KiB
C
#include <precomp.h>
|
|
#include "tracing.h"
|
|
#include "utils.h"
|
|
#include "intflist.h"
|
|
#include "intfhdl.h"
|
|
|
|
DWORD
|
|
OpenIntfHandle(
|
|
LPWSTR wszGuid,
|
|
PHANDLE pIntfHdl)
|
|
{
|
|
DWORD dwErr;
|
|
PHASH_NODE pNode;
|
|
PHSH_HANDLE pHshHandle;
|
|
|
|
DbgPrint((TRC_TRACK,"[OpenIntfHandle(%S)", wszGuid));
|
|
|
|
// the caller is supposed to expect the handle in return
|
|
// if he doesn't, return with INVALID_PARAMETER.
|
|
if (pIntfHdl == NULL)
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// lock the hash, to mutual exclude concurrent calls
|
|
EnterCriticalSection(&g_hshHandles.csMutex);
|
|
|
|
// query the hash for the guid.
|
|
dwErr = HshQueryObjectRef(
|
|
g_hshHandles.pRoot,
|
|
wszGuid,
|
|
&pNode);
|
|
|
|
// if the guid in the hash, we already have the handle opened..
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// return it to the caller and bump up the reference counter.
|
|
// the caller is still supposed to close this handle when it is
|
|
// no longer needed
|
|
pHshHandle = (PHSH_HANDLE)pNode->pObject;
|
|
pHshHandle->nRefCount++;
|
|
*pIntfHdl = pHshHandle->hdlInterf;
|
|
DbgPrint((TRC_GENERIC, "OpenIntfHandle -> 0x%x (cached)", *pIntfHdl));
|
|
}
|
|
// if the guid is not in the hash, we need to open a new handle for
|
|
// this guid.
|
|
else if (dwErr == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
HANDLE IntfHdl = INVALID_HANDLE_VALUE;
|
|
DWORD dwDummy;
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
// first allocate memory for the HSH_HANDLE object.
|
|
// if this fails no need to go further to ndisuio
|
|
pHshHandle = MemCAlloc(sizeof(HSH_HANDLE));
|
|
if (pHshHandle == NULL)
|
|
dwErr = GetLastError();
|
|
|
|
// if everything looks fine so far
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// create the handle
|
|
IntfHdl = CreateFileA(
|
|
"\\\\.\\\\Ndisuio",
|
|
GENERIC_READ | GENERIC_WRITE,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
|
INVALID_HANDLE_VALUE);
|
|
if (IntfHdl == INVALID_HANDLE_VALUE)
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR,"CreateFileA failed with %d", dwErr));
|
|
}
|
|
}
|
|
|
|
// if still fine so far
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// attempt to open the handle
|
|
if (!DeviceIoControl(
|
|
IntfHdl,
|
|
IOCTL_NDISUIO_OPEN_DEVICE,
|
|
(LPVOID)wszGuid,
|
|
wcslen(wszGuid)*sizeof(WCHAR),
|
|
NULL,
|
|
0,
|
|
&dwDummy,
|
|
NULL))
|
|
{
|
|
dwErr = GetLastError();
|
|
DbgPrint((TRC_ERR,"IOCTL_NDISUIO_OPEN_DEVICE failed with %d", dwErr));
|
|
}
|
|
}
|
|
|
|
// if finally we're ok here,
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// set up the HSH_HANDLE structure and insert it in the hash
|
|
pHshHandle->hdlInterf = IntfHdl;
|
|
pHshHandle->nRefCount = 1;
|
|
|
|
dwErr = HshInsertObjectRef(
|
|
g_hshHandles.pRoot,
|
|
wszGuid,
|
|
pHshHandle,
|
|
&g_hshHandles.pRoot);
|
|
}
|
|
|
|
// if ok at the end, return the handle to the caller
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
DbgPrint((TRC_GENERIC, "OpenIntfHandle -> 0x%x (new)", IntfHdl));
|
|
*pIntfHdl = IntfHdl;
|
|
}
|
|
// otherwise clear up all resources
|
|
else
|
|
{
|
|
if (IntfHdl != INVALID_HANDLE_VALUE)
|
|
CloseHandle(IntfHdl);
|
|
MemFree(pHshHandle);
|
|
}
|
|
}
|
|
// out of critical section
|
|
LeaveCriticalSection(&g_hshHandles.csMutex);
|
|
|
|
exit:
|
|
DbgPrint((TRC_TRACK,"OpenIntfHandle]=%d", dwErr));
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
CloseIntfHandle(
|
|
LPWSTR wszGuid)
|
|
{
|
|
DWORD dwErr;
|
|
PHASH_NODE pNode;
|
|
|
|
DbgPrint((TRC_TRACK,"[CloseIntfHandle(%S)", wszGuid));
|
|
|
|
// lock the hash
|
|
EnterCriticalSection(&g_hshHandles.csMutex);
|
|
|
|
// query the hash for the guid.
|
|
dwErr = HshQueryObjectRef(
|
|
g_hshHandles.pRoot,
|
|
wszGuid,
|
|
&pNode);
|
|
// the object should be found.. but who knows
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
PHSH_HANDLE pHshHandle;
|
|
|
|
// the hash refuses to hash in NULL pObjects, so pHshHandle is guaranteed to be not NULL
|
|
pHshHandle = (PHSH_HANDLE)pNode->pObject;
|
|
// HshHandles are hashed in with a refCount of 1, and whenever we remove a handle
|
|
// if the ref count reaches 0 we delete it entirely.
|
|
// Having here a <=0 ref count is completely wrong.
|
|
DbgAssert((pHshHandle->nRefCount > 0, "Corrupted nRefCount %d", pHshHandle->nRefCount));
|
|
pHshHandle->nRefCount--;
|
|
|
|
// if the ref count reached 0, remove the HSH_HANDLE from the hash..
|
|
if (pHshHandle->nRefCount == 0)
|
|
{
|
|
dwErr = HshRemoveObjectRef(
|
|
g_hshHandles.pRoot,
|
|
pNode,
|
|
&pHshHandle,
|
|
&g_hshHandles.pRoot);
|
|
if (dwErr == ERROR_SUCCESS)
|
|
{
|
|
// .. and clear all associated resources
|
|
DbgPrint((TRC_GENERIC,"CloseIntfHandle -> 0x%x (closed)", pHshHandle->hdlInterf));
|
|
CloseHandle(pHshHandle->hdlInterf);
|
|
MemFree(pHshHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgPrint((TRC_GENERIC,"CloseIntfHandle -> 0x%x (deref)", pHshHandle->hdlInterf));
|
|
}
|
|
}
|
|
|
|
LeaveCriticalSection(&g_hshHandles.csMutex);
|
|
|
|
DbgPrint((TRC_TRACK,"CloseIntfHandle]=%d", dwErr));
|
|
|
|
return dwErr;
|
|
}
|