You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
653 lines
17 KiB
653 lines
17 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: HandleTracking.cpp
|
|
* Content: Handle Tracking debug logic
|
|
*
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 10/31/2001 masonb Created
|
|
*
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "dncmni.h"
|
|
|
|
|
|
#ifdef DBG
|
|
|
|
CBilink g_blHandles;
|
|
#ifndef DPNBUILD_ONLYONETHREAD
|
|
DNCRITICAL_SECTION g_HandleLock;
|
|
#endif // !DPNBUILD_ONLYONETHREAD
|
|
|
|
#define IsValidHandle(x) \
|
|
(x != NULL && x != INVALID_HANDLE_VALUE && \
|
|
(x->type == TypeEvent || \
|
|
x->type == TypeMutex || \
|
|
x->type == TypeSemaphore || \
|
|
x->type == TypeFile || \
|
|
x->type == TypeFileMap || \
|
|
x->type == TypeThread || \
|
|
x->type == TypeProcess || \
|
|
x->type == TypeSpecial))
|
|
|
|
BOOL DNHandleTrackInitialize()
|
|
{
|
|
g_blHandles.Initialize();
|
|
return DNInitializeCriticalSection(&g_HandleLock);
|
|
}
|
|
|
|
VOID DNHandleTrackDeinitialize()
|
|
{
|
|
DNDeleteCriticalSection(&g_HandleLock);
|
|
}
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "DNHandleTrackDumpLeaks"
|
|
BOOL DNHandleTrackDumpLeaks()
|
|
{
|
|
BOOL fLeaked = FALSE;
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
while(!g_blHandles.IsEmpty())
|
|
{
|
|
DNHANDLE dnh = CONTAINING_RECORD(g_blHandles.GetNext(), TRACKED_HANDLE, blHandle);
|
|
dnh->blHandle.RemoveFromList();
|
|
|
|
fLeaked = TRUE;
|
|
|
|
// Dump dnh details
|
|
switch(dnh->type)
|
|
{
|
|
case TypeEvent:
|
|
DPFX(DPFPREP, 0, "Event leaked %p", dnh->handle);
|
|
break;
|
|
case TypeMutex:
|
|
DPFX(DPFPREP, 0, "Mutex leaked %p", dnh->handle);
|
|
break;
|
|
case TypeSemaphore:
|
|
DPFX(DPFPREP, 0, "Semaphore leaked %p", dnh->handle);
|
|
break;
|
|
case TypeFile:
|
|
DPFX(DPFPREP, 0, "File leaked %p", dnh->handle);
|
|
break;
|
|
#ifndef DPNBUILD_SINGLEPROCESS
|
|
case TypeFileMap:
|
|
DPFX(DPFPREP, 0, "FileMapping leaked %p", dnh->handle);
|
|
break;
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
case TypeThread:
|
|
DPFX(DPFPREP, 0, "Thread leaked %p", dnh->handle);
|
|
break;
|
|
#ifndef DPNBUILD_SINGLEPROCESS
|
|
case TypeProcess:
|
|
DPFX(DPFPREP, 0, "Process leaked %p", dnh->handle);
|
|
break;
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
case TypeSpecial:
|
|
DPFX(DPFPREP, 0, "Special handle leaked %p", dnh->handle);
|
|
break;
|
|
|
|
default:
|
|
DPFX(DPFPREP, 0, "Unknown handle leaked %p", dnh->handle);
|
|
DNASSERT(0);
|
|
break;
|
|
}
|
|
|
|
// Show the callstack of the place the handle was allocated.
|
|
TCHAR CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
|
|
dnh->AllocCallStack.GetCallStackString( CallStackBuffer );
|
|
DPFX(DPFPREP, 0, "%s\n", CallStackBuffer );
|
|
|
|
DNFree(dnh);
|
|
}
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
return fLeaked;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackMakeDNHANDLE(HANDLE h)
|
|
{
|
|
if (h == 0 || h == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (DNHANDLE)h;
|
|
}
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeSpecial;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
return dnh;
|
|
}
|
|
|
|
VOID DNHandleTrackRemoveDNHANDLE(DNHANDLE dnh)
|
|
{
|
|
DNASSERT(IsValidHandle(dnh));
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.RemoveFromList();
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
DNFree(dnh);
|
|
}
|
|
|
|
HANDLE DNHandleTrackHandleFromDNHANDLE(DNHANDLE h)
|
|
{
|
|
if (h == 0 || h == INVALID_HANDLE_VALUE)
|
|
{
|
|
return (HANDLE)h;
|
|
}
|
|
|
|
DNASSERT(IsValidHandle(h));
|
|
return h->handle;
|
|
}
|
|
|
|
#ifndef DPNBUILD_SINGLEPROCESS
|
|
// NOTE: pCurrentDirectory is const on the desktop, but non-const on WinCE
|
|
BOOL DNHandleTrackCreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, DNPROCESS_INFORMATION* lpProcessInformation)
|
|
{
|
|
PROCESS_INFORMATION pi;
|
|
DWORD dwLastError;
|
|
|
|
DNHANDLE dnhProcess = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnhProcess)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DNHANDLE dnhThread = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnhThread)
|
|
{
|
|
DNFree(dnhProcess);
|
|
return FALSE;
|
|
}
|
|
|
|
// NOTE: On CE only the current directory is declared non-const so cast it off
|
|
#ifdef WINCE
|
|
if (!CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPTSTR)lpCurrentDirectory, lpStartupInfo, &pi))
|
|
#else // !WINCE
|
|
if (!CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, &pi))
|
|
#endif // WINCE
|
|
{
|
|
dwLastError = GetLastError();
|
|
DNFree(dnhProcess);
|
|
DNFree(dnhThread);
|
|
SetLastError(dwLastError);
|
|
return FALSE;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
dnhProcess->AllocCallStack.NoteCurrentCallStack();
|
|
dnhProcess->handle = pi.hProcess;
|
|
dnhProcess->type = TypeProcess;
|
|
dnhProcess->blHandle.Initialize();
|
|
|
|
dnhThread->AllocCallStack.NoteCurrentCallStack();
|
|
dnhThread->handle = pi.hThread;
|
|
dnhThread->type = TypeThread;
|
|
dnhThread->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnhProcess->blHandle.InsertBefore(&g_blHandles);
|
|
dnhThread->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
lpProcessInformation->hProcess = dnhProcess;
|
|
lpProcessInformation->hThread = dnhThread;
|
|
lpProcessInformation->dwProcessId = pi.dwProcessId;
|
|
lpProcessInformation->dwThreadId = pi.dwThreadId;
|
|
|
|
SetLastError(dwLastError);
|
|
return TRUE;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeProcess;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
|
|
DNHANDLE DNHandleTrackCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeThread;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackCreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeEvent;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackOpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = OpenEvent(dwDesiredAccess, bInheritHandle, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeEvent;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
BOOL DNHandleTrackSetEvent(DNHANDLE hHandle)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
DNASSERT(hHandle->type == TypeEvent);
|
|
return SetEvent(hHandle->handle);
|
|
}
|
|
|
|
BOOL DNHandleTrackResetEvent(DNHANDLE hHandle)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
DNASSERT(hHandle->type == TypeEvent);
|
|
return ResetEvent(hHandle->handle);
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = CreateMutex(lpMutexAttributes, bInitialOwner, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeMutex;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackOpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = OpenMutex(dwDesiredAccess, bInheritHandle, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeMutex;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
BOOL DNHandleTrackReleaseMutex(DNHANDLE hHandle)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
DNASSERT(hHandle->type == TypeMutex);
|
|
return ReleaseMutex(hHandle->handle);
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackCreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeSemaphore;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
BOOL DNHandleTrackReleaseSemaphore(DNHANDLE hHandle, LONG lReleaseCount, LPLONG lpPreviousCount)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
DNASSERT(hHandle->type == TypeSemaphore);
|
|
return ReleaseSemaphore(hHandle->handle, lReleaseCount, lpPreviousCount);
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
|
if (h == INVALID_HANDLE_VALUE)
|
|
{
|
|
return DNINVALID_HANDLE_VALUE;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeFile;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
#ifndef DPNBUILD_SINGLEPROCESS
|
|
DNHANDLE DNHandleTrackCreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
// If someone wants to actually map a file, we need to make param 1 a DNHANDLE and do the appropriate work here.
|
|
DNASSERT(hFile == INVALID_HANDLE_VALUE);
|
|
|
|
HANDLE h = CreateFileMapping(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeFileMap;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
|
|
DNHANDLE DNHandleTrackOpenFileMapping(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
|
|
{
|
|
DWORD dwLastError;
|
|
|
|
HANDLE h = OpenFileMapping(dwDesiredAccess, bInheritHandle, lpName);
|
|
if (!h)
|
|
{
|
|
return 0;
|
|
}
|
|
dwLastError = GetLastError();
|
|
|
|
DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
|
|
if (!dnh)
|
|
{
|
|
CloseHandle(h);
|
|
SetLastError(dwLastError);
|
|
return 0;
|
|
}
|
|
|
|
dnh->AllocCallStack.NoteCurrentCallStack();
|
|
dnh->handle = h;
|
|
dnh->type = TypeFileMap;
|
|
dnh->blHandle.Initialize();
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
dnh->blHandle.InsertBefore(&g_blHandles);
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
SetLastError(dwLastError);
|
|
return dnh;
|
|
}
|
|
#endif // ! DPNBUILD_SINGLEPROCESS
|
|
|
|
DWORD DNHandleTrackWaitForSingleObject(DNHANDLE hHandle, DWORD dwMilliseconds)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
return WaitForSingleObject(hHandle->handle, dwMilliseconds);
|
|
}
|
|
|
|
DWORD DNHandleTrackWaitForSingleObjectEx(DNHANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
return WaitForSingleObjectEx(hHandle->handle, dwMilliseconds, bAlertable);
|
|
}
|
|
|
|
DWORD DNHandleTrackWaitForMultipleObjects(DWORD nCount, CONST DNHANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
|
|
{
|
|
DNASSERT(nCount <= MAXIMUM_WAIT_OBJECTS);
|
|
HANDLE rgh[MAXIMUM_WAIT_OBJECTS];
|
|
DWORD iHandle;
|
|
|
|
for (iHandle = 0; iHandle < nCount; iHandle++)
|
|
{
|
|
DNASSERT(IsValidHandle(lpHandles[iHandle]));
|
|
rgh[iHandle] = lpHandles[iHandle]->handle;
|
|
}
|
|
for (;iHandle < MAXIMUM_WAIT_OBJECTS; iHandle++)
|
|
{
|
|
rgh[iHandle] = 0;
|
|
}
|
|
return WaitForMultipleObjects(nCount, rgh, fWaitAll, dwMilliseconds);
|
|
}
|
|
|
|
DWORD DNHandleTrackWaitForMultipleObjectsEx(DWORD nCount, CONST DNHANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
|
|
{
|
|
DNASSERT(nCount <= MAXIMUM_WAIT_OBJECTS);
|
|
HANDLE rgh[MAXIMUM_WAIT_OBJECTS];
|
|
DWORD iHandle;
|
|
|
|
for (iHandle = 0; iHandle < nCount; iHandle++)
|
|
{
|
|
DNASSERT(IsValidHandle(lpHandles[iHandle]));
|
|
rgh[iHandle] = lpHandles[iHandle]->handle;
|
|
}
|
|
for (;iHandle < MAXIMUM_WAIT_OBJECTS; iHandle++)
|
|
{
|
|
rgh[iHandle] = 0;
|
|
}
|
|
return WaitForMultipleObjectsEx(nCount, rgh, fWaitAll, dwMilliseconds, bAlertable);
|
|
}
|
|
|
|
DWORD DNHandleTrackSignalObjectAndWait(DNHANDLE hObjectToSignal, DNHANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
|
|
{
|
|
DNASSERT(IsValidHandle(hObjectToSignal));
|
|
DNASSERT(IsValidHandle(hObjectToWaitOn));
|
|
DNASSERT(hObjectToSignal->handle != hObjectToWaitOn->handle);
|
|
|
|
#ifdef WINNT
|
|
return SignalObjectAndWait(hObjectToSignal->handle, hObjectToWaitOn->handle, dwMilliseconds, bAlertable);
|
|
#else // ! WINNT
|
|
BOOL fResult;
|
|
|
|
fResult = SetEvent(hObjectToSignal->handle);
|
|
DNASSERT(fResult);
|
|
return WaitForSingleObjectEx(hObjectToWaitOn->handle, dwMilliseconds, bAlertable);
|
|
#endif // ! WINNT
|
|
}
|
|
|
|
BOOL DNHandleTrackCloseHandle(DNHANDLE hHandle)
|
|
{
|
|
DNASSERT(IsValidHandle(hHandle));
|
|
|
|
DNEnterCriticalSection(&g_HandleLock);
|
|
hHandle->blHandle.RemoveFromList();
|
|
DNLeaveCriticalSection(&g_HandleLock);
|
|
|
|
HANDLE h = hHandle->handle;
|
|
|
|
DNFree(hHandle);
|
|
|
|
return CloseHandle(h);
|
|
}
|
|
|
|
#endif // DBG
|