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.

1619 lines
34 KiB

  1. //--------------------------------------------------------------------------;
  2. //
  3. // File: Exact.c
  4. //
  5. // Copyright (C) Microsoft Corporation, 1993 - 1996 All rights reserved
  6. //
  7. // Abstract:
  8. // Contains exact memory allocation routines.
  9. //
  10. // Contents:
  11. // GetPageSize()
  12. // SetExactHeaderInfo()
  13. // GetExactHeaderInfo()
  14. // ExactAllocPtr()
  15. // ExactFreePtr()
  16. // GetNumAllocations()
  17. // GetMemoryHandle()
  18. // ExactSize()
  19. // ExactReAllocPtr()
  20. // GetPointer()
  21. // SetPointer()
  22. // ExactHeapAllocPtr()
  23. // ExactHeapCreate()
  24. // ExactHeapDestroy()
  25. // ExactHeapFreePtr()
  26. // ExactHeapReAllocPtr()
  27. // ExactHeapSize()
  28. //
  29. // History:
  30. // 12/01/93 Fwong Verifying correctness.
  31. // 01/14/94 Fwong Adding Win32 Support.
  32. //
  33. //--------------------------------------------------------------------------;
  34. #include <windows.h>
  35. #ifdef WIN32
  36. #include <windowsx.h>
  37. #endif
  38. //==========================================================================;
  39. //
  40. // Structures...
  41. //
  42. //==========================================================================;
  43. #ifdef WIN32
  44. typedef struct EXACTHDR_tag
  45. {
  46. DWORD fdwFlags;
  47. LPVOID pEvil;
  48. LPVOID pStart;
  49. } EXACTHDR;
  50. typedef EXACTHDR *PEXACTHDR;
  51. typedef EXACTHDR NEAR *NPEXACTHDR;
  52. typedef EXACTHDR FAR *LPEXACTHDR;
  53. #else
  54. typedef struct EXACTHDR_tag
  55. {
  56. DWORD fdwFlags;
  57. HGLOBAL hMem;
  58. } EXACTHDR;
  59. typedef EXACTHDR *PEXACTHDR;
  60. typedef EXACTHDR NEAR *NPEXACTHDR;
  61. typedef EXACTHDR FAR *LPEXACTHDR;
  62. #endif
  63. typedef struct EXACTHEAP_tag
  64. {
  65. HGLOBAL hMem;
  66. DWORD cNumAlloc;
  67. DWORD cMaxAlloc;
  68. DWORD fdwFlags;
  69. LPVOID pPointers;
  70. } EXACTHEAP;
  71. typedef EXACTHEAP *PEXACTHEAP;
  72. typedef EXACTHEAP NEAR *NPEXACTHEAP;
  73. typedef EXACTHEAP FAR *LPEXACTHEAP;
  74. //==========================================================================;
  75. //
  76. // Constants...
  77. //
  78. //==========================================================================;
  79. #define EXACTMEM_SIGNATURE 0xdead0000
  80. #define EXACTMEM_SIGNATUREMASK 0xffff0000
  81. #define EXACTMEM_HANDLE 0x00000001
  82. #define EXACTMEM_INUSE 0x00000002
  83. #define HEAPCHUNKSIZE 32
  84. //==========================================================================;
  85. //
  86. // Macros...
  87. //
  88. //==========================================================================;
  89. #define IS_BAD_HEADER_SIGNATURE(a) (EXACTMEM_SIGNATURE != \
  90. ((a).fdwFlags & EXACTMEM_SIGNATUREMASK))
  91. #define IS_BAD_HEAP_SIGNATURE(a) (EXACTMEM_SIGNATURE != \
  92. ((a)->fdwFlags & EXACTMEM_SIGNATUREMASK))
  93. #define LOCK_HEAP(a) ((a)->fdwFlags |= EXACTMEM_INUSE)
  94. #define UNLOCK_HEAP(a) ((a)->fdwFlags &= (~EXACTMEM_INUSE))
  95. #ifdef WIN32
  96. #define WAIT_FOR_HEAP(a) while((a)->fdwFlags & EXACTMEM_INUSE) Sleep(0)
  97. #else
  98. #define WAIT_FOR_HEAP(a) while((a)->fdwFlags & EXACTMEM_INUSE)
  99. #endif
  100. //==========================================================================;
  101. //
  102. // Debug Stuff...
  103. //
  104. //==========================================================================;
  105. #ifdef DEBUG
  106. #define DBGOUT(a) OutputDebugString("MEMGR:" a "\r\n");
  107. #else
  108. #define DBGOUT(a) //
  109. #endif
  110. #define DIVRU(a,b) (((a)/(b)) + (((a)%(b))?1:0))
  111. DWORD gcAllocations = 0L;
  112. //--------------------------------------------------------------------------;
  113. //
  114. // DWORD GetPageSize
  115. //
  116. // Description:
  117. // Gets the page size for this platform.
  118. //
  119. // Arguments:
  120. // None.
  121. //
  122. // Return (DWORD):
  123. // Size (in bytes) of a page.
  124. //
  125. // History:
  126. // 08/09/94 Fwong Retroactive commenting. <Internal>
  127. //
  128. //--------------------------------------------------------------------------;
  129. #ifdef WIN32
  130. DWORD GetPageSize
  131. (
  132. void
  133. )
  134. {
  135. SYSTEM_INFO sinf;
  136. GetSystemInfo(&sinf);
  137. return (sinf.dwPageSize);
  138. } // GetPageSize()
  139. #endif // WIN32
  140. //--------------------------------------------------------------------------;
  141. //
  142. // BOOL SetExactHeaderInfo
  143. //
  144. // Description:
  145. // Given a pointer to an ExactAlloc'ed buffer, it stores the header
  146. // information.
  147. //
  148. // Arguments:
  149. // LPVOID pStart: Pointer to ExactAlloc'ed buffer.
  150. //
  151. // LPEXACTHDR pExactHdr: Pointer to header.
  152. //
  153. // Return (BOOL):
  154. // TRUE if successful, FALSE otherwise.
  155. //
  156. // History:
  157. // 08/10/94 Fwong Facilitating writing headers. <Internal>
  158. //
  159. //--------------------------------------------------------------------------;
  160. BOOL SetExactHeaderInfo
  161. (
  162. LPVOID pStart,
  163. LPEXACTHDR pExactHdr
  164. )
  165. {
  166. pStart = ((LPBYTE)pStart) - sizeof(EXACTHDR);
  167. if(IsBadWritePtr(pStart,sizeof(EXACTHDR)))
  168. {
  169. return FALSE;
  170. }
  171. hmemcpy(pStart,pExactHdr,sizeof(EXACTHDR));
  172. return TRUE;
  173. } // SetExactHeaderInfo()
  174. //--------------------------------------------------------------------------;
  175. //
  176. // BOOL GetExactHeaderInfo
  177. //
  178. // Description:
  179. // Given a pointer to an ExactAlloc'ed buffer, it stores the header
  180. // information.
  181. //
  182. // Arguments:
  183. // LPVOID pStart: Pointer to ExactAlloc'ed buffer.
  184. //
  185. // LPEXACTHDR pExactHdr: Pointer to header.
  186. //
  187. // Return (BOOL):
  188. // TRUE if successful, FALSE otherwise.
  189. //
  190. // History:
  191. // 08/10/94 Fwong Facilitating reading headers. <Internal>
  192. //
  193. //--------------------------------------------------------------------------;
  194. BOOL GetExactHeaderInfo
  195. (
  196. LPVOID pStart,
  197. LPEXACTHDR pExactHdr
  198. )
  199. {
  200. pStart = ((LPBYTE)pStart) - sizeof(EXACTHDR);
  201. if(IsBadReadPtr(pStart,sizeof(EXACTHDR)))
  202. {
  203. return FALSE;
  204. }
  205. hmemcpy(pExactHdr,pStart,sizeof(EXACTHDR));
  206. return TRUE;
  207. } // GetExactHeaderInfo()
  208. //==========================================================================;
  209. //
  210. // Explanation: Okay, before I get flamed. This is the explanation of
  211. // how things work in the Win32 version of ExactAllocPtr(); it is
  212. // relatively non-trivial.
  213. //
  214. // Windows NT sets memory access on a per page basis. You can mark a page
  215. // of memory with certain access rights. The concept is to return a
  216. // pointer that will hit a PAGE_NOACCESS page on the boundary.
  217. // Like this...
  218. //
  219. // ----|-----------|-----------|-no-access-|-----------|-----------|-----
  220. // ^
  221. // +---- pointer n bytes from "no access" page
  222. //
  223. // Very simple. However, you shouldn't be marking a page as PAGE_NOACCESS
  224. // unless you own the entire page. (Windows NT doesn't hesitate
  225. // allocating memory within the same page with GlobalAlloc, and having
  226. // other things faulting).
  227. //
  228. // The only way to guarantee getting a full block is to allocate at a
  229. // buffer at least a full block larger in length. So we have
  230. // something that looks like this...
  231. //
  232. // |<----buffer-length---->|
  233. // ----|-----------|-----------|-no-access-|-----------|-----------|-----
  234. // ^ ^
  235. // +------+---- actual pointer from allocation
  236. // +---- offset pointer to return
  237. //
  238. // Note: Since the implementation changed to using VirtualAlloc (formerly
  239. // used GlobalAlloc), we are guaranteed all memory allocations to be
  240. // on page boundaries.
  241. //
  242. // In addition, we also need to keep track of some other things (so that
  243. // we can free the memory and return the access rights on the "no
  244. // access" page to "read/write access". Moreover, to confirm that
  245. // the memory allocation was actually done by us, we also put in a
  246. // "signature." These are all stored in a header, which is stored
  247. // right before the pointer to return. It should look like this...
  248. //
  249. // |<----buffer-length---->|
  250. // ----|-----------|-----------|-no-access-|-----------|-----------|-----
  251. // ^ ^ ^
  252. // +----+-+---- actual pointer from allocation
  253. // + +---- offset pointer to return
  254. // +------ location to store header information
  255. //
  256. // Note: Due to alignment problems (with the MIPS architecture) with
  257. // writing the header data directly into memory, we're doing an
  258. // hmemcpy to from a local header. It may look bad and/or
  259. // ugly. DON'T CHANGE IT! IT WORKS!
  260. //
  261. //==========================================================================;
  262. //--------------------------------------------------------------------------;
  263. //
  264. // LPVOID ExactAllocPtr
  265. //
  266. // Description:
  267. // Performs an exact memory allocation.
  268. //
  269. // Note: WIN32 Version counts on VirtualAlloc allocating memory in
  270. // page boundaries.
  271. //
  272. // Arguments:
  273. // UINT fuAlloc: Flags for GlobalAlloc. These are ignored for WIN32.
  274. //
  275. // DWORD cbAlloc: Size of Buffer.
  276. //
  277. // Return (LPVOID):
  278. // Pointer to allocated buffer.
  279. //
  280. // History:
  281. // 11/17/93 Fwong Created for exact allocation management.
  282. // 01/14/94 Fwong Adding Win32 Support.
  283. // 01/26/94 Fwong Revising to workaround NT problem.
  284. // 08/02/94 Fwong Changing to use VirtualAlloc.
  285. //
  286. //--------------------------------------------------------------------------;
  287. #ifdef WIN32
  288. LPVOID ExactAllocPtr
  289. (
  290. UINT fuAlloc,
  291. DWORD cbAlloc
  292. )
  293. {
  294. static DWORD dwPageSize = 0L;
  295. DWORD dw;
  296. DWORD cbActual;
  297. DWORD cbExtra;
  298. EXACTHDR ExactHdr;
  299. LPVOID pCurrent;
  300. if(0 == dwPageSize)
  301. {
  302. dwPageSize = GetPageSize();
  303. }
  304. //
  305. // Header info...
  306. //
  307. cbExtra = sizeof(EXACTHDR);
  308. //
  309. // dw = Number of Pages to allocate.
  310. // cbActual = Number of bytes.
  311. //
  312. dw = DIVRU(cbAlloc + cbExtra, dwPageSize) + 1;
  313. cbActual = dw * dwPageSize;
  314. //
  315. // Getting pointer...
  316. //
  317. ExactHdr.pStart = VirtualAlloc(
  318. NULL,
  319. cbActual,
  320. MEM_COMMIT|MEM_RESERVE,
  321. PAGE_READWRITE);
  322. if(NULL == ExactHdr.pStart)
  323. {
  324. //
  325. // Something failed here...
  326. //
  327. DBGOUT("VirtualAlloc failed.");
  328. return NULL;
  329. }
  330. //
  331. // pEvil = first byte in last page.
  332. //
  333. ExactHdr.pEvil = ((LPBYTE)ExactHdr.pStart) + cbActual - dwPageSize;
  334. //
  335. // pCurrent = cbAlloc number of bytes from "Evil" page.
  336. //
  337. pCurrent = ((LPBYTE)ExactHdr.pEvil) - cbAlloc;
  338. //
  339. // Making page "Evil"!
  340. //
  341. if(FALSE == VirtualProtect(ExactHdr.pEvil,1,PAGE_NOACCESS,&dw))
  342. {
  343. //
  344. // VirtualProtect failed. Failing ExactAllocPtr.
  345. //
  346. DBGOUT("VirtualProtect failed.");
  347. VirtualFree(ExactHdr.pStart,0,MEM_RELEASE);
  348. return NULL;
  349. }
  350. ExactHdr.fdwFlags = EXACTMEM_SIGNATURE;
  351. //
  352. // Storing header information.
  353. //
  354. SetExactHeaderInfo(pCurrent,&ExactHdr);
  355. gcAllocations++;
  356. return (LPVOID)(((LPBYTE)ExactHdr.pEvil) - cbAlloc);
  357. } // ExactAllocPtr()
  358. #else
  359. LPVOID ExactAllocPtr
  360. (
  361. UINT fuAlloc,
  362. DWORD cbAlloc
  363. )
  364. {
  365. HGLOBAL hMem;
  366. EXACTHDR ExactHdr;
  367. LPBYTE pbyte;
  368. hMem = GlobalAlloc(fuAlloc,cbAlloc + sizeof(EXACTHDR));
  369. //
  370. // Something failed here...
  371. //
  372. if(NULL == hMem)
  373. {
  374. DBGOUT("GlobalAlloc failed.");
  375. return NULL;
  376. }
  377. //
  378. // Offsetting the pointer by the amount of "extra" bytes.
  379. // extra bytes = actual (GlobalSize) - wanted (cbAlloc)
  380. //
  381. pbyte = (LPBYTE)GlobalLock(hMem);
  382. if(NULL == pbyte)
  383. {
  384. DBGOUT("GlobalLock failed.");
  385. GlobalFree(hMem);
  386. return NULL;
  387. }
  388. pbyte += (GlobalSize(hMem) - cbAlloc);
  389. ExactHdr.hMem = hMem;
  390. ExactHdr.fdwFlags = EXACTMEM_SIGNATURE;
  391. //
  392. // Storing Header information.
  393. //
  394. SetExactHeaderInfo(pbyte,&ExactHdr);
  395. gcAllocations++;
  396. return pbyte;
  397. } // ExactAllocPtr()
  398. #endif
  399. //--------------------------------------------------------------------------;
  400. //
  401. // BOOL ExactFreePtr
  402. //
  403. // Description:
  404. // Frees a previously allocated pointer.
  405. //
  406. // Arguments:
  407. // LPVOID pvoid: Pointer to buffer.
  408. //
  409. // Return (BOOL):
  410. // TRUE if successful, FALSE otherwise.
  411. //
  412. // History:
  413. // 11/17/93 Fwong Created for exact allocation management.
  414. // 01/26/94 Fwong Adding stuff to workaround NT problem.
  415. // 08/08/94 Fwong Changed to use VirtualFree.
  416. //
  417. //--------------------------------------------------------------------------;
  418. BOOL ExactFreePtr
  419. (
  420. LPVOID pvoid
  421. )
  422. {
  423. EXACTHDR ExactHdr;
  424. if(NULL == pvoid)
  425. {
  426. DBGOUT("Bad Pointer.");
  427. return FALSE;
  428. }
  429. //
  430. // Retrieving header info.
  431. //
  432. if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
  433. {
  434. DBGOUT("Bad Header.");
  435. return FALSE;
  436. }
  437. //
  438. // Is the signature correct?
  439. //
  440. if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
  441. {
  442. DBGOUT("Bad Signature.");
  443. return FALSE;
  444. }
  445. //
  446. // Was it allocated through "Handle" API's?
  447. //
  448. if(EXACTMEM_HANDLE & ExactHdr.fdwFlags)
  449. {
  450. DBGOUT("Using Heap memory for non heap API.");
  451. return FALSE;
  452. }
  453. #ifdef WIN32
  454. {
  455. DWORD dw;
  456. //
  457. // Setting access rights back to PAGE_READWRITE.
  458. //
  459. if(FALSE == VirtualProtect(ExactHdr.pEvil,1,PAGE_READWRITE,&dw))
  460. {
  461. //
  462. // What is wrong now?!
  463. //
  464. DBGOUT("VirtualProtect failed.");
  465. return FALSE;
  466. }
  467. //
  468. // Freeing memory.
  469. //
  470. if(FALSE == VirtualFree(ExactHdr.pStart,0,MEM_RELEASE))
  471. {
  472. //
  473. // VirtualFree failed?!
  474. //
  475. DBGOUT("VirtualFree failed.");
  476. return FALSE;
  477. }
  478. }
  479. #else
  480. GlobalUnlock(ExactHdr.hMem);
  481. if(NULL != GlobalFree(ExactHdr.hMem))
  482. {
  483. DBGOUT("GlobalFree failed.");
  484. return FALSE;
  485. }
  486. #endif
  487. gcAllocations--;
  488. return TRUE;
  489. } // ExactFreePtr()
  490. //--------------------------------------------------------------------------;
  491. //
  492. // DWORD GetNumAllocations
  493. //
  494. // Description:
  495. // Returns the number of allocations that have been performed through
  496. // memgr.
  497. //
  498. // Arguments:
  499. // None.
  500. //
  501. // Return (DWORD):
  502. // Count of number of allocations.
  503. //
  504. // History:
  505. // 06/06/94 Fwong To minimize memory leaks.
  506. //
  507. //--------------------------------------------------------------------------;
  508. DWORD GetNumAllocations
  509. (
  510. void
  511. )
  512. {
  513. return gcAllocations;
  514. } // GetNumAllocations()
  515. //--------------------------------------------------------------------------;
  516. //
  517. // HGLOBAL GetMemoryHandle
  518. //
  519. // Description:
  520. // Given a pointer (allocated by memgr) it returns the handle.
  521. //
  522. // Arguments:
  523. // LPVOID pvoid: Pointer to buffer.
  524. //
  525. // Return (HGLOBAL):
  526. // handle to memory.
  527. //
  528. // History:
  529. // 06/06/94 Fwong To make things more flexible.
  530. //
  531. //--------------------------------------------------------------------------;
  532. #ifdef WIN32
  533. HGLOBAL GetMemoryHandle
  534. (
  535. LPVOID pvoid
  536. )
  537. {
  538. //
  539. // The algorithm does not use memory handles for WIN32 anymore.
  540. //
  541. return NULL;
  542. } // GetMemoryHandle()
  543. #else
  544. HGLOBAL GetMemoryHandle
  545. (
  546. LPVOID pvoid
  547. )
  548. {
  549. EXACTHDR ExactHdr;
  550. if(NULL == pvoid)
  551. {
  552. DBGOUT("Bad Pointer.");
  553. return NULL;
  554. }
  555. //
  556. // Retrieving header info.
  557. //
  558. if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
  559. {
  560. DBGOUT("Bad Header.");
  561. return NULL;
  562. }
  563. //
  564. // Is the signature correct?
  565. //
  566. if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
  567. {
  568. DBGOUT("Bad Signature.");
  569. return NULL;
  570. }
  571. return (HGLOBAL)(ExactHdr.hMem);
  572. } // GetMemoryHandle()
  573. #endif
  574. //--------------------------------------------------------------------------;
  575. //
  576. // DWORD ExactSize
  577. //
  578. // Description:
  579. // Given an ExactAlloc'ed pointer, it returns the "exact" size of the
  580. // buffer.
  581. //
  582. // Arguments:
  583. // LPVOID pvoid: Originally ExactAlloc'ed pointer.
  584. //
  585. // Return (DWORD):
  586. // Size (in bytes) of buffer; Zero if an error occurs.
  587. //
  588. // History:
  589. // 08/08/94 Fwong Adding this for ReAlloc support.
  590. //
  591. //--------------------------------------------------------------------------;
  592. #ifdef WIN32
  593. DWORD ExactSize
  594. (
  595. LPVOID pvoid
  596. )
  597. {
  598. EXACTHDR ExactHdr;
  599. if(NULL == pvoid)
  600. {
  601. DBGOUT("Bad Pointer.");
  602. return 0L;
  603. }
  604. //
  605. // Retrieving header info.
  606. //
  607. if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
  608. {
  609. DBGOUT("Bad Header.");
  610. return 0L;
  611. }
  612. //
  613. // Is the signature correct?
  614. //
  615. if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
  616. {
  617. DBGOUT("Bad Signature.");
  618. return 0L;
  619. }
  620. return (DWORD)(((LPBYTE)ExactHdr.pEvil) - (LPBYTE)(pvoid));
  621. } // ExactSize()
  622. #else
  623. DWORD ExactSize
  624. (
  625. LPVOID pvoid
  626. )
  627. {
  628. EXACTHDR ExactHdr;
  629. DWORD dw;
  630. if(NULL == pvoid)
  631. {
  632. DBGOUT("Bad Pointer.");
  633. return 0L;
  634. }
  635. //
  636. // Retrieving header info.
  637. //
  638. if(FALSE == GetExactHeaderInfo(pvoid,&ExactHdr))
  639. {
  640. DBGOUT("Bad Header.");
  641. return 0L;
  642. }
  643. //
  644. // Is the signature correct?
  645. //
  646. if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
  647. {
  648. DBGOUT("Bad Signature.");
  649. return 0L;
  650. }
  651. dw = LOWORD(pvoid);
  652. return (DWORD)(GlobalSize(ExactHdr.hMem) - dw);
  653. } // ExactSize()
  654. #endif
  655. //--------------------------------------------------------------------------;
  656. //
  657. // LPVOID ExactReAlloc
  658. //
  659. // Description:
  660. // Re-allocates the buffer to be a different size of different
  661. // allocation flags.
  662. //
  663. // Note: Don't count on the pointer remaining the same; the pointer
  664. // _WILL_ change.
  665. //
  666. // Arguments:
  667. // LPVOID pOldPtr: Pointer to old buffer.
  668. //
  669. // DWORD cbAlloc: Number of bytes to re-allocate to.
  670. //
  671. // UINT fuAlloc: Allocation flags.
  672. //
  673. // Return (LPVOID):
  674. // Pointer to buffer, or NULL if unsuccessful.
  675. //
  676. // History:
  677. // 08/08/94 Fwong To make life a little easier.
  678. //
  679. //--------------------------------------------------------------------------;
  680. LPVOID ExactReAllocPtr
  681. (
  682. LPVOID pOldPtr,
  683. DWORD cbAlloc,
  684. UINT fuAlloc
  685. )
  686. {
  687. LPVOID pNewPtr;
  688. DWORD dw;
  689. EXACTHDR ExactHdr;
  690. //
  691. // Retrieving header info.
  692. //
  693. if(FALSE == GetExactHeaderInfo(pOldPtr,&ExactHdr))
  694. {
  695. DBGOUT("Bad Header.");
  696. return NULL;
  697. }
  698. //
  699. // Is the signature correct?
  700. //
  701. if(IS_BAD_HEADER_SIGNATURE(ExactHdr))
  702. {
  703. DBGOUT("Bad Signature.");
  704. return NULL;
  705. }
  706. //
  707. // Was it allocated through "Handle" API's?
  708. //
  709. if(EXACTMEM_HANDLE & ExactHdr.fdwFlags)
  710. {
  711. DBGOUT("Using heap memory for non heap API.");
  712. return NULL;
  713. }
  714. pNewPtr = ExactAllocPtr(fuAlloc,cbAlloc);
  715. if(NULL == pNewPtr)
  716. {
  717. DBGOUT("ExactAllocPtr failed.");
  718. return NULL;
  719. }
  720. //
  721. // Determining how many bytes to copy over...
  722. //
  723. dw = ExactSize(pOldPtr);
  724. dw = min(dw,cbAlloc);
  725. hmemcpy(pNewPtr,pOldPtr,dw);
  726. ExactFreePtr(pOldPtr);
  727. return pNewPtr;
  728. } // ExactReAllocPtr()
  729. //--------------------------------------------------------------------------;
  730. //
  731. // LPVOID GetPointer
  732. //
  733. // Description:
  734. // Given the index, gets the pointer from a buffer of pointers.
  735. //
  736. // Note: This was done very carefully due to the alignment problems
  737. // with MIPS machines. DON'T MESS WITH IT!
  738. //
  739. // Arguments:
  740. // LPVOID pvoid: Pointer to buffer.
  741. //
  742. // DWORD index: Index into buffer.
  743. //
  744. // Return (LPVOID):
  745. // The pointer at the appropriate index.
  746. //
  747. // History:
  748. // 08/11/94 Fwong For Heap Management. <Internal>
  749. //
  750. //--------------------------------------------------------------------------;
  751. LPVOID GetPointer
  752. (
  753. LPVOID pvoid,
  754. DWORD index
  755. )
  756. {
  757. LPVOID pReturn;
  758. index *= sizeof(LPVOID);
  759. pvoid = ((LPBYTE)pvoid) + index;
  760. hmemcpy((LPVOID)(&pReturn),pvoid,sizeof(LPVOID));
  761. return pReturn;
  762. } // GetPointer()
  763. //--------------------------------------------------------------------------;
  764. //
  765. // void SetPointer
  766. //
  767. // Description:
  768. // Given the index, sets a pointer within a buffer of pointers.
  769. //
  770. // Note: This was done very carefully due to the alignment problems
  771. // with MIPS machines. DON'T MESS WITH IT!
  772. //
  773. // Arguments:
  774. // LPVOID pvoid: Pointer to buffer.
  775. //
  776. // DWORD index: Index into buffer.
  777. //
  778. // LPVOID ptr: Pointer to store.
  779. //
  780. // Return (void):
  781. //
  782. // History:
  783. // 08/11/94 Fwong For Heap Management. <Internal>
  784. //
  785. //--------------------------------------------------------------------------;
  786. void SetPointer
  787. (
  788. LPVOID pvoid,
  789. DWORD index,
  790. LPVOID ptr
  791. )
  792. {
  793. index *= sizeof(LPVOID);
  794. pvoid = ((LPBYTE)pvoid) + index;
  795. hmemcpy(pvoid,(LPVOID)(&ptr),sizeof(LPVOID));
  796. } // SetPointer()
  797. //--------------------------------------------------------------------------;
  798. //
  799. // LPVOID ExactHeapAllocPtr
  800. //
  801. // Description:
  802. // ExactAlloc's a buffer through a heap handle.
  803. //
  804. // Arguments:
  805. // HANDLE hHeap: Handle to heap.
  806. //
  807. // UINT fuAlloc: Allocation flags for memory (See GlobalAlloc).
  808. //
  809. // DWORD cbAlloc: Size (in bytes) of buffer.
  810. //
  811. // Return (LPVOID):
  812. // Pointer to buffer, or NULL if an error occurs.
  813. //
  814. // History:
  815. // 08/11/94 Fwong Adding heap support.
  816. //
  817. //--------------------------------------------------------------------------;
  818. LPVOID ExactHeapAllocPtr
  819. (
  820. HANDLE hHeap,
  821. UINT fuAlloc,
  822. DWORD cbAlloc
  823. )
  824. {
  825. NPEXACTHEAP npExactHeap;
  826. EXACTHDR ExactHdr;
  827. LPVOID pNewMem;
  828. HGLOBAL hMem;
  829. DWORD dw;
  830. npExactHeap = (NPEXACTHEAP)hHeap;
  831. //
  832. // Checking if it is a bad pointer.
  833. //
  834. if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
  835. {
  836. DBGOUT("Bad hHeap.");
  837. return NULL;
  838. }
  839. //
  840. // Checking if it is a bad handle.
  841. //
  842. if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
  843. {
  844. DBGOUT("Bad hHeap.");
  845. return NULL;
  846. }
  847. //
  848. // If someone else has a hold of the heap, we wait.
  849. //
  850. WAIT_FOR_HEAP(npExactHeap);
  851. LOCK_HEAP(npExactHeap);
  852. //
  853. // Can we store the pointer?
  854. //
  855. if(npExactHeap->cNumAlloc == npExactHeap->cMaxAlloc)
  856. {
  857. //
  858. // Getting room for HEAPCHUNKSIZE number of more items
  859. //
  860. dw = (npExactHeap->cMaxAlloc + HEAPCHUNKSIZE) * sizeof(LPVOID);
  861. hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_SHARE,dw);
  862. if(NULL == hMem)
  863. {
  864. DBGOUT("GlobalAlloc failed.");
  865. UNLOCK_HEAP(npExactHeap);
  866. return NULL;
  867. }
  868. pNewMem = GlobalLock(hMem);
  869. if(NULL == pNewMem)
  870. {
  871. DBGOUT("GlobalLock failed.");
  872. GlobalFree(hMem);
  873. UNLOCK_HEAP(npExactHeap);
  874. return NULL;
  875. }
  876. //
  877. // Copying all old pointers.
  878. //
  879. dw = npExactHeap->cMaxAlloc * sizeof(LPVOID);
  880. hmemcpy(pNewMem,npExactHeap->pPointers,dw);
  881. //
  882. // Freeing old buffer.
  883. //
  884. GlobalUnlock(npExactHeap->hMem);
  885. GlobalFree(npExactHeap->hMem);
  886. //
  887. // Updating heap header.
  888. //
  889. npExactHeap->cMaxAlloc += HEAPCHUNKSIZE;
  890. npExactHeap->hMem = hMem;
  891. npExactHeap->pPointers = pNewMem;
  892. }
  893. pNewMem = ExactAllocPtr(fuAlloc,cbAlloc);
  894. if(NULL == pNewMem)
  895. {
  896. DBGOUT("ExactAllocPtr failed.");
  897. UNLOCK_HEAP(npExactHeap);
  898. return NULL;
  899. }
  900. //
  901. // Marking buffer as allocated by HEAP API's.
  902. //
  903. GetExactHeaderInfo(pNewMem,&ExactHdr);
  904. ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
  905. SetExactHeaderInfo(pNewMem,&ExactHdr);
  906. //
  907. // Updating Heap info.
  908. //
  909. SetPointer(npExactHeap->pPointers,npExactHeap->cNumAlloc,pNewMem);
  910. npExactHeap->cNumAlloc++;
  911. UNLOCK_HEAP(npExactHeap);
  912. return pNewMem;
  913. } // ExactHeapAllocPtr()
  914. //--------------------------------------------------------------------------;
  915. //
  916. // HANDLE ExactHeapCreate
  917. //
  918. // Description:
  919. // Creates a heap to do subsequent memory allocations.
  920. //
  921. // Arguments:
  922. // DWORD fdwFlags: Flags for function (none are defined yet).
  923. //
  924. // Return (HANDLE):
  925. // Handle to heap, or NULL if an error occured.
  926. //
  927. // History:
  928. // 08/11/94 Fwong Adding heap support.
  929. //
  930. //--------------------------------------------------------------------------;
  931. HANDLE ExactHeapCreate
  932. (
  933. DWORD fdwFlags
  934. )
  935. {
  936. NPEXACTHEAP npExactHeap;
  937. HGLOBAL hMem;
  938. npExactHeap = (NPEXACTHEAP)LocalAlloc(LPTR,sizeof(EXACTHEAP));
  939. if(NULL == npExactHeap)
  940. {
  941. DBGOUT("LocalAlloc failed.");
  942. return NULL;
  943. }
  944. hMem = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE,HEAPCHUNKSIZE*sizeof(LPVOID));
  945. if(NULL == hMem)
  946. {
  947. DBGOUT("GlobalAlloc failed.");
  948. LocalFree((HLOCAL)npExactHeap);
  949. return NULL;
  950. }
  951. npExactHeap->pPointers = GlobalLock(hMem);
  952. if(NULL == npExactHeap->pPointers)
  953. {
  954. DBGOUT("GlobalLock failed.");
  955. GlobalFree(hMem);
  956. LocalFree((HLOCAL)npExactHeap);
  957. return NULL;
  958. }
  959. npExactHeap->fdwFlags = EXACTMEM_SIGNATURE;
  960. npExactHeap->cNumAlloc = 0L;
  961. npExactHeap->cMaxAlloc = HEAPCHUNKSIZE;
  962. npExactHeap->hMem = hMem;
  963. return (HANDLE)(npExactHeap);
  964. } // ExactHeapCreate()
  965. //--------------------------------------------------------------------------;
  966. //
  967. // BOOL ExactHeapDestroy
  968. //
  969. // Description:
  970. // "Destroys" heap. Invalidates handle and frees all associated
  971. // memory allocations.
  972. //
  973. // Arguments:
  974. // HANDLE hHeap: Handle to heap.
  975. //
  976. // Return (BOOL):
  977. // TRUE if successful, FALSE otherwise.
  978. //
  979. // History:
  980. // 08/11/94 Fwong Adding heap support.
  981. //
  982. //--------------------------------------------------------------------------;
  983. BOOL ExactHeapDestroy
  984. (
  985. HANDLE hHeap
  986. )
  987. {
  988. NPEXACTHEAP npExactHeap;
  989. EXACTHDR ExactHdr;
  990. LPVOID pMem;
  991. DWORD dw;
  992. npExactHeap = (NPEXACTHEAP)hHeap;
  993. //
  994. // Checking if it is a bad pointer.
  995. //
  996. if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
  997. {
  998. DBGOUT("Bad hHeap.");
  999. return FALSE;
  1000. }
  1001. //
  1002. // Checking if it is a bad handle.
  1003. //
  1004. if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
  1005. {
  1006. DBGOUT("Bad hHeap.");
  1007. return FALSE;
  1008. }
  1009. //
  1010. // If someone else has a hold of the heap, we wait.
  1011. //
  1012. WAIT_FOR_HEAP(npExactHeap);
  1013. LOCK_HEAP(npExactHeap);
  1014. //
  1015. // Freeing all memory...
  1016. //
  1017. for(dw = npExactHeap->cNumAlloc;dw;dw--)
  1018. {
  1019. pMem = GetPointer(npExactHeap->pPointers,dw-1);
  1020. GetExactHeaderInfo(pMem,&ExactHdr);
  1021. ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
  1022. SetExactHeaderInfo(pMem,&ExactHdr);
  1023. if(FALSE == ExactFreePtr(pMem))
  1024. {
  1025. DBGOUT("ExactFreePtr failed.");
  1026. UNLOCK_HEAP(npExactHeap);
  1027. return FALSE;
  1028. }
  1029. }
  1030. //
  1031. // Invalidating handle... Just in case.
  1032. //
  1033. npExactHeap->fdwFlags = 0L;
  1034. //
  1035. // Freeing memory.
  1036. //
  1037. GlobalUnlock(npExactHeap->hMem);
  1038. GlobalFree(npExactHeap->hMem);
  1039. LocalFree((HLOCAL)(npExactHeap));
  1040. return TRUE;
  1041. } // ExactHeapDestroy()
  1042. //--------------------------------------------------------------------------;
  1043. //
  1044. // BOOL ExactHeapFreePtr
  1045. //
  1046. // Description:
  1047. // Frees memory allocated through ExactHeapAllocPtr.
  1048. //
  1049. // Arguments:
  1050. // HANDLE hHeap: Handle to heap.
  1051. //
  1052. // UINT fuFree: Flags for function (None are defined yet).
  1053. //
  1054. // LPVOID pMemFree: Buffer to free.
  1055. //
  1056. // Return (BOOL):
  1057. // TRUE if successful, FALSE otherwise.
  1058. //
  1059. // History:
  1060. // 08/11/94 Fwong Adding heap support.
  1061. //
  1062. //--------------------------------------------------------------------------;
  1063. BOOL ExactHeapFreePtr
  1064. (
  1065. HANDLE hHeap,
  1066. UINT fuFree,
  1067. LPVOID pMemFree
  1068. )
  1069. {
  1070. NPEXACTHEAP npExactHeap;
  1071. EXACTHDR ExactHdr;
  1072. LPVOID pMem;
  1073. DWORD dw;
  1074. npExactHeap = (NPEXACTHEAP)hHeap;
  1075. //
  1076. // Checking if it is a bad pointer.
  1077. //
  1078. if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
  1079. {
  1080. DBGOUT("Bad hHeap.");
  1081. return FALSE;
  1082. }
  1083. //
  1084. // Checking if it is a bad handle.
  1085. //
  1086. if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
  1087. {
  1088. DBGOUT("Bad hHeap.");
  1089. return FALSE;
  1090. }
  1091. //
  1092. // If someone else has a hold of the heap, we wait.
  1093. //
  1094. WAIT_FOR_HEAP(npExactHeap);
  1095. LOCK_HEAP(npExactHeap);
  1096. //
  1097. // Searching for pointer...
  1098. //
  1099. for(dw = npExactHeap->cNumAlloc;dw;dw--)
  1100. {
  1101. pMem = GetPointer(npExactHeap->pPointers,dw-1);
  1102. if(pMemFree == pMem)
  1103. {
  1104. //
  1105. // Marking buffer as not allocated by HEAP API's.
  1106. //
  1107. GetExactHeaderInfo(pMem,&ExactHdr);
  1108. ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
  1109. SetExactHeaderInfo(pMem,&ExactHdr);
  1110. //
  1111. // Freeing memory...
  1112. //
  1113. if(FALSE == ExactFreePtr(pMem))
  1114. {
  1115. DBGOUT("ExactFreePtr failed.");
  1116. ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
  1117. SetExactHeaderInfo(pMem,&ExactHdr);
  1118. UNLOCK_HEAP(npExactHeap);
  1119. return FALSE;
  1120. }
  1121. //
  1122. // Exchanging this pointer and last pointer...
  1123. //
  1124. npExactHeap->cNumAlloc--;
  1125. pMem = GetPointer(npExactHeap->pPointers,npExactHeap->cNumAlloc);
  1126. SetPointer(npExactHeap->pPointers,dw-1,pMem);
  1127. UNLOCK_HEAP(npExactHeap);
  1128. return TRUE;
  1129. }
  1130. }
  1131. //
  1132. // Pointer was not found?!
  1133. //
  1134. DBGOUT("Pointer not found.");
  1135. UNLOCK_HEAP(npExactHeap);
  1136. return FALSE;
  1137. } // ExactHeapFreePtr()
  1138. //--------------------------------------------------------------------------;
  1139. //
  1140. // LPVOID ExactHeapReAllocPtr
  1141. //
  1142. // Description:
  1143. // Reallocates a buffer to different size or allocation flags.
  1144. //
  1145. // Note: Don't count on the pointer remaining the same; the pointer
  1146. // _WILL_ change.
  1147. //
  1148. // Arguments:
  1149. // HANDLE hHeap: Handle to heap.
  1150. //
  1151. // LPVOID pOldPtr: Buffer to reallocate.
  1152. //
  1153. // DWORD cbAlloc: New size of buffer (in bytes).
  1154. //
  1155. // UINT fuAlloc: New allocation flags (See GlobalAlloc).
  1156. //
  1157. // Return (LPVOID):
  1158. // Pointer to new buffer, or NULL if error occurs.
  1159. //
  1160. // History:
  1161. // 08/11/94 Fwong Adding heap support.
  1162. //
  1163. //--------------------------------------------------------------------------;
  1164. LPVOID ExactHeapReAllocPtr
  1165. (
  1166. HANDLE hHeap,
  1167. LPVOID pOldPtr,
  1168. DWORD cbAlloc,
  1169. UINT fuAlloc
  1170. )
  1171. {
  1172. NPEXACTHEAP npExactHeap;
  1173. EXACTHDR ExactHdr;
  1174. LPVOID pMem;
  1175. DWORD dw;
  1176. npExactHeap = (NPEXACTHEAP)hHeap;
  1177. //
  1178. // Checking if it is a bad pointer.
  1179. //
  1180. if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
  1181. {
  1182. DBGOUT("Bad hHeap.");
  1183. return NULL;
  1184. }
  1185. //
  1186. // Checking if it is a bad handle.
  1187. //
  1188. if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
  1189. {
  1190. DBGOUT("Bad hHeap.");
  1191. return NULL;
  1192. }
  1193. //
  1194. // If someone else has a hold of the heap, we wait.
  1195. //
  1196. WAIT_FOR_HEAP(npExactHeap);
  1197. LOCK_HEAP(npExactHeap);
  1198. //
  1199. // Searching for pointer...
  1200. //
  1201. for(dw = npExactHeap->cNumAlloc;dw;dw--)
  1202. {
  1203. pMem = GetPointer(npExactHeap->pPointers,dw-1);
  1204. if(pOldPtr == pMem)
  1205. {
  1206. //
  1207. // Marking buffer as not allocated by HEAP API's.
  1208. //
  1209. GetExactHeaderInfo(pMem,&ExactHdr);
  1210. ExactHdr.fdwFlags &= (~EXACTMEM_HANDLE);
  1211. SetExactHeaderInfo(pMem,&ExactHdr);
  1212. //
  1213. // Doing ReAlloc...
  1214. //
  1215. pMem = ExactReAllocPtr(pOldPtr,cbAlloc,fuAlloc);
  1216. if(NULL == pMem)
  1217. {
  1218. DBGOUT("ExactReAllocPtr failed.");
  1219. UNLOCK_HEAP(npExactHeap);
  1220. return NULL;
  1221. }
  1222. //
  1223. // Marking buffer as allocated by HEAP API's.
  1224. //
  1225. GetExactHeaderInfo(pMem,&ExactHdr);
  1226. ExactHdr.fdwFlags |= EXACTMEM_HANDLE;
  1227. SetExactHeaderInfo(pMem,&ExactHdr);
  1228. //
  1229. // Updating pointer...
  1230. //
  1231. SetPointer(npExactHeap->pPointers,dw-1,pMem);
  1232. UNLOCK_HEAP(npExactHeap);
  1233. return pMem;
  1234. }
  1235. }
  1236. //
  1237. // Pointer not found?!
  1238. //
  1239. DBGOUT("Pointer not found.");
  1240. UNLOCK_HEAP(npExactHeap);
  1241. return NULL;
  1242. } // ExactHeapReAllocPtr()
  1243. //--------------------------------------------------------------------------;
  1244. //
  1245. // DWORD ExactHeapSize
  1246. //
  1247. // Description:
  1248. // Gets the size of the buffer the pointer refers to.
  1249. //
  1250. // Arguments:
  1251. // HANDLE hHeap: Handle to heap.
  1252. //
  1253. // UINT fuSize: Flags to function (None defined).
  1254. //
  1255. // LPVOID pMemSize: Pointer to buffer in question.
  1256. //
  1257. // Return (DWORD):
  1258. // Size (in bytes) of buffer, or Zero if error occurs
  1259. //
  1260. // History:
  1261. // 08/11/94 Fwong Adding heap support.
  1262. //
  1263. //--------------------------------------------------------------------------;
  1264. DWORD ExactHeapSize
  1265. (
  1266. HANDLE hHeap,
  1267. UINT fuSize,
  1268. LPVOID pMemSize
  1269. )
  1270. {
  1271. NPEXACTHEAP npExactHeap;
  1272. LPVOID pMem;
  1273. DWORD dw;
  1274. npExactHeap = (NPEXACTHEAP)hHeap;
  1275. //
  1276. // Checking if it is a bad pointer.
  1277. //
  1278. if(IsBadReadPtr(npExactHeap,sizeof(EXACTHEAP)))
  1279. {
  1280. DBGOUT("Bad hHeap.");
  1281. return 0L;
  1282. }
  1283. //
  1284. // Checking if it is a bad handle.
  1285. //
  1286. if(IS_BAD_HEAP_SIGNATURE(npExactHeap))
  1287. {
  1288. DBGOUT("Bad hHeap.");
  1289. return 0L;
  1290. }
  1291. //
  1292. // If someone else has a hold of the heap, we wait.
  1293. //
  1294. WAIT_FOR_HEAP(npExactHeap);
  1295. LOCK_HEAP(npExactHeap);
  1296. //
  1297. // Searching for pointer...
  1298. //
  1299. for(dw = npExactHeap->cNumAlloc;dw;dw--)
  1300. {
  1301. pMem = GetPointer(npExactHeap->pPointers,dw-1);
  1302. if(pMemSize == pMem)
  1303. {
  1304. UNLOCK_HEAP(npExactHeap);
  1305. return ExactSize(pMem);
  1306. }
  1307. }
  1308. //
  1309. // Pointer not found.
  1310. //
  1311. DBGOUT("Pointer not found.");
  1312. UNLOCK_HEAP(npExactHeap);
  1313. return 0L;
  1314. } // ExactHeapSize()