Leaked source code of windows server 2003
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.

652 lines
17 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 2001 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: HandleTracking.cpp
  6. * Content: Handle Tracking debug logic
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 10/31/2001 masonb Created
  12. *
  13. *
  14. ***************************************************************************/
  15. #include "dncmni.h"
  16. #ifdef DBG
  17. CBilink g_blHandles;
  18. #ifndef DPNBUILD_ONLYONETHREAD
  19. DNCRITICAL_SECTION g_HandleLock;
  20. #endif // !DPNBUILD_ONLYONETHREAD
  21. #define IsValidHandle(x) \
  22. (x != NULL && x != INVALID_HANDLE_VALUE && \
  23. (x->type == TypeEvent || \
  24. x->type == TypeMutex || \
  25. x->type == TypeSemaphore || \
  26. x->type == TypeFile || \
  27. x->type == TypeFileMap || \
  28. x->type == TypeThread || \
  29. x->type == TypeProcess || \
  30. x->type == TypeSpecial))
  31. BOOL DNHandleTrackInitialize()
  32. {
  33. g_blHandles.Initialize();
  34. return DNInitializeCriticalSection(&g_HandleLock);
  35. }
  36. VOID DNHandleTrackDeinitialize()
  37. {
  38. DNDeleteCriticalSection(&g_HandleLock);
  39. }
  40. #undef DPF_MODNAME
  41. #define DPF_MODNAME "DNHandleTrackDumpLeaks"
  42. BOOL DNHandleTrackDumpLeaks()
  43. {
  44. BOOL fLeaked = FALSE;
  45. DNEnterCriticalSection(&g_HandleLock);
  46. while(!g_blHandles.IsEmpty())
  47. {
  48. DNHANDLE dnh = CONTAINING_RECORD(g_blHandles.GetNext(), TRACKED_HANDLE, blHandle);
  49. dnh->blHandle.RemoveFromList();
  50. fLeaked = TRUE;
  51. // Dump dnh details
  52. switch(dnh->type)
  53. {
  54. case TypeEvent:
  55. DPFX(DPFPREP, 0, "Event leaked %p", dnh->handle);
  56. break;
  57. case TypeMutex:
  58. DPFX(DPFPREP, 0, "Mutex leaked %p", dnh->handle);
  59. break;
  60. case TypeSemaphore:
  61. DPFX(DPFPREP, 0, "Semaphore leaked %p", dnh->handle);
  62. break;
  63. case TypeFile:
  64. DPFX(DPFPREP, 0, "File leaked %p", dnh->handle);
  65. break;
  66. #ifndef DPNBUILD_SINGLEPROCESS
  67. case TypeFileMap:
  68. DPFX(DPFPREP, 0, "FileMapping leaked %p", dnh->handle);
  69. break;
  70. #endif // ! DPNBUILD_SINGLEPROCESS
  71. case TypeThread:
  72. DPFX(DPFPREP, 0, "Thread leaked %p", dnh->handle);
  73. break;
  74. #ifndef DPNBUILD_SINGLEPROCESS
  75. case TypeProcess:
  76. DPFX(DPFPREP, 0, "Process leaked %p", dnh->handle);
  77. break;
  78. #endif // ! DPNBUILD_SINGLEPROCESS
  79. case TypeSpecial:
  80. DPFX(DPFPREP, 0, "Special handle leaked %p", dnh->handle);
  81. break;
  82. default:
  83. DPFX(DPFPREP, 0, "Unknown handle leaked %p", dnh->handle);
  84. DNASSERT(0);
  85. break;
  86. }
  87. // Show the callstack of the place the handle was allocated.
  88. TCHAR CallStackBuffer[ CALLSTACK_BUFFER_SIZE ];
  89. dnh->AllocCallStack.GetCallStackString( CallStackBuffer );
  90. DPFX(DPFPREP, 0, "%s\n", CallStackBuffer );
  91. DNFree(dnh);
  92. }
  93. DNLeaveCriticalSection(&g_HandleLock);
  94. return fLeaked;
  95. }
  96. DNHANDLE DNHandleTrackMakeDNHANDLE(HANDLE h)
  97. {
  98. if (h == 0 || h == INVALID_HANDLE_VALUE)
  99. {
  100. return (DNHANDLE)h;
  101. }
  102. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  103. if (!dnh)
  104. {
  105. CloseHandle(h);
  106. return 0;
  107. }
  108. dnh->AllocCallStack.NoteCurrentCallStack();
  109. dnh->handle = h;
  110. dnh->type = TypeSpecial;
  111. dnh->blHandle.Initialize();
  112. DNEnterCriticalSection(&g_HandleLock);
  113. dnh->blHandle.InsertBefore(&g_blHandles);
  114. DNLeaveCriticalSection(&g_HandleLock);
  115. return dnh;
  116. }
  117. VOID DNHandleTrackRemoveDNHANDLE(DNHANDLE dnh)
  118. {
  119. DNASSERT(IsValidHandle(dnh));
  120. DNEnterCriticalSection(&g_HandleLock);
  121. dnh->blHandle.RemoveFromList();
  122. DNLeaveCriticalSection(&g_HandleLock);
  123. DNFree(dnh);
  124. }
  125. HANDLE DNHandleTrackHandleFromDNHANDLE(DNHANDLE h)
  126. {
  127. if (h == 0 || h == INVALID_HANDLE_VALUE)
  128. {
  129. return (HANDLE)h;
  130. }
  131. DNASSERT(IsValidHandle(h));
  132. return h->handle;
  133. }
  134. #ifndef DPNBUILD_SINGLEPROCESS
  135. // NOTE: pCurrentDirectory is const on the desktop, but non-const on WinCE
  136. 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)
  137. {
  138. PROCESS_INFORMATION pi;
  139. DWORD dwLastError;
  140. DNHANDLE dnhProcess = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  141. if (!dnhProcess)
  142. {
  143. return FALSE;
  144. }
  145. DNHANDLE dnhThread = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  146. if (!dnhThread)
  147. {
  148. DNFree(dnhProcess);
  149. return FALSE;
  150. }
  151. // NOTE: On CE only the current directory is declared non-const so cast it off
  152. #ifdef WINCE
  153. if (!CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, (LPTSTR)lpCurrentDirectory, lpStartupInfo, &pi))
  154. #else // !WINCE
  155. if (!CreateProcess(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, &pi))
  156. #endif // WINCE
  157. {
  158. dwLastError = GetLastError();
  159. DNFree(dnhProcess);
  160. DNFree(dnhThread);
  161. SetLastError(dwLastError);
  162. return FALSE;
  163. }
  164. dwLastError = GetLastError();
  165. dnhProcess->AllocCallStack.NoteCurrentCallStack();
  166. dnhProcess->handle = pi.hProcess;
  167. dnhProcess->type = TypeProcess;
  168. dnhProcess->blHandle.Initialize();
  169. dnhThread->AllocCallStack.NoteCurrentCallStack();
  170. dnhThread->handle = pi.hThread;
  171. dnhThread->type = TypeThread;
  172. dnhThread->blHandle.Initialize();
  173. DNEnterCriticalSection(&g_HandleLock);
  174. dnhProcess->blHandle.InsertBefore(&g_blHandles);
  175. dnhThread->blHandle.InsertBefore(&g_blHandles);
  176. DNLeaveCriticalSection(&g_HandleLock);
  177. lpProcessInformation->hProcess = dnhProcess;
  178. lpProcessInformation->hThread = dnhThread;
  179. lpProcessInformation->dwProcessId = pi.dwProcessId;
  180. lpProcessInformation->dwThreadId = pi.dwThreadId;
  181. SetLastError(dwLastError);
  182. return TRUE;
  183. }
  184. DNHANDLE DNHandleTrackOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
  185. {
  186. DWORD dwLastError;
  187. HANDLE h = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
  188. if (!h)
  189. {
  190. return 0;
  191. }
  192. dwLastError = GetLastError();
  193. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  194. if (!dnh)
  195. {
  196. CloseHandle(h);
  197. SetLastError(dwLastError);
  198. return 0;
  199. }
  200. dnh->AllocCallStack.NoteCurrentCallStack();
  201. dnh->handle = h;
  202. dnh->type = TypeProcess;
  203. dnh->blHandle.Initialize();
  204. DNEnterCriticalSection(&g_HandleLock);
  205. dnh->blHandle.InsertBefore(&g_blHandles);
  206. DNLeaveCriticalSection(&g_HandleLock);
  207. SetLastError(dwLastError);
  208. return dnh;
  209. }
  210. #endif // ! DPNBUILD_SINGLEPROCESS
  211. DNHANDLE DNHandleTrackCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId)
  212. {
  213. DWORD dwLastError;
  214. HANDLE h = CreateThread(lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId);
  215. if (!h)
  216. {
  217. return 0;
  218. }
  219. dwLastError = GetLastError();
  220. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  221. if (!dnh)
  222. {
  223. CloseHandle(h);
  224. SetLastError(dwLastError);
  225. return 0;
  226. }
  227. dnh->AllocCallStack.NoteCurrentCallStack();
  228. dnh->handle = h;
  229. dnh->type = TypeThread;
  230. dnh->blHandle.Initialize();
  231. DNEnterCriticalSection(&g_HandleLock);
  232. dnh->blHandle.InsertBefore(&g_blHandles);
  233. DNLeaveCriticalSection(&g_HandleLock);
  234. SetLastError(dwLastError);
  235. return dnh;
  236. }
  237. DNHANDLE DNHandleTrackCreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName)
  238. {
  239. DWORD dwLastError;
  240. HANDLE h = CreateEvent(lpEventAttributes, bManualReset, bInitialState, lpName);
  241. if (!h)
  242. {
  243. return 0;
  244. }
  245. dwLastError = GetLastError();
  246. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  247. if (!dnh)
  248. {
  249. CloseHandle(h);
  250. SetLastError(dwLastError);
  251. return 0;
  252. }
  253. dnh->AllocCallStack.NoteCurrentCallStack();
  254. dnh->handle = h;
  255. dnh->type = TypeEvent;
  256. dnh->blHandle.Initialize();
  257. DNEnterCriticalSection(&g_HandleLock);
  258. dnh->blHandle.InsertBefore(&g_blHandles);
  259. DNLeaveCriticalSection(&g_HandleLock);
  260. SetLastError(dwLastError);
  261. return dnh;
  262. }
  263. DNHANDLE DNHandleTrackOpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
  264. {
  265. DWORD dwLastError;
  266. HANDLE h = OpenEvent(dwDesiredAccess, bInheritHandle, lpName);
  267. if (!h)
  268. {
  269. return 0;
  270. }
  271. dwLastError = GetLastError();
  272. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  273. if (!dnh)
  274. {
  275. CloseHandle(h);
  276. SetLastError(dwLastError);
  277. return 0;
  278. }
  279. dnh->AllocCallStack.NoteCurrentCallStack();
  280. dnh->handle = h;
  281. dnh->type = TypeEvent;
  282. dnh->blHandle.Initialize();
  283. DNEnterCriticalSection(&g_HandleLock);
  284. dnh->blHandle.InsertBefore(&g_blHandles);
  285. DNLeaveCriticalSection(&g_HandleLock);
  286. SetLastError(dwLastError);
  287. return dnh;
  288. }
  289. BOOL DNHandleTrackSetEvent(DNHANDLE hHandle)
  290. {
  291. DNASSERT(IsValidHandle(hHandle));
  292. DNASSERT(hHandle->type == TypeEvent);
  293. return SetEvent(hHandle->handle);
  294. }
  295. BOOL DNHandleTrackResetEvent(DNHANDLE hHandle)
  296. {
  297. DNASSERT(IsValidHandle(hHandle));
  298. DNASSERT(hHandle->type == TypeEvent);
  299. return ResetEvent(hHandle->handle);
  300. }
  301. DNHANDLE DNHandleTrackCreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner, LPCTSTR lpName)
  302. {
  303. DWORD dwLastError;
  304. HANDLE h = CreateMutex(lpMutexAttributes, bInitialOwner, lpName);
  305. if (!h)
  306. {
  307. return 0;
  308. }
  309. dwLastError = GetLastError();
  310. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  311. if (!dnh)
  312. {
  313. CloseHandle(h);
  314. SetLastError(dwLastError);
  315. return 0;
  316. }
  317. dnh->AllocCallStack.NoteCurrentCallStack();
  318. dnh->handle = h;
  319. dnh->type = TypeMutex;
  320. dnh->blHandle.Initialize();
  321. DNEnterCriticalSection(&g_HandleLock);
  322. dnh->blHandle.InsertBefore(&g_blHandles);
  323. DNLeaveCriticalSection(&g_HandleLock);
  324. SetLastError(dwLastError);
  325. return dnh;
  326. }
  327. DNHANDLE DNHandleTrackOpenMutex(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
  328. {
  329. DWORD dwLastError;
  330. HANDLE h = OpenMutex(dwDesiredAccess, bInheritHandle, lpName);
  331. if (!h)
  332. {
  333. return 0;
  334. }
  335. dwLastError = GetLastError();
  336. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  337. if (!dnh)
  338. {
  339. CloseHandle(h);
  340. SetLastError(dwLastError);
  341. return 0;
  342. }
  343. dnh->AllocCallStack.NoteCurrentCallStack();
  344. dnh->handle = h;
  345. dnh->type = TypeMutex;
  346. dnh->blHandle.Initialize();
  347. DNEnterCriticalSection(&g_HandleLock);
  348. dnh->blHandle.InsertBefore(&g_blHandles);
  349. DNLeaveCriticalSection(&g_HandleLock);
  350. SetLastError(dwLastError);
  351. return dnh;
  352. }
  353. BOOL DNHandleTrackReleaseMutex(DNHANDLE hHandle)
  354. {
  355. DNASSERT(IsValidHandle(hHandle));
  356. DNASSERT(hHandle->type == TypeMutex);
  357. return ReleaseMutex(hHandle->handle);
  358. }
  359. DNHANDLE DNHandleTrackCreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName)
  360. {
  361. DWORD dwLastError;
  362. HANDLE h = CreateSemaphore(lpSemaphoreAttributes, lInitialCount, lMaximumCount, lpName);
  363. if (!h)
  364. {
  365. return 0;
  366. }
  367. dwLastError = GetLastError();
  368. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  369. if (!dnh)
  370. {
  371. CloseHandle(h);
  372. SetLastError(dwLastError);
  373. return 0;
  374. }
  375. dnh->AllocCallStack.NoteCurrentCallStack();
  376. dnh->handle = h;
  377. dnh->type = TypeSemaphore;
  378. dnh->blHandle.Initialize();
  379. DNEnterCriticalSection(&g_HandleLock);
  380. dnh->blHandle.InsertBefore(&g_blHandles);
  381. DNLeaveCriticalSection(&g_HandleLock);
  382. SetLastError(dwLastError);
  383. return dnh;
  384. }
  385. BOOL DNHandleTrackReleaseSemaphore(DNHANDLE hHandle, LONG lReleaseCount, LPLONG lpPreviousCount)
  386. {
  387. DNASSERT(IsValidHandle(hHandle));
  388. DNASSERT(hHandle->type == TypeSemaphore);
  389. return ReleaseSemaphore(hHandle->handle, lReleaseCount, lpPreviousCount);
  390. }
  391. DNHANDLE DNHandleTrackCreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
  392. {
  393. DWORD dwLastError;
  394. HANDLE h = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  395. if (h == INVALID_HANDLE_VALUE)
  396. {
  397. return DNINVALID_HANDLE_VALUE;
  398. }
  399. dwLastError = GetLastError();
  400. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  401. if (!dnh)
  402. {
  403. CloseHandle(h);
  404. SetLastError(dwLastError);
  405. return 0;
  406. }
  407. dnh->AllocCallStack.NoteCurrentCallStack();
  408. dnh->handle = h;
  409. dnh->type = TypeFile;
  410. dnh->blHandle.Initialize();
  411. DNEnterCriticalSection(&g_HandleLock);
  412. dnh->blHandle.InsertBefore(&g_blHandles);
  413. DNLeaveCriticalSection(&g_HandleLock);
  414. SetLastError(dwLastError);
  415. return dnh;
  416. }
  417. #ifndef DPNBUILD_SINGLEPROCESS
  418. DNHANDLE DNHandleTrackCreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName)
  419. {
  420. DWORD dwLastError;
  421. // If someone wants to actually map a file, we need to make param 1 a DNHANDLE and do the appropriate work here.
  422. DNASSERT(hFile == INVALID_HANDLE_VALUE);
  423. HANDLE h = CreateFileMapping(hFile, lpAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName);
  424. if (!h)
  425. {
  426. return 0;
  427. }
  428. dwLastError = GetLastError();
  429. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  430. if (!dnh)
  431. {
  432. CloseHandle(h);
  433. SetLastError(dwLastError);
  434. return 0;
  435. }
  436. dnh->AllocCallStack.NoteCurrentCallStack();
  437. dnh->handle = h;
  438. dnh->type = TypeFileMap;
  439. dnh->blHandle.Initialize();
  440. DNEnterCriticalSection(&g_HandleLock);
  441. dnh->blHandle.InsertBefore(&g_blHandles);
  442. DNLeaveCriticalSection(&g_HandleLock);
  443. SetLastError(dwLastError);
  444. return dnh;
  445. }
  446. DNHANDLE DNHandleTrackOpenFileMapping(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName)
  447. {
  448. DWORD dwLastError;
  449. HANDLE h = OpenFileMapping(dwDesiredAccess, bInheritHandle, lpName);
  450. if (!h)
  451. {
  452. return 0;
  453. }
  454. dwLastError = GetLastError();
  455. DNHANDLE dnh = (DNHANDLE)DNMalloc(sizeof(TRACKED_HANDLE));
  456. if (!dnh)
  457. {
  458. CloseHandle(h);
  459. SetLastError(dwLastError);
  460. return 0;
  461. }
  462. dnh->AllocCallStack.NoteCurrentCallStack();
  463. dnh->handle = h;
  464. dnh->type = TypeFileMap;
  465. dnh->blHandle.Initialize();
  466. DNEnterCriticalSection(&g_HandleLock);
  467. dnh->blHandle.InsertBefore(&g_blHandles);
  468. DNLeaveCriticalSection(&g_HandleLock);
  469. SetLastError(dwLastError);
  470. return dnh;
  471. }
  472. #endif // ! DPNBUILD_SINGLEPROCESS
  473. DWORD DNHandleTrackWaitForSingleObject(DNHANDLE hHandle, DWORD dwMilliseconds)
  474. {
  475. DNASSERT(IsValidHandle(hHandle));
  476. return WaitForSingleObject(hHandle->handle, dwMilliseconds);
  477. }
  478. DWORD DNHandleTrackWaitForSingleObjectEx(DNHANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertable)
  479. {
  480. DNASSERT(IsValidHandle(hHandle));
  481. return WaitForSingleObjectEx(hHandle->handle, dwMilliseconds, bAlertable);
  482. }
  483. DWORD DNHandleTrackWaitForMultipleObjects(DWORD nCount, CONST DNHANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
  484. {
  485. DNASSERT(nCount <= MAXIMUM_WAIT_OBJECTS);
  486. HANDLE rgh[MAXIMUM_WAIT_OBJECTS];
  487. DWORD iHandle;
  488. for (iHandle = 0; iHandle < nCount; iHandle++)
  489. {
  490. DNASSERT(IsValidHandle(lpHandles[iHandle]));
  491. rgh[iHandle] = lpHandles[iHandle]->handle;
  492. }
  493. for (;iHandle < MAXIMUM_WAIT_OBJECTS; iHandle++)
  494. {
  495. rgh[iHandle] = 0;
  496. }
  497. return WaitForMultipleObjects(nCount, rgh, fWaitAll, dwMilliseconds);
  498. }
  499. DWORD DNHandleTrackWaitForMultipleObjectsEx(DWORD nCount, CONST DNHANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds, BOOL bAlertable)
  500. {
  501. DNASSERT(nCount <= MAXIMUM_WAIT_OBJECTS);
  502. HANDLE rgh[MAXIMUM_WAIT_OBJECTS];
  503. DWORD iHandle;
  504. for (iHandle = 0; iHandle < nCount; iHandle++)
  505. {
  506. DNASSERT(IsValidHandle(lpHandles[iHandle]));
  507. rgh[iHandle] = lpHandles[iHandle]->handle;
  508. }
  509. for (;iHandle < MAXIMUM_WAIT_OBJECTS; iHandle++)
  510. {
  511. rgh[iHandle] = 0;
  512. }
  513. return WaitForMultipleObjectsEx(nCount, rgh, fWaitAll, dwMilliseconds, bAlertable);
  514. }
  515. DWORD DNHandleTrackSignalObjectAndWait(DNHANDLE hObjectToSignal, DNHANDLE hObjectToWaitOn, DWORD dwMilliseconds, BOOL bAlertable)
  516. {
  517. DNASSERT(IsValidHandle(hObjectToSignal));
  518. DNASSERT(IsValidHandle(hObjectToWaitOn));
  519. DNASSERT(hObjectToSignal->handle != hObjectToWaitOn->handle);
  520. #ifdef WINNT
  521. return SignalObjectAndWait(hObjectToSignal->handle, hObjectToWaitOn->handle, dwMilliseconds, bAlertable);
  522. #else // ! WINNT
  523. BOOL fResult;
  524. fResult = SetEvent(hObjectToSignal->handle);
  525. DNASSERT(fResult);
  526. return WaitForSingleObjectEx(hObjectToWaitOn->handle, dwMilliseconds, bAlertable);
  527. #endif // ! WINNT
  528. }
  529. BOOL DNHandleTrackCloseHandle(DNHANDLE hHandle)
  530. {
  531. DNASSERT(IsValidHandle(hHandle));
  532. DNEnterCriticalSection(&g_HandleLock);
  533. hHandle->blHandle.RemoveFromList();
  534. DNLeaveCriticalSection(&g_HandleLock);
  535. HANDLE h = hHandle->handle;
  536. DNFree(hHandle);
  537. return CloseHandle(h);
  538. }
  539. #endif // DBG