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.

778 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( FALSE );
  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. //
  93. // leaks memory header. This structure is at the front of the allocated area
  94. // and the area behind it is returned to the caller. PlaceHolder holds the
  95. // heap free list pointer. Signature holds ALOC or FREE.
  96. //
  97. #define HEAP_SIGNATURE_ALLOC 'COLA'
  98. #define HEAP_SIGNATURE_FREE 'EERF'
  99. typedef struct _MEM_HDR {
  100. PVOID PlaceHolder;
  101. DWORD Signature;
  102. PVOID CallersAddress;
  103. PVOID CallersCaller;
  104. } MEM_HDR, *PMEM_HDR;
  105. HLOCAL
  106. WINAPI
  107. LocalAlloc(
  108. UINT uFlags,
  109. SIZE_T uBytes
  110. )
  111. {
  112. HLOCAL memory;
  113. PMEM_HDR memHdr;
  114. PVOID callersAddress;
  115. PVOID callersCaller;
  116. RtlGetCallersAddress(
  117. &callersAddress,
  118. &callersCaller );
  119. memHdr = (PVOID)(*SystemLocalAlloc)( uFlags, uBytes + sizeof(MEM_HDR) );
  120. if ( !memHdr ) {
  121. return NULL;
  122. }
  123. memHdr->Signature = HEAP_SIGNATURE_ALLOC;
  124. memHdr->CallersAddress = callersAddress;
  125. memHdr->CallersCaller = callersCaller;
  126. return(memHdr+1);
  127. }
  128. HLOCAL
  129. WINAPI
  130. LocalFree(
  131. HLOCAL hMem
  132. )
  133. {
  134. PMEM_HDR memHdr = hMem;
  135. PVOID callersAddress;
  136. PVOID callersCaller;
  137. if ( memHdr ) {
  138. --memHdr;
  139. if ( memHdr->Signature == HEAP_SIGNATURE_FREE ) {
  140. CHAR buf[64];
  141. sprintf( buf, "Freeing %X a 2nd time!\n", memHdr );
  142. OutputDebugString( buf );
  143. DebugBreak();
  144. } else if ( memHdr->Signature == HEAP_SIGNATURE_ALLOC ) {
  145. RtlGetCallersAddress(&callersAddress,
  146. &callersCaller );
  147. memHdr->Signature = HEAP_SIGNATURE_FREE;
  148. memHdr->CallersAddress = callersAddress;
  149. memHdr->CallersCaller = callersCaller;
  150. } else {
  151. memHdr++;
  152. }
  153. }
  154. return( (HLOCAL)(*SystemLocalFree)(memHdr) );
  155. }
  156. HANDLE
  157. WINAPI
  158. CreateEventA(
  159. LPSECURITY_ATTRIBUTES lpEventAttributes,
  160. BOOL bManualReset,
  161. BOOL bInitialState,
  162. LPCSTR lpName
  163. )
  164. {
  165. HANDLE handle;
  166. PVOID callersAddress;
  167. PVOID callersCaller;
  168. handle = (HANDLE)(*SystemCreateEventA)(
  169. lpEventAttributes,
  170. bManualReset,
  171. bInitialState,
  172. lpName
  173. );
  174. if ( handle != NULL ) {
  175. SetHandleTable( handle, TRUE, LeaksEvent );
  176. }
  177. if ( LeaksVerbose ) {
  178. ClRtlLogPrint("[LEAKS] CreateEventA returns handle %1!X!, called from %2!X! and %3!X!\n",
  179. handle,
  180. callersAddress,
  181. callersCaller );
  182. }
  183. return(handle);
  184. } // CreateEventA
  185. HANDLE
  186. WINAPI
  187. CreateEventW(
  188. LPSECURITY_ATTRIBUTES lpEventAttributes,
  189. BOOL bManualReset,
  190. BOOL bInitialState,
  191. LPCWSTR lpName
  192. )
  193. {
  194. HANDLE handle;
  195. PVOID callersAddress;
  196. PVOID callersCaller;
  197. handle = (HANDLE)(*SystemCreateEventW)(
  198. lpEventAttributes,
  199. bManualReset,
  200. bInitialState,
  201. lpName
  202. );
  203. if ( handle != NULL ) {
  204. SetHandleTable( handle, TRUE, LeaksEvent );
  205. }
  206. if ( LeaksVerbose ) {
  207. ClRtlLogPrint("[LEAKS] CreateEventW returns handle %1!X!, called from %2!X! and %3!X!\n",
  208. handle,
  209. callersAddress,
  210. callersCaller );
  211. }
  212. return(handle);
  213. } // CreateEventW
  214. LONG
  215. APIENTRY
  216. RegOpenKeyA(
  217. HKEY hKey,
  218. LPCSTR lpSubKey,
  219. PHKEY phkResult
  220. )
  221. {
  222. LONG status;
  223. PVOID callersAddress;
  224. PVOID callersCaller;
  225. status = (*SystemRegOpenKeyA)(
  226. hKey,
  227. lpSubKey,
  228. phkResult
  229. );
  230. if ( status == ERROR_SUCCESS ) {
  231. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  232. }
  233. if ( LeaksVerbose ) {
  234. ClRtlLogPrint("[LEAKS] RegOpenKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  235. *phkResult,
  236. status,
  237. callersAddress,
  238. callersCaller );
  239. }
  240. return(status);
  241. } // RegOpenKeyA
  242. LONG
  243. APIENTRY
  244. RegOpenKeyW(
  245. HKEY hKey,
  246. LPCWSTR lpSubKey,
  247. PHKEY phkResult
  248. )
  249. {
  250. LONG status;
  251. PVOID callersAddress;
  252. PVOID callersCaller;
  253. status = (*SystemRegOpenKeyW)(
  254. hKey,
  255. lpSubKey,
  256. phkResult
  257. );
  258. if ( status == ERROR_SUCCESS ) {
  259. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  260. }
  261. if ( LeaksVerbose ) {
  262. ClRtlLogPrint("[LEAKS] RegOpenKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  263. *phkResult,
  264. status,
  265. callersAddress,
  266. callersCaller );
  267. }
  268. return(status);
  269. } // RegOpenKeyW
  270. LONG
  271. APIENTRY
  272. RegOpenKeyExA(
  273. HKEY hKey,
  274. LPCSTR lpSubKey,
  275. DWORD ulOptions,
  276. REGSAM samDesired,
  277. PHKEY phkResult
  278. )
  279. {
  280. LONG status;
  281. PVOID callersAddress;
  282. PVOID callersCaller;
  283. status = (*SystemRegOpenKeyExA)(
  284. hKey,
  285. lpSubKey,
  286. ulOptions,
  287. samDesired,
  288. phkResult
  289. );
  290. if ( status == ERROR_SUCCESS ) {
  291. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  292. }
  293. if ( LeaksVerbose ) {
  294. ClRtlLogPrint("[LEAKS] RegOpenKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  295. *phkResult,
  296. status,
  297. callersAddress,
  298. callersCaller );
  299. }
  300. return(status);
  301. } // RegOpenKeyExA
  302. LONG
  303. APIENTRY
  304. RegOpenKeyExW(
  305. HKEY hKey,
  306. LPCWSTR lpSubKey,
  307. DWORD ulOptions,
  308. REGSAM samDesired,
  309. PHKEY phkResult
  310. )
  311. {
  312. LONG status;
  313. PVOID callersAddress;
  314. PVOID callersCaller;
  315. status = (*SystemRegOpenKeyExW)(
  316. hKey,
  317. lpSubKey,
  318. ulOptions,
  319. samDesired,
  320. phkResult
  321. );
  322. if ( status == ERROR_SUCCESS ) {
  323. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  324. }
  325. if ( LeaksVerbose ) {
  326. ClRtlLogPrint("[LEAKS] RegOpenKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  327. *phkResult,
  328. status,
  329. callersAddress,
  330. callersCaller );
  331. }
  332. return(status);
  333. } // RegOpenKeyExW
  334. LONG
  335. APIENTRY
  336. RegCreateKeyA(
  337. HKEY hKey,
  338. LPCSTR lpSubKey,
  339. PHKEY phkResult
  340. )
  341. {
  342. LONG status;
  343. PVOID callersAddress;
  344. PVOID callersCaller;
  345. status = (*SystemRegCreateKeyA)(
  346. hKey,
  347. lpSubKey,
  348. phkResult
  349. );
  350. if ( status == ERROR_SUCCESS ) {
  351. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  352. }
  353. if ( LeaksVerbose ) {
  354. ClRtlLogPrint("[LEAKS] RegCreateKeyA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  355. *phkResult,
  356. status,
  357. callersAddress,
  358. callersCaller );
  359. }
  360. return(status);
  361. } // RegCreateKeyA
  362. LONG
  363. APIENTRY
  364. RegCreateKeyW(
  365. HKEY hKey,
  366. LPCWSTR lpSubKey,
  367. PHKEY phkResult
  368. )
  369. {
  370. LONG status;
  371. PVOID callersAddress;
  372. PVOID callersCaller;
  373. status = (*SystemRegCreateKeyW)(
  374. hKey,
  375. lpSubKey,
  376. phkResult
  377. );
  378. if ( status == ERROR_SUCCESS ) {
  379. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  380. }
  381. if ( LeaksVerbose ) {
  382. ClRtlLogPrint("[LEAKS] RegCreateKeyW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  383. *phkResult,
  384. status,
  385. callersAddress,
  386. callersCaller );
  387. }
  388. return(status);
  389. } // RegCreateKeyW
  390. LONG
  391. APIENTRY
  392. RegCreateKeyExA(
  393. HKEY hKey,
  394. LPCSTR lpSubKey,
  395. DWORD Reserved,
  396. LPSTR lpClass,
  397. DWORD dwOptions,
  398. REGSAM samDesired,
  399. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  400. PHKEY phkResult,
  401. LPDWORD lpdwDisposition
  402. )
  403. {
  404. LONG status;
  405. PVOID callersAddress;
  406. PVOID callersCaller;
  407. status = (*SystemRegCreateKeyExA)(hKey,
  408. lpSubKey,
  409. Reserved,
  410. lpClass,
  411. dwOptions,
  412. samDesired,
  413. lpSecurityAttributes,
  414. phkResult,
  415. lpdwDisposition
  416. );
  417. if ( status == ERROR_SUCCESS ) {
  418. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  419. }
  420. if ( LeaksVerbose ) {
  421. ClRtlLogPrint("[LEAKS] RegCreateKeyExA returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  422. *phkResult,
  423. status,
  424. callersAddress,
  425. callersCaller );
  426. }
  427. return(status);
  428. } // RegCreateKeyExA
  429. LONG
  430. APIENTRY
  431. RegCreateKeyExW(
  432. HKEY hKey,
  433. LPCWSTR lpSubKey,
  434. DWORD Reserved,
  435. LPWSTR lpClass,
  436. DWORD dwOptions,
  437. REGSAM samDesired,
  438. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  439. PHKEY phkResult,
  440. LPDWORD lpdwDisposition
  441. )
  442. {
  443. LONG status;
  444. PVOID callersAddress;
  445. PVOID callersCaller;
  446. status = (*SystemRegCreateKeyExW)(
  447. hKey,
  448. lpSubKey,
  449. Reserved,
  450. lpClass,
  451. dwOptions,
  452. samDesired,
  453. lpSecurityAttributes,
  454. phkResult,
  455. lpdwDisposition
  456. );
  457. if ( status == ERROR_SUCCESS ) {
  458. SetHandleTable( *phkResult, TRUE, LeaksRegistry );
  459. }
  460. if ( LeaksVerbose ) {
  461. ClRtlLogPrint("[LEAKS] RegCreateKeyExW returns key %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  462. *phkResult,
  463. status,
  464. callersAddress,
  465. callersCaller );
  466. }
  467. return(status);
  468. } // RegCreateKeyExW
  469. LONG
  470. APIENTRY
  471. RegCloseKey(
  472. HKEY hKey
  473. )
  474. {
  475. LONG status;
  476. PVOID callersAddress;
  477. PVOID callersCaller;
  478. status = (*SystemRegCloseKey)( hKey );
  479. if ( status == ERROR_SUCCESS ) {
  480. SetHandleTable( hKey, FALSE, LeaksRegistry );
  481. }
  482. if ( LeaksVerbose ) {
  483. ClRtlLogPrint("[LEAKS] RegCloseKey for key %1!X! returns status %2!u!, called from %3!X! and %4!X!\n",
  484. hKey,
  485. status,
  486. callersAddress,
  487. callersCaller );
  488. }
  489. return(status);
  490. } // RegCloseKey
  491. BOOL
  492. WINAPI
  493. CloseHandle(
  494. IN OUT HANDLE hObject
  495. )
  496. {
  497. PVOID callersAddress;
  498. PVOID callersCaller;
  499. if ( HandleTable[ HINDEX( hObject )].InUse ) {
  500. RtlGetCallersAddress(&callersAddress,
  501. &callersCaller );
  502. HandleTable[ HINDEX( hObject )].InUse = FALSE;
  503. HandleTable[ HINDEX( hObject )].Caller = callersAddress;
  504. HandleTable[ HINDEX( hObject )].CallersCaller = callersCaller;
  505. if ( LeaksVerbose ) {
  506. ClRtlLogPrint("[LEAKS] CloseHandle for handle %1!X!, called from %2!X! and %3!X!\n",
  507. hObject,
  508. callersAddress,
  509. callersCaller );
  510. }
  511. }
  512. return (*SystemCloseHandle)( hObject );
  513. }
  514. BOOL
  515. WINAPI
  516. OpenProcessToken (
  517. IN HANDLE ProcessHandle,
  518. IN DWORD DesiredAccess,
  519. OUT PHANDLE TokenHandle
  520. )
  521. {
  522. BOOL status;
  523. PVOID callersAddress;
  524. PVOID callersCaller;
  525. status = (*SystemOpenProcessToken)(ProcessHandle,
  526. DesiredAccess,
  527. TokenHandle);
  528. if ( status ) {
  529. SetHandleTable( *TokenHandle, TRUE, LeaksToken );
  530. }
  531. if ( LeaksVerbose ) {
  532. ClRtlLogPrint("[LEAKS] OpenProcessToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  533. *TokenHandle,
  534. status,
  535. callersAddress,
  536. callersCaller );
  537. }
  538. return(status);
  539. }
  540. BOOL
  541. WINAPI
  542. OpenThreadToken (
  543. IN HANDLE ThreadHandle,
  544. IN DWORD DesiredAccess,
  545. IN BOOL OpenAsSelf,
  546. OUT PHANDLE TokenHandle
  547. )
  548. {
  549. BOOL status;
  550. PVOID callersAddress;
  551. PVOID callersCaller;
  552. status = (*SystemOpenThreadToken)(ThreadHandle,
  553. DesiredAccess,
  554. OpenAsSelf,
  555. TokenHandle);
  556. if ( status ) {
  557. SetHandleTable( *TokenHandle, TRUE, LeaksToken );
  558. }
  559. if ( LeaksVerbose ) {
  560. ClRtlLogPrint("[LEAKS] OpenThreadToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  561. *TokenHandle,
  562. status,
  563. callersAddress,
  564. callersCaller );
  565. }
  566. return(status);
  567. }
  568. BOOL
  569. WINAPI
  570. DuplicateToken(
  571. IN HANDLE ExistingTokenHandle,
  572. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  573. OUT PHANDLE DuplicateTokenHandle
  574. )
  575. {
  576. BOOL status;
  577. PVOID callersAddress;
  578. PVOID callersCaller;
  579. status = (*SystemDuplicateToken)(ExistingTokenHandle,
  580. ImpersonationLevel,
  581. DuplicateTokenHandle);
  582. if ( status ) {
  583. SetHandleTable( *DuplicateTokenHandle, TRUE, LeaksToken );
  584. }
  585. if ( LeaksVerbose ) {
  586. ClRtlLogPrint("[LEAKS] DuplicateToken returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  587. *DuplicateTokenHandle,
  588. status,
  589. callersAddress,
  590. callersCaller );
  591. }
  592. return(status);
  593. }
  594. BOOL
  595. WINAPI
  596. DuplicateTokenEx(
  597. IN HANDLE hExistingToken,
  598. IN DWORD dwDesiredAccess,
  599. IN LPSECURITY_ATTRIBUTES lpTokenAttributes,
  600. IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
  601. IN TOKEN_TYPE TokenType,
  602. OUT PHANDLE phNewToken)
  603. {
  604. BOOL status;
  605. PVOID callersAddress;
  606. PVOID callersCaller;
  607. status = (*SystemDuplicateTokenEx)(hExistingToken,
  608. dwDesiredAccess,
  609. lpTokenAttributes,
  610. ImpersonationLevel,
  611. TokenType,
  612. phNewToken);
  613. if ( status ) {
  614. SetHandleTable( *phNewToken, TRUE, LeaksToken );
  615. }
  616. if ( LeaksVerbose ) {
  617. ClRtlLogPrint("[LEAKS] DuplicateTokenEx returns handle %1!X!, status %2!u!, called from %3!X! and %4!X!\n",
  618. *phNewToken,
  619. status,
  620. callersAddress,
  621. callersCaller );
  622. }
  623. return(status);
  624. }