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.

441 lines
12 KiB

  1. /*
  2. ** memmon\api\memmon.c - Win32 functions to talk to Memmon
  3. */
  4. #include "Precomp.h"
  5. #ifdef TRACK_ALLOCATIONS // { TRACK_ALLOCATIONS
  6. // #define LOG_ALLOCATIONS 1
  7. static HANDLE hMemmon = INVALID_HANDLE_VALUE; /* VxD handle */
  8. static unsigned uMyProcessId;
  9. /*
  10. ** OpenMemmon - Must be called before any other calls. Gets a handle to
  11. ** Memmon.
  12. */
  13. int OpenMemmon( void )
  14. {
  15. #ifdef LOG_ALLOCATIONS
  16. OutputDebugString("OpenMemmon()\r\n");
  17. #endif
  18. uMyProcessId = GetCurrentProcessId();
  19. if( hMemmon != INVALID_HANDLE_VALUE )
  20. return TRUE;
  21. hMemmon = CreateFile( "\\\\.\\memmon", GENERIC_READ, 0,
  22. NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  23. if( hMemmon == INVALID_HANDLE_VALUE )
  24. return FALSE;
  25. else
  26. return TRUE;
  27. }
  28. /*
  29. ** CloseMemmon - Should be called when the program is finished with Memmon.
  30. ** Closes handle.
  31. */
  32. void CloseMemmon( void )
  33. {
  34. #ifdef LOG_ALLOCATIONS
  35. OutputDebugString("CloseMemmon()\r\n");
  36. #endif
  37. /*
  38. ** If we have a valid handle to memmon, free any buffers and
  39. ** close it.
  40. */
  41. if( hMemmon != INVALID_HANDLE_VALUE ) {
  42. FreeBuffer();
  43. CloseHandle( hMemmon );
  44. hMemmon = INVALID_HANDLE_VALUE;
  45. }
  46. }
  47. /*
  48. ** FindFirstVxD - Get information on the first VxD in the system
  49. **
  50. ** Returns 0 on failure, number of VxDs on success
  51. */
  52. int FindFirstVxD( VxDInfo * info )
  53. {
  54. int temp, num;
  55. temp = info->vi_size;
  56. DeviceIoControl( hMemmon, MEMMON_DIOC_FindFirstVxD,
  57. info, sizeof( VxDInfo ), NULL, 0, NULL, NULL );
  58. num = info->vi_size;
  59. info->vi_size = temp;
  60. return num;
  61. }
  62. /*
  63. ** FindNextVxD - Get information on the next VxD in the system. Must
  64. ** pass same pointer as used in FindFirstVxD. Continue to call
  65. ** until it returns FALSE to get all VxDs.
  66. **
  67. ** Returns 0 on failure (no more VxDs), >0 on success, -1 for restart
  68. */
  69. int FindNextVxD( VxDInfo * info )
  70. {
  71. DeviceIoControl( hMemmon, MEMMON_DIOC_FindNextVxD,
  72. info, sizeof( VxDInfo ), NULL, 0, NULL, NULL );
  73. return info->vi_vhandle;
  74. }
  75. /*
  76. ** GetVxDLoadInfo - Get information about VxD objects, sizes, etc.
  77. ** info must be large enough to hold all of them. Use obj
  78. ** count from VxDInfo to allocate appropriate memory. handle
  79. ** comes from VxDInfo as well.
  80. **
  81. ** Returns 0 on failure, >0 on success
  82. */
  83. int GetVxDLoadInfo( VxDLoadInfo * info, int handle, int size )
  84. {
  85. info->vli_size = size;
  86. info->vli_objinfo[0].voi_linearaddr = handle;
  87. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetVxDLoadInfo,
  88. info, size, NULL, 0, NULL, NULL );
  89. }
  90. /*
  91. ** GetFirstContext - Get information on first context in system.
  92. ** ProcessIDs returned will match Toolhelp32 process ids.
  93. **
  94. ** ciFlags field of ContextInfo contains 1 if this is the first time
  95. ** this context has been examined.
  96. **
  97. ** bIgnoreStatus = FALSE - Causes ciFlags to be zero if this context
  98. ** is examined again
  99. ** bIgnoreStatus = TRUE - ciFlags will be the same next time as it
  100. ** is this time
  101. **
  102. ** Returns 0 on failure, >0 on success
  103. */
  104. int GetFirstContext( ContextInfo * context, BOOL bIgnoreStatus )
  105. {
  106. context->ciProcessID = uMyProcessId;
  107. if( bIgnoreStatus )
  108. context->ciFlags = 1;
  109. else
  110. context->ciFlags = 0;
  111. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetFirstContext,
  112. context, sizeof( ContextInfo ), NULL, 0, NULL, NULL );
  113. }
  114. /*
  115. ** GetNextContext - Pass same structure used in GetFirstContext
  116. **
  117. ** ciFlags field of ContextInfo contains 1 if this is the first time
  118. ** this context has been examined.
  119. **
  120. ** bIgnoreStatus = FALSE - Causes ciFlags to be zero if this context
  121. ** is examined again
  122. ** bIgnoreStatus = TRUE - ciFlags will be the same next time as it
  123. ** is this time
  124. **
  125. ** Returns 0 on failure (no more contexts), >0 on success
  126. **
  127. ** On failure, if the ciHandle field is -1, the list changed during
  128. ** the search, and needs to be read again. (FindFirstContext again)
  129. */
  130. int GetNextContext( ContextInfo * context, BOOL bIgnoreStatus )
  131. {
  132. if( bIgnoreStatus )
  133. context->ciFlags = 1;
  134. else
  135. context->ciFlags = 0;
  136. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetNextContext,
  137. context, sizeof( ContextInfo ), NULL, 0, NULL, NULL );
  138. }
  139. /*
  140. ** GetContextInfo - Get a list of block addresses and sizes for a context
  141. ** Use ContextInfo to decide how many, and allocate enough space.
  142. **
  143. ** Returns 0 on failure, >0 on success
  144. */
  145. int GetContextInfo( int handle, BlockRecord * info, int numblocks )
  146. {
  147. info->brLinAddr = numblocks;
  148. info->brPages = handle;
  149. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetContextInfo,
  150. info, numblocks * sizeof( BlockRecord ), NULL,
  151. 0, NULL, NULL );
  152. }
  153. /*
  154. ** SetBuffer - Allocate and lock some number of pages
  155. ** - If called more than once, the previous buffer is freed.
  156. **
  157. ** pages is the number of pages to allocate
  158. **
  159. ** Returns NULL on failure, pointer to buffer on success
  160. */
  161. void * SetBuffer( int pages )
  162. {
  163. unsigned uAddr = (unsigned)pages;
  164. int iRes;
  165. iRes = DeviceIoControl( hMemmon, MEMMON_DIOC_SetBuffer,
  166. &uAddr, sizeof( uAddr ), NULL, 0, NULL, NULL );
  167. if( iRes )
  168. return (void *)uAddr;
  169. else
  170. return NULL;
  171. }
  172. /*
  173. ** FreeBuffer - Free the buffer allocated by SetBuffer
  174. **
  175. ** Returns 0 on failure, >0 on success
  176. */
  177. int FreeBuffer( void )
  178. {
  179. return DeviceIoControl( hMemmon, MEMMON_DIOC_FreeBuffer,
  180. NULL, 0, NULL, 0, NULL, NULL );
  181. }
  182. /*
  183. ** GetPageInfo - Get present/committed/accessed information about a
  184. ** range of pages in a specific process
  185. **
  186. ** uAddr is the address to get the information
  187. ** uNumPages is the number of pages to get information on
  188. ** uProcessID is GetCurrentProcessID() or a process id from ToolHelp
  189. ** It's ignored if the address is a global address
  190. ** pBuffer is a buffer uNumPages long where the info will be stored:
  191. ** - one byte for each page, a combination of the following flags:
  192. ** MEMMON_Present
  193. ** MEMMON_Committed
  194. ** MEMMON_Accessed
  195. ** MEMMON_Writeable
  196. ** MEMMON_Lock
  197. **
  198. ** Returns 0 on failure, >0 on success
  199. */
  200. int GetPageInfo( unsigned uAddr, unsigned uNumPages,
  201. unsigned uProcessID, char * pBuffer )
  202. {
  203. PAGEINFO pi;
  204. pi.uAddr = uAddr;
  205. pi.uNumPages = uNumPages;
  206. pi.uProcessID = uProcessID;
  207. pi.uCurrentProcessID = uMyProcessId;
  208. pi.uOperation = PAGES_QUERY;
  209. pi.pBuffer = pBuffer;
  210. return DeviceIoControl( hMemmon, MEMMON_DIOC_PageInfo,
  211. &pi, sizeof( PAGEINFO ), NULL, 0, NULL, NULL );
  212. }
  213. /*
  214. ** ClearAccessed - Clear accessed bits for a range of process pages
  215. **
  216. ** uAddr is the address of the first page to clear
  217. ** uNumPages is the number of pages to reset
  218. ** uProcessID is GetCurrentProcessID() or a process id from ToolHelp
  219. ** It's ignored if the block is a global block
  220. **
  221. ** Returns 0 on failure, >0 on success
  222. */
  223. int ClearAccessed( unsigned uAddr, unsigned uNumPages, unsigned uProcessID )
  224. {
  225. PAGEINFO pi;
  226. pi.uAddr = uAddr;
  227. pi.uNumPages = uNumPages;
  228. pi.uProcessID = uProcessID;
  229. pi.uCurrentProcessID = uMyProcessId;
  230. pi.uOperation = PAGES_CLEAR;
  231. pi.pBuffer = NULL;
  232. return DeviceIoControl( hMemmon, MEMMON_DIOC_PageInfo,
  233. &pi, sizeof( PAGEINFO ), NULL, 0, NULL, NULL );
  234. }
  235. /*
  236. ** GetHeapSize - return how many allocated blocks in kernel heaps
  237. **
  238. ** uSwap - Estimated number allocated blocks in swappable heap
  239. ** uFixed - Estimated number allocated blocks in fixed heap
  240. **
  241. ** This number is lower than the actual number of blocks in the heap.
  242. ** Some VMM functions call HeapAllocate directly rather than through
  243. ** the service and aren't included in this count. Free blocks aren't
  244. ** included in this count.
  245. **
  246. */
  247. void GetHeapSizeEstimate( unsigned * uSwap, unsigned * uFixed )
  248. {
  249. unsigned info[2];
  250. DeviceIoControl( hMemmon, MEMMON_DIOC_GetHeapSize,
  251. info, sizeof( info ), NULL, 0, NULL, NULL );
  252. *uSwap = info[0];
  253. *uFixed = info[1];
  254. }
  255. /*
  256. ** GetHeapList - Get list of busy and free blocks in one of the kernel
  257. ** heaps
  258. **
  259. ** pBuffer - buffer to store records
  260. ** uSize - size of buffer in bytes
  261. ** uFlags - MEMMON_HEAPSWAP or MEMMON_HEAPLOCK
  262. **
  263. ** Each record is two dwords. The first, contains an address and flags:
  264. **
  265. ** MEMMON_HP_FREE - This block heap is not in use
  266. ** MEMMON_HP_VALID - If set the size of the block can be calculated by
  267. ** subtracting this address from the next. If this
  268. ** flag isn't set, this block is a sentinel block and
  269. ** it's size is 0.
  270. **
  271. ** The second dword contains the EIP of the caller. This value is 0
  272. ** for all free blocks. If this value is 0 for a busy block,
  273. ** HeapAllocate was called directly (not through the service) and so
  274. ** this block was allocated somewhere in VMM.
  275. **
  276. ** Returns number of heap blocks stored in buffer
  277. */
  278. int GetHeapList( unsigned * pBuffer, unsigned uSize, unsigned uFlags )
  279. {
  280. unsigned info[3];
  281. info[0] = (unsigned)pBuffer;
  282. info[1] = uSize;
  283. info[2] = uFlags;
  284. DeviceIoControl( hMemmon, MEMMON_DIOC_GetHeapList,
  285. info, sizeof( info ), NULL, 0, NULL, NULL );
  286. return info[0];
  287. }
  288. /*
  289. ** GetSysInfo - get system info from memmon
  290. **
  291. ** pInfo - pointer to SYSINFO struct to fill in
  292. **
  293. ** Returns: 0 on failure, non 0 on success
  294. */
  295. int GetSysInfo( PSYSINFO pInfo )
  296. {
  297. pInfo->infoSize = sizeof( SYSINFO );
  298. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetSysInfo,
  299. pInfo, pInfo->infoSize, NULL, 0, NULL, NULL );
  300. }
  301. /*
  302. ** AddName - Add a name to Memmon's name list for this process
  303. **
  304. ** uAddress - Address of block to name
  305. ** pszName - name of block
  306. **
  307. ** Returns 0 on success, non-0 on failure
  308. */
  309. int AddName( unsigned uAddress, char * pszName )
  310. {
  311. unsigned info[3];
  312. int res;
  313. #ifdef LOG_ALLOCATIONS
  314. char szDebug[96];
  315. wsprintf(szDebug, "ADD - 0x%08lX - %s\r\n", uAddress, pszName);
  316. OutputDebugString(szDebug);
  317. #endif
  318. info[0] = uMyProcessId;
  319. info[1] = uAddress;
  320. info[2] = (unsigned)pszName;
  321. res = DeviceIoControl( hMemmon, MEMMON_DIOC_AddName,
  322. info, sizeof( info ), NULL, 0, NULL, NULL );
  323. if (res)
  324. OutputDebugString("SUCCESS\r\n");
  325. else
  326. OutputDebugString("FAILURE\r\n");
  327. return res;
  328. }
  329. /*
  330. ** RemoveName - Remove a name from Memmon's name list for this process
  331. **
  332. ** uAddress - Address of block to remove name
  333. **
  334. ** Returns 0 on success, non-0 on failure
  335. */
  336. int RemoveName( unsigned uAddress )
  337. {
  338. unsigned info[2];
  339. #ifdef LOG_ALLOCATIONS
  340. char szDebug[96];
  341. wsprintf(szDebug, "RMV - 0x%08lX \r\n", uAddress);
  342. OutputDebugString(szDebug);
  343. #endif
  344. info[0] = uMyProcessId;
  345. info[1] = uAddress;
  346. return DeviceIoControl( hMemmon, MEMMON_DIOC_RemoveName,
  347. info, sizeof( info ), NULL, 0, NULL, NULL );
  348. }
  349. /*
  350. ** GetFirstName - Get first name in name list for a context
  351. **
  352. ** pContext - Context to get first name in
  353. ** pName - Buffer to use for name info
  354. **
  355. ** Returns 0 on success, non-0 on failure
  356. */
  357. int GetFirstName( ContextInfo * pContext, PBLOCKNAME pBlock )
  358. {
  359. unsigned info[2];
  360. info[0] = (unsigned)pContext;
  361. info[1] = (unsigned)pBlock;
  362. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetFirstName,
  363. info, sizeof( info ), NULL, 0, NULL, NULL );
  364. }
  365. /*
  366. ** GetNextName - Remove a name from Memmon's name list for this process
  367. **
  368. ** pBlock - Buffer to save info
  369. **
  370. ** Returns 0 on success, non-0 on failure
  371. */
  372. int GetNextName( PBLOCKNAME pBlock )
  373. {
  374. return DeviceIoControl( hMemmon, MEMMON_DIOC_GetNextName,
  375. pBlock, sizeof( BLOCKNAME ), NULL, 0, NULL, NULL );
  376. }
  377. #endif // } TRACK_ALLOCATIONS