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.

903 lines
23 KiB

  1. /*
  2. - MEMORY.C
  3. -
  4. *
  5. * Contains the following functions exported from MAPIX.DLL:
  6. * MAPIAllocateBuffer
  7. * MAPIAllocateMore
  8. * MAPIFreeBuffer
  9. *
  10. * Contains the following functions handed to providers:
  11. * MAPIAllocateBufferProv
  12. * MAPIAllocateMoreProv
  13. *
  14. * Contains the following functions private to MAPIX.DLL:
  15. * MAPIAllocateBufferExt
  16. * MAPIAllocateMoreExt
  17. */
  18. #include "_apipch.h"
  19. #define _MEMORY_C
  20. // Critical section for serializing heap access
  21. #if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
  22. CRITICAL_SECTION csHeap;
  23. #endif
  24. #if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
  25. CRITICAL_SECTION csMapiInit;
  26. #endif
  27. #if (defined(WIN32) || defined(WIN16)) && !defined(MAC)
  28. CRITICAL_SECTION csMapiSearchPath;
  29. #endif
  30. #ifdef WIN32
  31. /* This is the entire 32-bit implementation for instance globals. */
  32. VOID FAR *pinstX = NULL;
  33. #endif
  34. #ifndef MAC
  35. // DefineInstList(lpInstUtil);
  36. #endif
  37. #ifdef MAC
  38. #include <utilmac.h>
  39. #define PvGetInstanceGlobals() PvGetInstanceGlobalsMac(kInstMAPIX)
  40. #define PvGetInstanceGlobalsEx(_x) PvGetInstanceGlobalsMac(kInstMAPIU)
  41. #endif
  42. // Buffer link overhead.
  43. // Blocks of memory obtained with MAPIAllocateMore are linked to a
  44. // block obtained with MAPIAllocateBuffer, so that the whole chain
  45. // may be freed with one call to MAPIFreeBuffer.
  46. typedef struct _BufInternal * LPBufInternal;
  47. typedef struct _BufInternal
  48. {
  49. #ifdef DEBUG
  50. ULONG ulPad;
  51. HLH hHeap;
  52. #endif
  53. ULONG ulAllocFlags;
  54. LPBufInternal pLink;
  55. } BufInternal;
  56. // Values for ulAllocFlags. This dword contains two kinds of
  57. // information:
  58. // = In the high-order word, flags telling whether or not
  59. // the block is the head of an allocation chain, and whether
  60. // the block contains additional debugging information.
  61. // = In the low-order word, an enum telling which heap
  62. // it was allocated from.
  63. #ifdef DEBUG
  64. #define ALLOC_DEBUG ((ULONG) 0x40000000)
  65. #else
  66. #define ALLOC_DEBUG ((ULONG) 0x00000000)
  67. #endif
  68. #define ALLOC_WITH_ALLOC (((ULONG) 0x10000000) | ALLOC_DEBUG)
  69. #define ALLOC_WITH_ALLOC_MORE (((ULONG) 0x20000000) | ALLOC_DEBUG)
  70. #define FLAGSMASK ((ULONG) 0xFFFF0000)
  71. #define GetFlags(_fl) ((ULONG) (_fl) & FLAGSMASK)
  72. #define heapidClient 1
  73. #define heapidProvider 2
  74. #define HEAPIDMASK 0xFFFF
  75. #define GetHeapid(_fl) (((int)(_fl)) & HEAPIDMASK)
  76. // Conversion macros
  77. #define INT_SIZE(a) ((a) + sizeof (BufInternal))
  78. #define LPBufExtFromLPBufInt( PBUFINT ) \
  79. ((LPVOID)(((LPBYTE) PBUFINT) + sizeof(BufInternal)))
  80. #define LPBufIntFromLPBufExt( PBUFEXT ) \
  81. ((LPBufInternal)(((LPBYTE) PBUFEXT) - sizeof(BufInternal)))
  82. #ifdef DEBUG
  83. // Internal stuff for checking memory buffer consistency.
  84. // The flag fAssertBadBlocks governs whether we generate an
  85. // assert or a debug trace when passed a bad block.
  86. // By default, we'll assert.
  87. // In the macros, _p is the address of a memory block;
  88. // _s is a string describing what's wrong with it
  89. static int fAssertBadBlocks = -1; // read from INI file
  90. #define TellBadBlock(_p, _s) \
  91. { if (fAssertBadBlocks == 1) \
  92. TrapSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), _p); \
  93. else \
  94. TraceSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), _p); }
  95. #define TellBadBlockInt(_p, _s) \
  96. { if (fAssertBadBlocks == 1) \
  97. TrapSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), LPBufExtFromLPBufInt(_p)); \
  98. else \
  99. TraceSz1( TEXT("MAPIAlloc: memory block %08lX ") _s TEXT("\n"), LPBufExtFromLPBufInt(_p)); }
  100. BOOL FValidAllocChain(LPBufInternal lpBuf);
  101. #else
  102. #define TellBadBlock(_p, _s)
  103. #define TellBadBlockInt(_p, _s)
  104. #endif
  105. /* Internal Prototypes */
  106. STDMETHODIMP_(SCODE)
  107. MAPIAllocateBufferExt(
  108. int heapid,
  109. ULONG ulSize,
  110. LPVOID * lppv);
  111. STDMETHODIMP_(SCODE)
  112. MAPIAllocateMoreExt(
  113. int heapid,
  114. ULONG ulSize,
  115. LPVOID lpv,
  116. LPVOID * lppv);
  117. SCODE ScGetHlh(int heapid, HLH FAR *phlh);
  118. #ifndef MAC
  119. #ifndef WIN32
  120. #pragma SEGMENT(MAPI_Core1)
  121. #endif
  122. #else
  123. #pragma code_seg("mapi", "fixed")
  124. #endif
  125. /*----------------------------------------------*/
  126. /* Beginning of Client Allocators */
  127. /*----------------------------------------------*/
  128. /*
  129. * MAPIAllocateBuffer
  130. *
  131. * Purpose:
  132. * Allocates a memory buffer on behalf of the client. Can be
  133. * freed with MAPIFreeBuffer().
  134. *
  135. * Arguments:
  136. * ulSize in Size, in bytes, of the buffer to be allocated.
  137. * lppv out Pointer to variable where the address of the
  138. * allocated memory will be returned.
  139. *
  140. * Assumes:
  141. * Should be called from a client and therefore will allocate
  142. * memory from the Client heap - pinst->hlhClient.
  143. *
  144. * Returns:
  145. * HRESULT: created from scodes described below.
  146. *
  147. * Side effects:
  148. * Increments allocation count in the INST.
  149. *
  150. * Errors:
  151. * MAPI_E_INSUFFICIENT_MEMORY Allocation failed.
  152. * MAPI_E_INVALID_PARAMETER Second argument is invalid.
  153. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535 on Win16).
  154. */
  155. STDMETHODIMP_(SCODE)
  156. MAPIAllocateBuffer(ULONG ulSize, LPVOID * lppv)
  157. {
  158. SCODE sc = S_OK;
  159. if (lpfnAllocateBufferExternal) {
  160. return(lpfnAllocateBufferExternal(ulSize, lppv));
  161. }
  162. #ifdef DEBUG
  163. // Initialize flag that controls how noisy we are about invalid
  164. // blocks passed to us.
  165. if (fAssertBadBlocks == -1)
  166. {
  167. fAssertBadBlocks = GetPrivateProfileInt( TEXT("General"), TEXT("AssertBadBlocks"),
  168. 1, TEXT("WABDBG.INI"));
  169. }
  170. #endif
  171. #ifdef PARAMETER_VALIDATION
  172. if (IsBadWritePtr((LPVOID) lppv, sizeof (LPVOID)))
  173. {
  174. DebugTraceArg(MAPIAllocateBuffer, TEXT("lppv fails address check"));
  175. return MAPI_E_INVALID_PARAMETER;
  176. }
  177. #endif
  178. sc = MAPIAllocateBufferExt(heapidClient, ulSize, lppv);
  179. DebugTraceSc(MAPIAllocateBuffer, sc);
  180. return sc;
  181. }
  182. /*
  183. * MAPIAllocateMore
  184. *
  185. * Purpose:
  186. * Allocates a linked memory buffer on behalf of the client,
  187. * in such a way that it can be freed with one call to MAPIFreeBuffer
  188. * (passing the buffer the client originally allocated with
  189. * MAPIAllocateBuffer).
  190. *
  191. * Arguments:
  192. * ulSize in Size, in bytes, of the buffer to be allocated.
  193. * lpv in Pointer to a buffer allocated with MAPIAllocateBuffer.
  194. * lppv out Pointer to variable where the address of the
  195. * allocated memory will be returned.
  196. *
  197. * Assumes:
  198. * Validates that lpBufOrig and lppv point to writable memory.
  199. * Validate that ulSize is less than 64K (on Win16 only) and that
  200. * lpBufOrig was allocated with MAPIAllocateBuffer.
  201. * Should be called from a client and therefore will allocate
  202. * memory from the Client heap - pinstUtil->hlhClient.
  203. *
  204. * Returns:
  205. * HRESULT: created from scodes described below.
  206. *
  207. * Side effects:
  208. * None
  209. *
  210. * Errors:
  211. * MAPI_E_INSUFFICIENT_MEMORY Allocation failed.
  212. * MAPI_E_INVALID_PARAMETER Second or third argument is invalid.
  213. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535).
  214. */
  215. STDMETHODIMP_(SCODE)
  216. MAPIAllocateMore(ULONG ulSize, LPVOID lpv, LPVOID * lppv)
  217. {
  218. SCODE sc = S_OK;
  219. if (lpfnAllocateMoreExternal) {
  220. return(lpfnAllocateMoreExternal(ulSize, lpv, lppv));
  221. }
  222. #ifdef PARAMETER_VALIDATION
  223. /*LPBufInternal lpBufOrig = LPBufIntFromLPBufExt(lpv);
  224. if (IsBadWritePtr(lpBufOrig, sizeof(BufInternal)))
  225. {
  226. TellBadBlock(lpv, "fails address check");
  227. return MAPI_E_INVALID_PARAMETER;
  228. }
  229. if (GetFlags(lpBufOrig->ulAllocFlags) != ALLOC_WITH_ALLOC)
  230. {
  231. TellBadBlock(lpv, "has invalid allocation flags");
  232. return MAPI_E_INVALID_PARAMETER;
  233. }
  234. */
  235. if (IsBadWritePtr(lppv, sizeof(LPVOID)))
  236. {
  237. DebugTraceArg(MAPIAllocateMore, TEXT("lppv fails address check"));
  238. return MAPI_E_INVALID_PARAMETER;
  239. }
  240. #endif /* PARAMETER_VALIDATION */
  241. sc = MAPIAllocateMoreExt(heapidClient, ulSize, lpv, lppv);
  242. DebugTraceSc(MAPIAllocateMore, sc);
  243. return sc;
  244. }
  245. /*
  246. * MAPIFreeBuffer
  247. *
  248. * Purpose:
  249. * Frees a memory block (or chain of blocks).
  250. * Frees any additional blocks linked with MAPIAllocateMore to
  251. * the buffer argument. Uses hHeap in the block header to
  252. * determine which heap to free into.
  253. *
  254. * Arguments:
  255. * lpv Pointer to a buffer allocated with MAPIAllocateBuffer.
  256. * lpv may be null, in which case we return immediately.
  257. *
  258. * Assumes:
  259. * This routine validates that lpv points to writable memory,
  260. * and was allocated with MAPIAllocateBuffer.
  261. *
  262. * Returns:
  263. * O if successful, lpv if unsuccessful.
  264. * If we are partially successful, i.e. the original block is
  265. * freed but the chain is corrupt further on, returns 0.
  266. *
  267. */
  268. #ifndef WIN16
  269. STDAPI_(ULONG)
  270. MAPIFreeBuffer(LPVOID lpv)
  271. #else
  272. ULONG FAR PASCAL
  273. MAPIFreeBuffer(LPVOID lpv)
  274. #endif
  275. {
  276. LPBufInternal lpBufInt;
  277. LPBufInternal lpT;
  278. HLH hlh;
  279. int heapid;
  280. if (!lpv)
  281. return(0L); // for callers who don't check for NULL themselves.
  282. if (lpfnFreeBufferExternal) {
  283. return(lpfnFreeBufferExternal(lpv));
  284. }
  285. lpBufInt = LPBufIntFromLPBufExt(lpv);
  286. #ifdef PARAMETER_VALIDATION
  287. // NOTE: these validations should be exactly the same as those
  288. // that cause FValidAllocChain to return FALSE.
  289. if (IsBadWritePtr(lpBufInt, sizeof(BufInternal)))
  290. {
  291. TellBadBlock(lpv, TEXT("fails address check"));
  292. return E_FAIL;
  293. }
  294. if (GetFlags(lpBufInt->ulAllocFlags) != ALLOC_WITH_ALLOC)
  295. {
  296. TellBadBlock(lpv, TEXT("has invalid allocation flags"));
  297. return E_FAIL;
  298. }
  299. #endif
  300. // No CS used, as the internal heap is serialized.
  301. // Only the AllocMore needs a CS, the Free does not; freeing
  302. // a block whilst someone else is allocing more against it is
  303. // asking for trouble!
  304. // Note also that neither MAPIAllocateBuffer nor MAPIAllocateMore
  305. // allow callers to use them when pinst->cRef == 0. MAPIFreeBuffer
  306. // allows itself to be called in that case because simple MAPI
  307. // needs to be able to free memory up until the DLL is unloaded.
  308. #ifdef DEBUG
  309. // This call checks flags and addresses for the whole chain.
  310. // This means that, in DEBUG, we'll leak all of a chain that's
  311. // corrupted after the first block. In SHIP, on the other hand,
  312. // we'll free everything up until the broken link.
  313. // But we do not return an error, for consistency.
  314. if (!FValidAllocChain(lpBufInt))
  315. goto ret;
  316. #endif
  317. // Free the first block, using its allocator
  318. lpT = lpBufInt->pLink;
  319. heapid = GetHeapid(lpBufInt->ulAllocFlags);
  320. if (ScGetHlh(heapid, &hlh))
  321. {
  322. DebugTrace( TEXT("MAPIFreeBuffer: playing in a heap that's gone\n"));
  323. return E_FAIL;
  324. }
  325. Assert(hlh == lpBufInt->hHeap);
  326. LH_Free(hlh, lpBufInt);
  327. lpBufInt = lpT;
  328. while (lpBufInt)
  329. {
  330. // NOTE: these validations should be exactly the same as those
  331. // that cause FValidAllocChain to return FALSE.
  332. if (IsBadWritePtr(lpBufInt, sizeof(BufInternal)) ||
  333. GetFlags(lpBufInt->ulAllocFlags) != ALLOC_WITH_ALLOC_MORE)
  334. goto ret;
  335. lpT = lpBufInt->pLink;
  336. // Usually, chained buffers live in the same heap. We can do
  337. // less work in this common case.
  338. if ((int) GetHeapid(lpBufInt->ulAllocFlags) == heapid)
  339. LH_Free(hlh, lpBufInt);
  340. else
  341. {
  342. HLH hlhMore;
  343. if (!ScGetHlh(GetHeapid(lpBufInt->ulAllocFlags), &hlhMore))
  344. LH_Free(hlhMore, lpBufInt);
  345. else
  346. {
  347. DebugTrace(TEXT("MAPIFreeBuffer: playing in a chained heap that's gone\n"));
  348. }
  349. }
  350. lpBufInt = lpT;
  351. }
  352. ret:
  353. return 0;
  354. }
  355. #ifdef OLD_STUFF
  356. /*----------------------------------------------*/
  357. /* Beginning of Provider Allocators */
  358. /*----------------------------------------------*/
  359. /*
  360. * MAPIAllocateBufferProv
  361. *
  362. * Purpose:
  363. * Same as MAPIAllocateBuffer except uses the Service
  364. * Providers heap - pinst->hlhProvider.
  365. */
  366. STDMETHODIMP_(SCODE)
  367. MAPIAllocateBufferProv(ULONG ulSize, LPVOID * lppv)
  368. {
  369. SCODE sc = S_OK;
  370. #ifdef DEBUG
  371. // Initialize flag that controls how noisy we are about invalid
  372. // blocks passed to us.
  373. if (fAssertBadBlocks == -1)
  374. {
  375. fAssertBadBlocks = GetPrivateProfileInt("General", "AssertBadBlocks",
  376. 1, "WABDBG.INI");
  377. }
  378. #endif
  379. #ifdef PARAMETER_VALIDATION
  380. if (IsBadWritePtr((LPVOID) lppv, sizeof (LPVOID)))
  381. {
  382. DebugTraceArg(MAPIAllocateBuffer, TEXT("lppv fails address check"));
  383. return MAPI_E_INVALID_PARAMETER;
  384. }
  385. #endif
  386. sc = MAPIAllocateBufferExt(heapidProvider, ulSize, lppv);
  387. DebugTraceSc(MAPIAllocateBufferProv, sc);
  388. return sc;
  389. }
  390. /*
  391. * MAPIAllocateMoreProv
  392. *
  393. * Purpose:
  394. * Same as MAPIAllocateMore except uses the Service
  395. * Providers heap - pinst->hlhProvider.
  396. */
  397. STDMETHODIMP_(SCODE)
  398. MAPIAllocateMoreProv(ULONG ulSize, LPVOID lpv, LPVOID * lppv)
  399. {
  400. SCODE sc = S_OK;
  401. #ifdef PARAMETER_VALIDATION
  402. LPBufInternal lpBufOrig = LPBufIntFromLPBufExt(lpv);
  403. if (IsBadWritePtr(lpBufOrig, sizeof(BufInternal)))
  404. {
  405. TellBadBlock(lpv, "fails address check");
  406. return MAPI_E_INVALID_PARAMETER;
  407. }
  408. if (GetFlags(lpBufOrig->ulAllocFlags) != ALLOC_WITH_ALLOC)
  409. {
  410. TellBadBlock(lpv, "has invalid allocation flags");
  411. return MAPI_E_INVALID_PARAMETER;
  412. }
  413. if (IsBadWritePtr(lppv, sizeof(LPVOID)))
  414. {
  415. DebugTraceArg(MAPIAllocateMore, TEXT("lppv fails address check"));
  416. return MAPI_E_INVALID_PARAMETER;
  417. }
  418. #endif /* PARAMETER_VALIDATION */
  419. sc = MAPIAllocateMoreExt(heapidProvider, ulSize, lpv, lppv);
  420. DebugTraceSc(MAPIAllocateMoreProv, sc);
  421. return sc;
  422. }
  423. #endif
  424. /*----------------------------------------------*/
  425. /* Beginning of Extended Allocators */
  426. /*----------------------------------------------*/
  427. /*
  428. * MAPIAllocateBufferExt
  429. *
  430. * Purpose:
  431. * Allocates a memory buffer on the specified heap. Can be
  432. * freed with MAPIFreeBuffer().
  433. *
  434. * Arguments:
  435. * heapid in identifies the heap we wish to allocate in
  436. * pinst in Pointer to our instance data
  437. * ulSize in Size, in bytes, of the buffer to be allocated.
  438. * lppv out Pointer to variable where the address of the
  439. * allocated memory will be returned.
  440. *
  441. * Returns:
  442. * sc Indicating error if any (see below)
  443. *
  444. * Side effects:
  445. * Increments allocation count in the INST.
  446. *
  447. * Errors:
  448. * MAPI_E_INSUFFICIENT_MEMORY Allocation failed.
  449. * MAPI_E_INVALID_PARAMETER Second argument is invalid.
  450. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535 on Win16).
  451. */
  452. STDMETHODIMP_(SCODE)
  453. MAPIAllocateBufferExt(int heapid, ULONG ulSize, LPVOID * lppv)
  454. {
  455. SCODE sc = S_OK;
  456. LPBufInternal lpBufInt;
  457. HLH hlh;
  458. // Don't allow allocation to wrap across 32 bits, or to exceed 64K
  459. // under win16.
  460. if ( ulSize > INT_SIZE (ulSize)
  461. #ifdef WIN16
  462. || (INT_SIZE(ulSize) >= 0x10000)
  463. #endif
  464. )
  465. {
  466. DebugTrace(TEXT("MAPIAllocateBuffer: ulSize %ld is way too big\n"), ulSize);
  467. sc = MAPI_E_NOT_ENOUGH_MEMORY;
  468. goto ret;
  469. }
  470. if (sc = ScGetHlh(heapid, &hlh))
  471. goto ret;
  472. lpBufInt = (LPBufInternal)LH_Alloc(hlh, (UINT) INT_SIZE(ulSize));
  473. if (lpBufInt)
  474. {
  475. #ifdef DEBUG
  476. lpBufInt->hHeap = hlh;
  477. #endif
  478. lpBufInt->pLink = NULL;
  479. lpBufInt->ulAllocFlags = ALLOC_WITH_ALLOC | heapid;
  480. *lppv = (LPVOID) LPBufExtFromLPBufInt(lpBufInt);
  481. }
  482. else
  483. {
  484. DebugTrace(TEXT("MAPIAllocateBuffer: not enough memory for %ld\n"), ulSize);
  485. sc = MAPI_E_NOT_ENOUGH_MEMORY;
  486. }
  487. ret:
  488. return sc;
  489. }
  490. /*
  491. * MAPIAllocateMoreExt
  492. *
  493. * Purpose:
  494. * Allocates a linked memory buffer on the specified heap, in such
  495. * a way that it can be freed with one call to MAPIFreeBuffer
  496. * (passing the buffer the client originally allocated with
  497. * MAPIAllocateBuffer).
  498. *
  499. * Arguments:
  500. * heapid in Identifies the heap we wish to allocate in
  501. * ulSize in Size, in bytes, of the buffer to be allocated.
  502. * lpv in Pointer to a buffer allocated with MAPIAllocateBuffer.
  503. * lppv out Pointer to variable where the address of the
  504. * allocated memory will be returned.
  505. *
  506. * Assumes:
  507. * Validates that lpBufOrig and lppv point to writable memory.
  508. * Validate that ulSize is less than 64K (on Win16 only) and that
  509. * lpBufOrig was allocated with MAPIAllocateBuffer.
  510. *
  511. * Returns:
  512. * sc Indicating error if any (see below)
  513. *
  514. * Side effects:
  515. * None
  516. *
  517. * Errors:
  518. * MAPI_E_INSUFFICIENT_MEMORY Allocation failed.
  519. * MAPI_E_INVALID_PARAMETER Second or third argument is invalid.
  520. * MAPI_E_INVALID_PARAMETER ulSize is out of range (>= 65535).
  521. */
  522. STDMETHODIMP_(SCODE)
  523. MAPIAllocateMoreExt(int heapid, ULONG ulSize, LPVOID lpv, LPVOID * lppv)
  524. {
  525. SCODE sc = S_OK;
  526. LPBufInternal lpBufInt;
  527. LPBufInternal lpBufOrig;
  528. HLH hlh;
  529. lpBufOrig = LPBufIntFromLPBufExt(lpv);
  530. // Don't allow allocation to wrap across 32 bits, or to be
  531. // greater than 64K under win16.
  532. if ( ulSize > INT_SIZE (ulSize)
  533. #ifdef WIN16
  534. || (INT_SIZE(ulSize) >= 0x10000)
  535. #endif
  536. )
  537. {
  538. DebugTrace(TEXT("MAPIAllocateMore: ulSize %ld is way too big\n"), ulSize);
  539. sc = MAPI_E_NOT_ENOUGH_MEMORY;
  540. goto ret;
  541. }
  542. #ifdef DEBUG
  543. //$ BUG Difference in behavior between DEBUG and SHIP:
  544. // this validation will cause the call to fail in DEBUG if the
  545. // tail of a chain is corrupted, while the SHIP version will
  546. // add the new block at the (valid) head without checking.
  547. if (!FValidAllocChain(lpBufOrig))
  548. {
  549. sc = MAPI_E_INVALID_PARAMETER;
  550. goto ret;
  551. }
  552. #endif
  553. if (sc = ScGetHlh(heapid, &hlh))
  554. goto ret;
  555. // Allocate the chained block and hook it to the head of the chain.
  556. // In DEBUG, a separately wrapped allocator is used so that
  557. // we report the number of chains leaked, not the number of blocks.
  558. // In SHIP, they're the same allocator.
  559. lpBufInt = (LPBufInternal)LH_Alloc(hlh, (UINT) INT_SIZE (ulSize));
  560. if (lpBufInt)
  561. {
  562. #ifdef DEBUG
  563. { HLH hlhOrig;
  564. if (!ScGetHlh(GetHeapid(lpBufOrig->ulAllocFlags), &hlhOrig))
  565. LH_SetName1(hlh, lpBufInt, TEXT("+ %s"), LH_GetName(hlhOrig, lpBufOrig));
  566. }
  567. #endif
  568. // Serialize the smallest possible code section
  569. #ifdef DEBUG
  570. lpBufInt->hHeap = hlh;
  571. #endif
  572. lpBufInt->ulAllocFlags = ALLOC_WITH_ALLOC_MORE | heapid;
  573. EnterCriticalSection(&csHeap);
  574. lpBufInt->pLink = lpBufOrig->pLink;
  575. lpBufOrig->pLink = lpBufInt;
  576. LeaveCriticalSection(&csHeap);
  577. *lppv = (LPVOID) LPBufExtFromLPBufInt(lpBufInt);
  578. }
  579. else
  580. {
  581. DebugTrace(TEXT("MAPIAllocateMore: not enough memory for %ld\n"), ulSize);
  582. sc = MAPI_E_NOT_ENOUGH_MEMORY;
  583. }
  584. ret:
  585. return sc;
  586. }
  587. #ifdef OLD_STUFF
  588. /*
  589. * MAPIReallocateBuffer
  590. *
  591. * Purpose:
  592. * Allocates a memory buffer on the heap of the original allocation.
  593. * Can be freed with MAPIFreeBuffer().
  594. *
  595. * Arguments:
  596. * lpv in original pointer
  597. * ulSize in new size, in bytes, of the buffer to be allocated.
  598. * lppv out pointer to variable where the address of the
  599. * allocated memory will be returned.
  600. *
  601. * Returns:
  602. * sc Indicating error if any (see below)
  603. *
  604. * Errors:
  605. * MAPI_E_NOT_ENOUGH_MEMORY Allocation failed.
  606. */
  607. STDMETHODIMP_(SCODE)
  608. MAPIReallocateBuffer(LPVOID lpv, ULONG ulSize, LPVOID * lppv)
  609. {
  610. LPBufInternal lpBufInt;
  611. LPBufInternal lpBufIntNew;
  612. HLH hlh;
  613. // Do a real allocation if NULL is passed in as the base
  614. //
  615. if (!lpv)
  616. return MAPIAllocateBuffer (ulSize, lppv);
  617. // Don't allow allocation to wrap across 32 bits, or to exceed 64K
  618. // under win16.
  619. //
  620. if (ulSize > INT_SIZE (ulSize)
  621. #ifdef WIN16
  622. || (INT_SIZE(ulSize) >= 0x10000)
  623. #endif
  624. )
  625. {
  626. DebugTrace(TEXT("MAPIReallocateBuffer: ulSize %ld is way too big\n"), ulSize);
  627. return MAPI_E_NOT_ENOUGH_MEMORY;
  628. }
  629. lpBufInt = LPBufIntFromLPBufExt (lpv);
  630. if (ScGetHlh(GetHeapid(lpBufInt->ulAllocFlags), &hlh))
  631. {
  632. DebugTrace(TEXT("MAPIReallocateBuffer: playing in a heap that's gone\n"));
  633. return MAPI_E_NOT_INITIALIZED;
  634. }
  635. Assert(hlh == lpBufInt->hHeap);
  636. if ((lpBufInt->ulAllocFlags & ALLOC_WITH_ALLOC) != ALLOC_WITH_ALLOC)
  637. return MAPI_E_INVALID_PARAMETER;
  638. lpBufIntNew = (LPBufInternal)LH_Realloc (hlh, lpBufInt, (UINT) INT_SIZE(ulSize));
  639. if (lpBufIntNew)
  640. {
  641. Assert (lpBufIntNew->hHeap == hlh);
  642. *lppv = (LPVOID) LPBufExtFromLPBufInt (lpBufIntNew);
  643. }
  644. else
  645. {
  646. DebugTrace ( TEXT("MAPIReallocateBuffer: not enough memory for %ld\n"), ulSize);
  647. return MAPI_E_NOT_ENOUGH_MEMORY;
  648. }
  649. return S_OK;
  650. }
  651. #endif // OLD_STUFF
  652. #ifdef _WIN64
  653. void WabValidateClientheap()
  654. {
  655. LPINSTUTIL pinstUtil;
  656. pinstUtil = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil);
  657. Assert(pinstUtil);
  658. Assert(HeapValidate(pinstUtil->hlhClient->_hlhBlks, 0, NULL));
  659. Assert(HeapValidate(pinstUtil->hlhClient->_hlhData, 0, NULL));
  660. }
  661. #endif
  662. /*
  663. - ScGetHlh
  664. -
  665. * Purpose:
  666. * Finds the heap handle for a given heap ID.
  667. *
  668. * Arguments:
  669. * heapid in identifies the heap
  670. * Currently supports two: heapidClient and
  671. * heapidProvider.
  672. * hlh out the desired handle
  673. *
  674. * Returns:
  675. * SCODE
  676. *
  677. * Errors:
  678. * MAPI_E_NOT_INITIALIZED if the instance data that's supposed to
  679. * know about the heap is unavailable.
  680. */
  681. SCODE
  682. ScGetHlh(int heapid, HLH FAR *phlh)
  683. {
  684. LPINSTUTIL pinstUtil;
  685. LPINST pinst;
  686. switch (heapid)
  687. {
  688. case heapidClient:
  689. pinstUtil = (LPINSTUTIL) PvGetInstanceGlobalsEx(lpInstUtil);
  690. if (pinstUtil)
  691. {
  692. Assert(pinstUtil->hlhClient);
  693. #ifdef _WIN64 // additional check for Win64 (YST)
  694. Assert(HeapValidate(pinstUtil->hlhClient->_hlhBlks, 0, NULL));
  695. Assert(HeapValidate(pinstUtil->hlhClient->_hlhData, 0, NULL));
  696. #endif
  697. *phlh = pinstUtil->hlhClient;
  698. return S_OK;
  699. }
  700. else
  701. {
  702. DebugTrace(TEXT("ScGetHlh: INSTUTIL not available\n"));
  703. return MAPI_E_NOT_INITIALIZED;
  704. }
  705. break;
  706. case heapidProvider:
  707. // Note: do not acquire the INST critical section.
  708. // That frequently leads to deadlocks. We use our own
  709. // critical section specifically to protect the heaps.
  710. pinst = (LPINST) PvGetInstanceGlobals();
  711. if (pinst && pinst->cRef)
  712. {
  713. Assert(pinst->hlhProvider);
  714. #ifdef _WIN64 // additional check for Win64 (YST)
  715. Assert(HeapValidate(pinst->hlhProvider->_hlhBlks, 0, NULL));
  716. #endif
  717. *phlh = pinst->hlhProvider;
  718. return S_OK;
  719. }
  720. else
  721. {
  722. DebugTrace(TEXT("ScGetHlh: INST not available\n"));
  723. return MAPI_E_NOT_INITIALIZED;
  724. }
  725. break;
  726. }
  727. TrapSz1( TEXT("HlhOfHeapid: unknown heap ID %d"), heapid);
  728. return MAPI_E_CALL_FAILED;
  729. }
  730. #ifdef DEBUG
  731. /*
  732. * This function validates a block of memory, and any blocks
  733. * linked to it.
  734. *
  735. * NOTE: This is DEBUG-only code. To prevent differences in behavior
  736. * between debug and retail builds, any conditions that are not
  737. * checked in the retail code should only be asserted here -- they
  738. * should not cause a FALSE return. Currently the retail code does
  739. * not validate with DidAlloc(); it simply checks for accessibility
  740. * of the memory and the correct flag values.
  741. *
  742. * Whether this function generates asserts or debug trace output
  743. * is governed by a flag read from WABDBG.INI.
  744. */
  745. BOOL
  746. FValidAllocChain(LPBufInternal lpBuf)
  747. {
  748. LPBufInternal lpBufTemp;
  749. if (IsBadWritePtr(lpBuf, sizeof(BufInternal)))
  750. {
  751. TellBadBlockInt(lpBuf, TEXT("fails address check"));
  752. return FALSE;
  753. }
  754. if (GetFlags(lpBuf->ulAllocFlags) != ALLOC_WITH_ALLOC)
  755. {
  756. TellBadBlockInt(lpBuf, TEXT("has invalid flags"));
  757. return FALSE;
  758. }
  759. for (lpBufTemp = lpBuf->pLink; lpBufTemp; lpBufTemp = lpBufTemp->pLink)
  760. {
  761. if (IsBadWritePtr(lpBufTemp, sizeof(BufInternal)))
  762. {
  763. TellBadBlockInt(lpBufTemp, TEXT("(linked block) fails address check"));
  764. return FALSE;
  765. }
  766. if (GetFlags(lpBufTemp->ulAllocFlags) != ALLOC_WITH_ALLOC_MORE)
  767. {
  768. TellBadBlockInt(lpBufTemp, TEXT("(linked block) has invalid flags"));
  769. return FALSE;
  770. }
  771. }
  772. return TRUE;
  773. }
  774. #endif // DEBUG