Source code of Windows XP (NT5)
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.

768 lines
18 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. leaks.c
  5. Abstract:
  6. A filter DLL for trying to detect memory, event, registry, and
  7. token handle leaks.
  8. Author:
  9. Charlie Wickham/Rod Gamache
  10. Revision History:
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #define _ADVAPI32_
  16. #define _KERNEL32_
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include "clusrtl.h"
  20. #include "leaks.h"
  21. HINSTANCE Kernel32Handle;
  22. HINSTANCE Advapi32Handle;
  23. FARPROC SystemLocalAlloc;
  24. FARPROC SystemLocalFree;
  25. FARPROC SystemCreateEventA;
  26. FARPROC SystemCreateEventW;
  27. FARPROC SystemRegOpenKeyA;
  28. FARPROC SystemRegOpenKeyW;
  29. FARPROC SystemRegOpenKeyExA;
  30. FARPROC SystemRegOpenKeyExW;
  31. FARPROC SystemRegCreateKeyA;
  32. FARPROC SystemRegCreateKeyW;
  33. FARPROC SystemRegCreateKeyExA;
  34. FARPROC SystemRegCreateKeyExW;
  35. FARPROC SystemRegCloseKey;
  36. FARPROC SystemOpenProcessToken;
  37. FARPROC SystemOpenThreadToken;
  38. FARPROC SystemDuplicateToken;
  39. FARPROC SystemDuplicateTokenEx;
  40. FARPROC SystemCloseHandle;
  41. #define SetSystemPointer( _h, _n ) \
  42. System##_n = GetProcAddress( _h, #_n );
  43. BOOL LeaksVerbose = FALSE;
  44. HANDLE_TABLE HandleTable[ MAX_HANDLE / HANDLE_DELTA ];
  45. BOOLEAN
  46. WINAPI
  47. LeaksDllEntry(
  48. IN HINSTANCE DllHandle,
  49. IN DWORD Reason,
  50. IN LPVOID Reserved
  51. )
  52. /*++
  53. Routine Description:
  54. Main DLL entrypoint
  55. Arguments:
  56. DllHandle - Supplies the DLL handle.
  57. Reason - Supplies the call reason
  58. Return Value:
  59. TRUE if successful
  60. FALSE if unsuccessful
  61. --*/
  62. {
  63. if (Reason == DLL_PROCESS_ATTACH) {
  64. DisableThreadLibraryCalls(DllHandle);
  65. ClRtlInitialize( TRUE, NULL );
  66. //
  67. // get pointers to the real functions
  68. //
  69. Kernel32Handle = LoadLibrary( "kernel32.dll" );
  70. Advapi32Handle = LoadLibrary( "advapi32.dll" );
  71. SetSystemPointer( Kernel32Handle, LocalAlloc );
  72. SetSystemPointer( Kernel32Handle, LocalFree );
  73. SetSystemPointer( Kernel32Handle, CreateEventA );
  74. SetSystemPointer( Kernel32Handle, CreateEventW );
  75. SetSystemPointer( Advapi32Handle, RegOpenKeyA );
  76. SetSystemPointer( Advapi32Handle, RegOpenKeyW );
  77. SetSystemPointer( Advapi32Handle, RegOpenKeyExA );
  78. SetSystemPointer( Advapi32Handle, RegOpenKeyExW );
  79. SetSystemPointer( Advapi32Handle, RegCreateKeyA );
  80. SetSystemPointer( Advapi32Handle, RegCreateKeyW );
  81. SetSystemPointer( Advapi32Handle, RegCreateKeyExA );
  82. SetSystemPointer( Advapi32Handle, RegCreateKeyExW );
  83. SetSystemPointer( Advapi32Handle, RegCloseKey );
  84. SetSystemPointer( Advapi32Handle, OpenProcessToken );
  85. SetSystemPointer( Advapi32Handle, OpenThreadToken );
  86. SetSystemPointer( Advapi32Handle, DuplicateToken );
  87. SetSystemPointer( Advapi32Handle, DuplicateTokenEx );
  88. SetSystemPointer( Kernel32Handle, CloseHandle );
  89. }
  90. return(TRUE);
  91. }
  92. HLOCAL
  93. WINAPI
  94. LEAKS_LocalAlloc(
  95. UINT uFlags,
  96. SIZE_T uBytes
  97. )
  98. {
  99. HLOCAL memory;
  100. PMEM_HDR memHdr;
  101. PVOID callersAddress;
  102. PVOID callersCaller;
  103. RtlGetCallersAddress(
  104. &callersAddress,
  105. &callersCaller );
  106. memHdr = (PVOID)(*SystemLocalAlloc)( uFlags, uBytes + sizeof(MEM_HDR) );
  107. if ( !memHdr ) {
  108. return NULL;
  109. }
  110. memHdr->Signature = HEAP_SIGNATURE_ALLOC;
  111. memHdr->CallersAddress = callersAddress;
  112. memHdr->CallersCaller = callersCaller;
  113. return(memHdr+1);
  114. }
  115. HLOCAL
  116. WINAPI
  117. LEAKS_LocalFree(
  118. HLOCAL hMem
  119. )
  120. {
  121. PMEM_HDR memHdr = hMem;
  122. PVOID callersAddress;
  123. PVOID callersCaller;
  124. CHAR buf[128];
  125. if ( memHdr ) {
  126. --memHdr;
  127. if ( memHdr->Signature == HEAP_SIGNATURE_FREE ) {
  128. sprintf( buf, "Freeing %p a 2nd time!\n", memHdr );
  129. OutputDebugString( buf );
  130. DebugBreak();
  131. } else if ( memHdr->Signature == HEAP_SIGNATURE_ALLOC ) {
  132. RtlGetCallersAddress(&callersAddress,
  133. &callersCaller );
  134. memHdr->Signature = HEAP_SIGNATURE_FREE;
  135. memHdr->CallersAddress = callersAddress;
  136. memHdr->CallersCaller = callersCaller;
  137. } else {
  138. memHdr++;
  139. }
  140. } else {
  141. #if 0
  142. sprintf( buf, "Passing NULL to LocalFree, tsk, tsk, tsk!!\n" );
  143. OutputDebugString( buf );
  144. DebugBreak();
  145. #endif
  146. }
  147. return( (HLOCAL)(*SystemLocalFree)(memHdr) );
  148. }
  149. HANDLE
  150. WINAPI
  151. LEAKS_CreateEventA(
  152. LPSECURITY_ATTRIBUTES lpEventAttributes,
  153. BOOL bManualReset,
  154. BOOL bInitialState,
  155. LPCSTR lpName
  156. )
  157. {
  158. HANDLE handle;
  159. PVOID callersAddress;
  160. PVOID callersCaller;
  161. handle = (HANDLE)(*SystemCreateEventA)(
  162. lpEventAttributes,
  163. bManualReset,
  164. bInitialState,
  165. lpName
  166. );
  167. if ( handle != NULL ) {
  168. SetHandleTable( handle, TRUE, LeaksEvent );
  169. }
  170. if ( LeaksVerbose ) {
  171. ClRtlLogPrint(LOG_NOISE, "[LEAKS] CreateEventA returns handle %1!X!, called from %2!X! and %3!X!\n",
  172. handle,
  173. callersAddress,
  174. callersCaller );
  175. }
  176. return(handle);
  177. } // CreateEventA
  178. HANDLE
  179. WINAPI
  180. LEAKS_CreateEventW(
  181. LPSECURITY_ATTRIBUTES lpEventAttributes,
  182. BOOL bManualReset,
  183. BOOL bInitialState,
  184. LPCWSTR lpName
  185. )
  186. {
  187. HANDLE handle;
  188. PVOID callersAddress;
  189. PVOID callersCaller;
  190. handle = (HANDLE)(*SystemCreateEventW)(
  191. lpEventAttributes,
  192. bManualReset,
  193. bInitialState,
  194. lpName
  195. );
  196. if ( handle != NULL ) {
  197. SetHandleTable( handle, TRUE, LeaksEvent );
  198. }
  199. if ( LeaksVerbose ) {
  200. ClRtlLogPrint(LOG_NOISE,"[LEAKS] CreateEventW returns handle %1!X!, called from %2!X! and %3!X!\n",
  201. handle,
  202. callersAddress,
  203. callersCaller );
  204. }
  205. return(handle);
  206. } // CreateEventW
  207. LONG
  208. APIENTRY
  209. LEAKS_RegOpenKeyA(
  210. HKEY hKey,
  211. LPCSTR lpSubKey,
  212. PHKEY phkResult
  213. )
  214. {
  215. LONG status;
  216. PVOID callersAddress;
  217. PVOID callersCaller;
  218. status = (LONG)(*SystemRegOpenKeyA)(
  219. hKey,
  220. lpSubKey,
  221. phkResult
  222. );
  223. if ( status == ERROR_SUCCESS ) {
  224. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  225. }
  226. if ( LeaksVerbose ) {
  227. ClRtlLogPrint(LOG_NOISE,"[LEAKS] RegOpenKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  228. *phkResult,
  229. status,
  230. callersAddress,
  231. callersCaller );
  232. }
  233. return(status);
  234. } // RegOpenKeyA
  235. LONG
  236. APIENTRY
  237. LEAKS_RegOpenKeyW(
  238. HKEY hKey,
  239. LPCWSTR lpSubKey,
  240. PHKEY phkResult
  241. )
  242. {
  243. LONG status;
  244. PVOID callersAddress;
  245. PVOID callersCaller;
  246. status = (LONG)(*SystemRegOpenKeyW)(
  247. hKey,
  248. lpSubKey,
  249. phkResult
  250. );
  251. if ( status == ERROR_SUCCESS ) {
  252. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  253. }
  254. if ( LeaksVerbose ) {
  255. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  256. *phkResult,
  257. status,
  258. callersAddress,
  259. callersCaller );
  260. }
  261. return(status);
  262. } // RegOpenKeyW
  263. LONG
  264. APIENTRY
  265. LEAKS_RegOpenKeyExA(
  266. HKEY hKey,
  267. LPCSTR lpSubKey,
  268. DWORD ulOptions,
  269. REGSAM samDesired,
  270. PHKEY phkResult
  271. )
  272. {
  273. LONG status;
  274. PVOID callersAddress;
  275. PVOID callersCaller;
  276. status = (LONG)(*SystemRegOpenKeyExA)(
  277. hKey,
  278. lpSubKey,
  279. ulOptions,
  280. samDesired,
  281. phkResult
  282. );
  283. if ( status == ERROR_SUCCESS ) {
  284. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  285. }
  286. if ( LeaksVerbose ) {
  287. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  288. *phkResult,
  289. status,
  290. callersAddress,
  291. callersCaller );
  292. }
  293. return(status);
  294. } // RegOpenKeyExA
  295. LONG
  296. APIENTRY
  297. LEAKS_RegOpenKeyExW(
  298. HKEY hKey,
  299. LPCWSTR lpSubKey,
  300. DWORD ulOptions,
  301. REGSAM samDesired,
  302. PHKEY phkResult
  303. )
  304. {
  305. LONG status;
  306. PVOID callersAddress;
  307. PVOID callersCaller;
  308. status = (LONG)(*SystemRegOpenKeyExW)(
  309. hKey,
  310. lpSubKey,
  311. ulOptions,
  312. samDesired,
  313. phkResult
  314. );
  315. if ( status == ERROR_SUCCESS ) {
  316. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  317. }
  318. if ( LeaksVerbose ) {
  319. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegOpenKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  320. *phkResult,
  321. status,
  322. callersAddress,
  323. callersCaller );
  324. }
  325. return(status);
  326. } // RegOpenKeyExW
  327. LONG
  328. APIENTRY
  329. LEAKS_RegCreateKeyA(
  330. HKEY hKey,
  331. LPCSTR lpSubKey,
  332. PHKEY phkResult
  333. )
  334. {
  335. LONG status;
  336. PVOID callersAddress;
  337. PVOID callersCaller;
  338. status = (LONG)(*SystemRegCreateKeyA)(
  339. hKey,
  340. lpSubKey,
  341. phkResult
  342. );
  343. if ( status == ERROR_SUCCESS ) {
  344. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  345. }
  346. if ( LeaksVerbose ) {
  347. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  348. *phkResult,
  349. status,
  350. callersAddress,
  351. callersCaller );
  352. }
  353. return(status);
  354. } // RegCreateKeyA
  355. LONG
  356. APIENTRY
  357. LEAKS_RegCreateKeyW(
  358. HKEY hKey,
  359. LPCWSTR lpSubKey,
  360. PHKEY phkResult
  361. )
  362. {
  363. LONG status;
  364. PVOID callersAddress;
  365. PVOID callersCaller;
  366. status = (LONG)(*SystemRegCreateKeyW)(
  367. hKey,
  368. lpSubKey,
  369. phkResult
  370. );
  371. if ( status == ERROR_SUCCESS ) {
  372. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  373. }
  374. if ( LeaksVerbose ) {
  375. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  376. *phkResult,
  377. status,
  378. callersAddress,
  379. callersCaller );
  380. }
  381. return(status);
  382. } // RegCreateKeyW
  383. LONG
  384. APIENTRY
  385. LEAKS_RegCreateKeyExA(
  386. HKEY hKey,
  387. LPCSTR lpSubKey,
  388. DWORD Reserved,
  389. LPSTR lpClass,
  390. DWORD dwOptions,
  391. REGSAM samDesired,
  392. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  393. PHKEY phkResult,
  394. LPDWORD lpdwDisposition
  395. )
  396. {
  397. LONG status;
  398. PVOID callersAddress;
  399. PVOID callersCaller;
  400. status = (LONG)(*SystemRegCreateKeyExA)(hKey,
  401. lpSubKey,
  402. Reserved,
  403. lpClass,
  404. dwOptions,
  405. samDesired,
  406. lpSecurityAttributes,
  407. phkResult,
  408. lpdwDisposition
  409. );
  410. if ( status == ERROR_SUCCESS ) {
  411. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  412. }
  413. if ( LeaksVerbose ) {
  414. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  415. *phkResult,
  416. status,
  417. callersAddress,
  418. callersCaller );
  419. }
  420. return(status);
  421. } // RegCreateKeyExA
  422. LONG
  423. APIENTRY
  424. LEAKS_RegCreateKeyExW(
  425. HKEY hKey,
  426. LPCWSTR lpSubKey,
  427. DWORD Reserved,
  428. LPWSTR lpClass,
  429. DWORD dwOptions,
  430. REGSAM samDesired,
  431. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  432. PHKEY phkResult,
  433. LPDWORD lpdwDisposition
  434. )
  435. {
  436. LONG status;
  437. PVOID callersAddress;
  438. PVOID callersCaller;
  439. status = (LONG)(*SystemRegCreateKeyExW)(
  440. hKey,
  441. lpSubKey,
  442. Reserved,
  443. lpClass,
  444. dwOptions,
  445. samDesired,
  446. lpSecurityAttributes,
  447. phkResult,
  448. lpdwDisposition
  449. );
  450. if ( status == ERROR_SUCCESS ) {
  451. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  452. }
  453. if ( LeaksVerbose ) {
  454. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCreateKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  455. *phkResult,
  456. status,
  457. callersAddress,
  458. callersCaller );
  459. }
  460. return(status);
  461. } // RegCreateKeyExW
  462. LONG
  463. APIENTRY
  464. LEAKS_RegCloseKey(
  465. HKEY hKey
  466. )
  467. {
  468. LONG status;
  469. PVOID callersAddress;
  470. PVOID callersCaller;
  471. status = (LONG)(*SystemRegCloseKey)( hKey );
  472. if ( status == ERROR_SUCCESS ) {
  473. SetHandleTable( hKey, FALSE, LeaksRegistry );
  474. }
  475. if ( LeaksVerbose ) {
  476. ClRtlLogPrint(LOG_NOISE, "[LEAKS] RegCloseKey for key %1!X! returns status %2!u!, called from %3!X! and %4!X!\n",
  477. hKey,
  478. status,
  479. callersAddress,
  480. callersCaller );
  481. }
  482. return(status);
  483. } // RegCloseKey
  484. BOOL
  485. WINAPI
  486. LEAKS_CloseHandle(
  487. IN OUT HANDLE hObject
  488. )
  489. {
  490. PVOID callersAddress;
  491. PVOID callersCaller;
  492. if ( HandleTable[ HINDEX( hObject )].InUse ) {
  493. RtlGetCallersAddress(&callersAddress,
  494. &callersCaller );
  495. HandleTable[ HINDEX( hObject )].InUse = FALSE;
  496. HandleTable[ HINDEX( hObject )].Caller = callersAddress;
  497. HandleTable[ HINDEX( hObject )].CallersCaller = callersCaller;
  498. if ( LeaksVerbose ) {
  499. ClRtlLogPrint(LOG_NOISE, "[LEAKS] CloseHandle for handle %1!X!, called from %2!X! and %3!X!\n",
  500. hObject,
  501. callersAddress,
  502. callersCaller );
  503. }
  504. }
  505. return (BOOL)(*SystemCloseHandle)( hObject );
  506. }
  507. BOOL
  508. WINAPI
  509. LEAKS_OpenProcessToken (
  510. IN HANDLE ProcessHandle,
  511. IN DWORD DesiredAccess,
  512. OUT PHANDLE TokenHandle
  513. )
  514. {
  515. BOOL status;
  516. PVOID callersAddress;
  517. PVOID callersCaller;
  518. status = (BOOL)(*SystemOpenProcessToken)(ProcessHandle,
  519. DesiredAccess,
  520. TokenHandle);
  521. if ( status ) {
  522. SetHandleTable( *TokenHandle, TRUE, LeaksToken );
  523. }
  524. if ( LeaksVerbose ) {
  525. ClRtlLogPrint(LOG_NOISE, "[LEAKS] OpenProcessToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  526. *TokenHandle,
  527. status,
  528. callersAddress,
  529. callersCaller );
  530. }
  531. return(status);
  532. }
  533. BOOL
  534. WINAPI
  535. LEAKS_OpenThreadToken (
  536. IN HANDLE ThreadHandle,
  537. IN DWORD DesiredAccess,
  538. IN BOOL OpenAsSelf,
  539. OUT PHANDLE TokenHandle
  540. )
  541. {
  542. BOOL status;
  543. PVOID callersAddress;
  544. PVOID callersCaller;
  545. status = (BOOL)(*SystemOpenThreadToken)(ThreadHandle,
  546. DesiredAccess,
  547. OpenAsSelf,
  548. TokenHandle);
  549. if ( status ) {
  550. SetHandleTable( *TokenHandle, TRUE, LeaksToken );
  551. }
  552. if ( LeaksVerbose ) {
  553. ClRtlLogPrint(LOG_NOISE, "[LEAKS] OpenThreadToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  554. *TokenHandle,
  555. status,
  556. callersAddress,
  557. callersCaller );
  558. }
  559. return(status);
  560. }
  561. BOOL
  562. WINAPI
  563. LEAKS_DuplicateToken(
  564. IN HANDLE ExistingTokenHandle,
  565. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  566. OUT PHANDLE DuplicateTokenHandle
  567. )
  568. {
  569. BOOL status;
  570. PVOID callersAddress;
  571. PVOID callersCaller;
  572. status = (BOOL)(*SystemDuplicateToken)(ExistingTokenHandle,
  573. ImpersonationLevel,
  574. DuplicateTokenHandle);
  575. if ( status ) {
  576. SetHandleTable( *DuplicateTokenHandle, TRUE, LeaksToken );
  577. }
  578. if ( LeaksVerbose ) {
  579. ClRtlLogPrint(LOG_NOISE, "[LEAKS] DuplicateToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  580. *DuplicateTokenHandle,
  581. status,
  582. callersAddress,
  583. callersCaller );
  584. }
  585. return(status);
  586. }
  587. BOOL
  588. WINAPI
  589. LEAKS_DuplicateTokenEx(
  590. IN HANDLE hExistingToken,
  591. IN DWORD dwDesiredAccess,
  592. IN LPSECURITY_ATTRIBUTES lpTokenAttributes,
  593. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  594. IN TOKEN_TYPE TokenType,
  595. OUT PHANDLE phNewToken)
  596. {
  597. BOOL status;
  598. PVOID callersAddress;
  599. PVOID callersCaller;
  600. status = (BOOL)(*SystemDuplicateTokenEx)(hExistingToken,
  601. dwDesiredAccess,
  602. lpTokenAttributes,
  603. ImpersonationLevel,
  604. TokenType,
  605. phNewToken);
  606. if ( status ) {
  607. SetHandleTable( *phNewToken, TRUE, LeaksToken );
  608. }
  609. if ( LeaksVerbose ) {
  610. ClRtlLogPrint(LOG_NOISE, "[LEAKS] DuplicateTokenEx returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  611. *phNewToken,
  612. status,
  613. callersAddress,
  614. callersCaller );
  615. }
  616. return(status);
  617. }