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.

448 lines
18 KiB

  1. // Ruler
  2. // 1 2 3 4 5 6 7 8
  3. //345678901234567890123456789012345678901234567890123456789012345678901234567890
  4. /********************************************************************/
  5. /* */
  6. /* The standard layout. */
  7. /* */
  8. /* The standard layout for 'cpp' files in this code is as */
  9. /* follows: */
  10. /* */
  11. /* 1. Include files. */
  12. /* 2. Constants local to the class. */
  13. /* 3. Data structures local to the class. */
  14. /* 4. Data initializations. */
  15. /* 5. Static functions. */
  16. /* 6. Class functions. */
  17. /* */
  18. /* The constructor is typically the first function, class */
  19. /* member functions appear in alphabetical order with the */
  20. /* destructor appearing at the end of the file. Any section */
  21. /* or function this is not required is simply omitted. */
  22. /* */
  23. /********************************************************************/
  24. #include "InterfacePCH.hpp"
  25. #include "DefaultHeap.hpp"
  26. #include "Global.hpp"
  27. #include "New.hpp"
  28. #include "WindowsHeap.hpp"
  29. /********************************************************************/
  30. /* */
  31. /* Constants local to the class. */
  32. /* */
  33. /* The constants supplied here are for common values. */
  34. /* */
  35. /********************************************************************/
  36. CONST SBIT32 NoHeapSize = -1;
  37. CONST SBIT32 ResizeDown = -64;
  38. CONST SBIT32 StandardSize = (1024 * 1024);
  39. /********************************************************************/
  40. /* */
  41. /* Data structures local to the class. */
  42. /* */
  43. /* We need to keep various information along with the heap */
  44. /* so here we supply a structure to hold it all. */
  45. /* */
  46. /********************************************************************/
  47. typedef struct
  48. {
  49. DWORD Flags;
  50. DEFAULT_HEAP Rockall;
  51. }
  52. WINDOWS_HEAP;
  53. /********************************************************************/
  54. /* */
  55. /* Create a new heap. */
  56. /* */
  57. /* Create a new heap and prepare it for use. If any problems */
  58. /* are encountered the request is rejected. */
  59. /* */
  60. /********************************************************************/
  61. extern "C" HANDLE WindowsHeapCreate
  62. (
  63. DWORD Flags,
  64. DWORD InitialSize,
  65. DWORD MaximumSize
  66. )
  67. {
  68. //
  69. // We do not support all the functionality with
  70. // this interface so just reject any calls that
  71. // require the unsupported features.
  72. //
  73. if ( MaximumSize <= 0 )
  74. {
  75. REGISTER WINDOWS_HEAP *WindowsHeap =
  76. #ifdef NO_DEFAULT_HEAP
  77. ((WINDOWS_HEAP*) malloc( sizeof(WINDOWS_HEAP) ));
  78. #else
  79. ((WINDOWS_HEAP*) DefaultHeap.New( sizeof(WINDOWS_HEAP) ));
  80. #endif
  81. //
  82. // If we were unable to allocate space for
  83. // the root of the heap then we exit.
  84. //
  85. if ( WindowsHeap != NULL )
  86. {
  87. //
  88. // Save the flags for later calls.
  89. //
  90. WindowsHeap -> Flags = Flags;
  91. //
  92. // Call the heap constructor.
  93. //
  94. PLACEMENT_NEW( & WindowsHeap -> Rockall,DEFAULT_HEAP )
  95. (
  96. ((SBIT32) (InitialSize + StandardSize)),
  97. True,
  98. False,
  99. ((BOOLEAN) ((Flags & HEAP_NO_SERIALIZE) == 0))
  100. );
  101. //
  102. // Ensure the heap is initialized correctly.
  103. //
  104. if ( ! WindowsHeap -> Rockall.Corrupt() )
  105. { return ((HANDLE) WindowsHeap); }
  106. else
  107. { free( WindowsHeap ); }
  108. }
  109. }
  110. return NULL;
  111. }
  112. /********************************************************************/
  113. /* */
  114. /* Allocate memory. . */
  115. /* */
  116. /* Create a new memory allocation and verify it works. if */
  117. /* not then throw an exception or return a status. */
  118. /* */
  119. /********************************************************************/
  120. extern "C" LPVOID WindowsHeapAlloc( HANDLE Heap,DWORD Flags,DWORD Size )
  121. {
  122. REGISTER DWORD AllFlags =
  123. (Flags | (((WINDOWS_HEAP*) Heap) -> Flags));
  124. REGISTER void *NewMemory =
  125. (
  126. ((WINDOWS_HEAP*) Heap) -> Rockall.New
  127. (
  128. Size,
  129. NULL,
  130. (AllFlags & HEAP_ZERO_MEMORY)
  131. )
  132. );
  133. //
  134. // If the caller has requested an exception when
  135. // an error occurs. We will generate this instead
  136. // of returning a status.
  137. //
  138. if ( (NewMemory == NULL) && (AllFlags & HEAP_GENERATE_EXCEPTIONS) )
  139. {
  140. SetLastError( ERROR_INVALID_PARAMETER );
  141. RaiseException( STATUS_NO_MEMORY,0,0,NULL );
  142. }
  143. return NewMemory;
  144. }
  145. /********************************************************************/
  146. /* */
  147. /* Compact the heap. */
  148. /* */
  149. /* Compact the heap by returning any unallocated space to the */
  150. /* operating system. This can prove to be very expensive if */
  151. /* the space is later reclaimed. */
  152. /* */
  153. /********************************************************************/
  154. extern "C" UINT WindowsHeapCompact( HANDLE Heap,DWORD Flags )
  155. {
  156. //
  157. // We instruct the heap to return any available
  158. // space to the operating system. If we later
  159. // choose to regain this space it is very expensive
  160. // so lets hope the user knew what he was doing.
  161. //
  162. ((WINDOWS_HEAP*) Heap) -> Rockall.Truncate();
  163. return 1;
  164. }
  165. /********************************************************************/
  166. /* */
  167. /* Free memory. */
  168. /* */
  169. /* Free a memory allocation so that the space may be recycled */
  170. /* for subsequent memory allocation requests. */
  171. /* */
  172. /********************************************************************/
  173. extern "C" BOOL WindowsHeapFree( HANDLE Heap,DWORD Flags,LPVOID Memory )
  174. {
  175. //
  176. // We release the memory allocation if it belongs to us.
  177. // If not then we simply fail the request. Regardless,
  178. // we are not negatively effected either way.
  179. //
  180. return ((BOOL) ((WINDOWS_HEAP*) Heap) -> Rockall.Delete( Memory ));
  181. }
  182. /********************************************************************/
  183. /* */
  184. /* Lock the heap. */
  185. /* */
  186. /* Lock the heap by claiming all of the associated heap locks. */
  187. /* All the locks associated with a heap help make the heap */
  188. /* scale well but are a big performance hit for this type of */
  189. /* request. */
  190. /* */
  191. /********************************************************************/
  192. extern "C" BOOL WindowsHeapLock( HANDLE Heap )
  193. {
  194. //
  195. // We have a whole fleet of locks assocaited with a heap.
  196. // Asking to claim all of them is not smart in most cases.
  197. // Nonetheless, this is part of the existing functionality
  198. // so we support it.
  199. //
  200. (((WINDOWS_HEAP*) Heap) -> Rockall.LockAll());
  201. return TRUE;
  202. }
  203. /********************************************************************/
  204. /* */
  205. /* Reallocate memory. */
  206. /* */
  207. /* Reallocate a portion of memory and possibly copy the data */
  208. /* to the enlarged memory area. */
  209. /* */
  210. /********************************************************************/
  211. extern "C" LPVOID WindowsHeapReAlloc
  212. (
  213. HANDLE Heap,
  214. DWORD Flags,
  215. LPVOID Memory,
  216. DWORD Size
  217. )
  218. {
  219. REGISTER DWORD AllFlags =
  220. (Flags | (((WINDOWS_HEAP*) Heap) -> Flags));
  221. REGISTER void *NewMemory =
  222. (
  223. ((WINDOWS_HEAP*) Heap) -> Rockall.Resize
  224. (
  225. Memory,
  226. Size,
  227. ((AllFlags & HEAP_REALLOC_IN_PLACE_ONLY) ? 0 : ResizeDown),
  228. false,
  229. (AllFlags & HEAP_ZERO_MEMORY)
  230. )
  231. );
  232. //
  233. // If the caller has requested an exception when
  234. // an error occurs. We will generate this instead
  235. // of returning a status.
  236. //
  237. if ( (NewMemory == NULL) && (AllFlags & HEAP_GENERATE_EXCEPTIONS) )
  238. {
  239. SetLastError( ERROR_INVALID_PARAMETER );
  240. RaiseException( STATUS_NO_MEMORY,0,0,NULL );
  241. }
  242. return NewMemory;
  243. }
  244. /********************************************************************/
  245. /* */
  246. /* Reset the heap. */
  247. /* */
  248. /* Delete all outstanding memory allocations while leaving */
  249. /* the structure of the heap in place ready for new memory */
  250. /* allocation requests. */
  251. /* */
  252. /********************************************************************/
  253. extern "C" VOID WindowsHeapReset( HANDLE Heap )
  254. {
  255. //
  256. // We have been asked to delete all the outstanding
  257. // memory allocations. This is significant and costly
  258. // process. Nonetheless, the overhead is the same as
  259. // around 20-30 delete requested so it can be worthwhile
  260. // in a number of cases.
  261. //
  262. ((WINDOWS_HEAP*) Heap) -> Rockall.DeleteAll();
  263. }
  264. /********************************************************************/
  265. /* */
  266. /* Allocation size. */
  267. /* */
  268. /* Although Rockall optionally supplies the allocation size */
  269. /* when a new allocation is requested. Nonetheless, this has */
  270. /* to be done the hard way with other interfaces. */
  271. /* */
  272. /********************************************************************/
  273. extern "C" DWORD WindowsHeapSize( HANDLE Heap,DWORD Flags,LPVOID Memory )
  274. {
  275. AUTO INT Size;
  276. //
  277. // We have to go to quite a bit of trouble to figure
  278. // out the allocation size. Unlike many other allocators
  279. // we only keep track of each allocations using 2 bits.
  280. // This combined with trying to establish that the allocation
  281. // is not unallocated and sitting in the cache somewhere
  282. // combine to make this quite expensive.
  283. //
  284. if ( ((WINDOWS_HEAP*) Heap) -> Rockall.Details( Memory,& Size ) )
  285. { return Size; }
  286. else
  287. { return ((DWORD) NoHeapSize); }
  288. }
  289. /********************************************************************/
  290. /* */
  291. /* Unlock the heap. */
  292. /* */
  293. /* Unlock the heap and release all the associated heap locks. */
  294. /* The multiple locks that need to be released make this quite */
  295. /* an expensive request. */
  296. /* */
  297. /********************************************************************/
  298. extern "C" BOOL WindowsHeapUnlock( HANDLE Heap )
  299. {
  300. //
  301. // We have a whole fleet of locks assocaited with a heap.
  302. // Asking to claim all of them is not smart in most cases.
  303. // Nonetheless, this is part of the existing functionality
  304. // so we support it.
  305. //
  306. (((WINDOWS_HEAP*) Heap) -> Rockall.UnlockAll());
  307. return TRUE;
  308. }
  309. /********************************************************************/
  310. /* */
  311. /* Validate the heap. */
  312. /* */
  313. /* Validate the heap or a specific heap allocation to ensure */
  314. /* all is well. We have to go to quite a bit of trouble to */
  315. /* figure this out so this call can be quite expensive. */
  316. /* */
  317. /********************************************************************/
  318. extern "C" BOOL WindowsHeapValidate( HANDLE Heap,DWORD Flags,LPVOID Memory )
  319. {
  320. //
  321. // We have to go to quite a bit of trouble to figure
  322. // out the allocation size. Unlike many other allocators
  323. // we only keep track of each allocations using 2 bits.
  324. // This combined with trying to establish that the allocation
  325. // is not unallocated and sitting in the cache somewhere
  326. // combine to make this quite expensive.
  327. //
  328. return (((WINDOWS_HEAP*) Heap) -> Rockall.Verify( Memory ));
  329. }
  330. /********************************************************************/
  331. /* */
  332. /* Walk the heap. */
  333. /* */
  334. /* Walk the heap and provide information about every allocated */
  335. /* and unallocated portion of memory. Needless to say this is */
  336. /* typically a long process and the request is not cheap. */
  337. /* */
  338. /********************************************************************/
  339. extern "C" BOOL WindowsHeapWalk( HANDLE Heap,LPPROCESS_HEAP_ENTRY Walk )
  340. {
  341. AUTO bool Active;
  342. REGISTER BOOL Result =
  343. (
  344. ((WINDOWS_HEAP*) Heap) -> Rockall.Walk
  345. (
  346. & Active,
  347. ((void**) & Walk -> lpData),
  348. ((int*) & Walk -> cbData)
  349. )
  350. );
  351. //
  352. // If we managed to find the next element we
  353. // fill in all the other fields as needed.
  354. //
  355. if ( Result )
  356. {
  357. //
  358. // Fill in all the addition fields just
  359. // to be compatible with the existing
  360. // functionality.
  361. //
  362. Walk -> cbOverhead = 0;
  363. Walk -> iRegionIndex = 0;
  364. Walk -> wFlags =
  365. (
  366. (Active)
  367. ? ((WORD) PROCESS_HEAP_ENTRY_BUSY)
  368. : ((WORD) PROCESS_HEAP_UNCOMMITTED_RANGE)
  369. );
  370. }
  371. return Result;
  372. }
  373. /********************************************************************/
  374. /* */
  375. /* Delete a heap. */
  376. /* */
  377. /* Delete a heap and release all the associated space. */
  378. /* */
  379. /********************************************************************/
  380. extern "C" BOOL WindowsHeapDestroy( HANDLE Heap )
  381. {
  382. if ( ! ((WINDOWS_HEAP*) Heap) -> Rockall.Corrupt() )
  383. {
  384. //
  385. // We do not appear to have damaged the heap
  386. // so it should be safe to delete it.
  387. //
  388. PLACEMENT_DELETE( & ((WINDOWS_HEAP*) Heap) -> Rockall,DEFAULT_HEAP );
  389. #ifdef NO_DEFAULT_HEAP
  390. free( ((WINDOWS_HEAP*) Heap) );
  391. #else
  392. DefaultHeap.Delete( ((WINDOWS_HEAP*) Heap) );
  393. #endif
  394. return TRUE;
  395. }
  396. else
  397. { return FALSE; }
  398. }