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.

585 lines
14 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // mem.c - memory functions
  24. ////
  25. #include "winlocal.h"
  26. #include <string.h>
  27. #include "mem.h"
  28. #include "sys.h"
  29. #include "trace.h"
  30. ////
  31. // private definitions
  32. ////
  33. #ifndef NOTRACE
  34. // mem control struct
  35. //
  36. typedef struct MEM
  37. {
  38. DWORD dwVersion;
  39. HINSTANCE hInst;
  40. HTASK hTask;
  41. long nBlocks;
  42. long sizBlocks;
  43. } MEM, FAR *LPMEM;
  44. // shared mem engine handle
  45. //
  46. static LPMEM lpMemShare = NULL;
  47. static int cShareUsage = 0;
  48. // helper functions
  49. //
  50. static LPMEM MemGetPtr(HMEM hMem);
  51. static HMEM MemGetHandle(LPMEM lpMem);
  52. ////
  53. // public functions
  54. ////
  55. // MemInit - initialize mem engine
  56. // <dwVersion> (i) must be MEM_VERSION
  57. // <hInst> (i) instance handle of calling module
  58. // return handle (NULL if error)
  59. //
  60. HMEM DLLEXPORT WINAPI MemInit(DWORD dwVersion, HINSTANCE hInst)
  61. {
  62. BOOL fSuccess = TRUE;
  63. LPMEM lpMem = NULL;
  64. BOOL fShare = TRUE;
  65. if (dwVersion != MEM_VERSION)
  66. fSuccess = FALSE;
  67. else if (hInst == NULL)
  68. fSuccess = FALSE;
  69. // if a shared mem engine already exists,
  70. // use it rather than create another one
  71. //
  72. else if (fShare && cShareUsage > 0 && lpMemShare != NULL)
  73. lpMem = lpMemShare;
  74. // memory is allocated such that the client app owns it
  75. // unless we are sharing the mem handle among several apps
  76. //
  77. #ifdef _WIN32
  78. else if ((lpMem = (LPMEM) HeapAlloc(GetProcessHeap(),
  79. HEAP_ZERO_MEMORY, sizeof(MEM))) == NULL)
  80. #else
  81. else if ((lpMem = (LPMEM) GlobalAllocPtr(GMEM_MOVEABLE |
  82. GMEM_ZEROINIT, sizeof(MEM))) == NULL)
  83. #endif
  84. fSuccess = FALSE;
  85. else
  86. {
  87. lpMem->dwVersion = dwVersion;
  88. lpMem->hInst = hInst;
  89. lpMem->hTask = GetCurrentTask();
  90. lpMem->nBlocks = 0;
  91. lpMem->sizBlocks = 0;
  92. }
  93. if (!fSuccess)
  94. {
  95. MemTerm(MemGetHandle(lpMem));
  96. lpMem = NULL;
  97. }
  98. // keep track of total modules sharing a mem engine handle
  99. //
  100. if (fSuccess && fShare)
  101. {
  102. if (++cShareUsage == 1)
  103. lpMemShare = lpMem;
  104. }
  105. return fSuccess ? MemGetHandle(lpMem) : NULL;
  106. }
  107. // MemTerm - shut down mem engine
  108. // <hMem> (i) handle returned from MemInit or NULL
  109. // return 0 if success
  110. //
  111. int DLLEXPORT WINAPI MemTerm(HMEM hMem)
  112. {
  113. BOOL fSuccess = TRUE;
  114. LPMEM lpMem;
  115. if ((lpMem = MemGetPtr(hMem)) == NULL)
  116. fSuccess = FALSE;
  117. // only shut down mem engine if handle
  118. // is not shared (or is no longer being shared)
  119. //
  120. else if (lpMem != lpMemShare || --cShareUsage <= 0)
  121. {
  122. // shared mem engine handle no longer valid
  123. //
  124. if (cShareUsage <= 0)
  125. lpMemShare = NULL;
  126. #ifdef _WIN32
  127. if (!HeapFree(GetProcessHeap(), 0, lpMem))
  128. #else
  129. if (GlobalFreePtr(lpMem) != 0)
  130. #endif
  131. fSuccess = FALSE;
  132. }
  133. return fSuccess ? 0 : -1;
  134. }
  135. // MemAlloc - allocate memory block
  136. // <hMem> (i) handle returned from MemInit or NULL
  137. // <sizBlock> (i) size of block, in bytes
  138. // <dwFlags> (i) control flags
  139. // MEM_NOZEROINIT do not initialize block
  140. // return pointer to block, NULL if error
  141. //
  142. LPVOID DLLEXPORT WINAPI MemAllocEx(HMEM hMem, long sizBlock, DWORD dwFlags,
  143. LPCTSTR lpszFileName, unsigned uLineNumber)
  144. {
  145. BOOL fSuccess = TRUE;
  146. LPMEM lpMem;
  147. LPVOID lpBlock;
  148. #ifdef _WIN32
  149. if ((lpMem = MemGetPtr(hMem)) == NULL)
  150. fSuccess = FALSE;
  151. else if ((lpBlock = HeapAlloc(GetProcessHeap(),
  152. (dwFlags & MEM_NOZEROINIT) ? 0 : HEAP_ZERO_MEMORY,
  153. sizBlock)) == NULL)
  154. fSuccess = FALSE;
  155. #else
  156. UINT wFlags = 0;
  157. wFlags |= GMEM_MOVEABLE;
  158. if (!(dwFlags & MEM_NOZEROINIT))
  159. wFlags |= GMEM_ZEROINIT;
  160. if ((lpMem = MemGetPtr(hMem)) == NULL)
  161. fSuccess = FALSE;
  162. else if ((lpBlock = GlobalAllocPtr(wFlags, sizBlock)) == NULL)
  163. fSuccess = FALSE;
  164. #endif
  165. // keep track of total blocks allocated, total size of all blocks
  166. //
  167. else if (++lpMem->nBlocks, lpMem->sizBlocks += sizBlock, FALSE)
  168. ;
  169. else if (TraceGetLevel(NULL) >= 9)
  170. {
  171. TracePrintf_7(NULL, 9, TEXT("%s(%u) : %08X = MemAllocEx(%p, %08X) (%ld, %ld)\n"),
  172. (LPTSTR) lpszFileName,
  173. (unsigned) uLineNumber,
  174. lpBlock,
  175. (long) sizBlock,
  176. (unsigned long) dwFlags,
  177. lpMem->nBlocks,
  178. lpMem->sizBlocks);
  179. }
  180. return fSuccess ? lpBlock : NULL;
  181. }
  182. // MemReAlloc - reallocate memory block
  183. // <hMem> (i) handle returned from MemInit or NULL
  184. // <lpBlock> (i) pointer returned from MemAlloc
  185. // <sizBlock> (i) new size of block, in bytes
  186. // <dwFlags> (i) control flags
  187. // MEM_NOZEROINIT do not initialize block
  188. // return pointer to block, NULL if error
  189. //
  190. LPVOID DLLEXPORT WINAPI MemReAllocEx(HMEM hMem, LPVOID lpBlock, long sizBlock,
  191. DWORD dwFlags, LPCTSTR lpszFileName, unsigned uLineNumber)
  192. {
  193. BOOL fSuccess = TRUE;
  194. LPMEM lpMem;
  195. LPVOID lpBlockOld = lpBlock;
  196. long sizBlockOld;
  197. #ifdef _WIN32
  198. if ((lpMem = MemGetPtr(hMem)) == NULL)
  199. fSuccess = FALSE;
  200. else if ((sizBlockOld = MemSize(hMem, lpBlock)) <= 0)
  201. fSuccess = FALSE;
  202. else if ((lpBlock = HeapReAlloc(GetProcessHeap(),
  203. (dwFlags & MEM_NOZEROINIT) ? 0 : HEAP_ZERO_MEMORY,
  204. lpBlockOld, sizBlock)) == NULL)
  205. fSuccess = FALSE;
  206. #else
  207. UINT wFlags = 0;
  208. wFlags |= GMEM_MOVEABLE;
  209. if (!(dwFlags & MEM_NOZEROINIT))
  210. wFlags |= GMEM_ZEROINIT;
  211. if ((lpMem = MemGetPtr(hMem)) == NULL)
  212. fSuccess = FALSE;
  213. else if ((sizBlockOld = MemSize(hMem, lpBlock)) <= 0)
  214. fSuccess = FALSE;
  215. else if ((lpBlock = GlobalReAllocPtr(lpBlockOld, sizBlock, wFlags)) == NULL)
  216. fSuccess = FALSE;
  217. #endif
  218. // keep track of total blocks allocated, total size of all blocks
  219. //
  220. else if (lpMem->sizBlocks -= sizBlockOld, lpMem->sizBlocks += sizBlock, FALSE)
  221. ;
  222. else if (TraceGetLevel(NULL) >= 9)
  223. {
  224. TracePrintf_8(NULL, 9, TEXT("%s(%u) : %p = MemReAllocEx(%p, %ld, %08X) (%ld, %ld)\n"),
  225. (LPTSTR) lpszFileName,
  226. (unsigned) uLineNumber,
  227. lpBlock,
  228. lpBlockOld,
  229. (long) sizBlock,
  230. (unsigned long) dwFlags,
  231. lpMem->nBlocks,
  232. lpMem->sizBlocks);
  233. }
  234. return fSuccess ? lpBlock : NULL;
  235. }
  236. // MemFree - free memory block
  237. // <hMem> (i) handle returned from MemInit or NULL
  238. // <lpBlock> (i) pointer returned from MemAlloc
  239. // return NULL if success, lpBlock if error
  240. //
  241. // NOTE: the return value of this function is designed to allow the
  242. // user of this function to easily assign NULL to a freed pointer,
  243. // as the following example demonstrates:
  244. //
  245. // if ((p = MemFree(hMem, p)) != NULL)
  246. // ; // error
  247. //
  248. LPVOID DLLEXPORT WINAPI MemFreeEx(HMEM hMem, LPVOID lpBlock,
  249. LPCTSTR lpszFileName, unsigned uLineNumber)
  250. {
  251. BOOL fSuccess = TRUE;
  252. LPMEM lpMem;
  253. long sizBlock;
  254. if ((lpMem = MemGetPtr(hMem)) == NULL)
  255. fSuccess = FALSE;
  256. else if ((sizBlock = MemSize(hMem, lpBlock)) <= 0)
  257. fSuccess = FALSE;
  258. #ifdef _WIN32
  259. else if (!HeapFree(GetProcessHeap(), 0, lpBlock))
  260. #else
  261. else if (GlobalFreePtr(lpBlock) != 0)
  262. #endif
  263. fSuccess = FALSE;
  264. // keep track of total blocks allocated, total size of all blocks
  265. //
  266. else if (--lpMem->nBlocks, lpMem->sizBlocks -= sizBlock, FALSE)
  267. ;
  268. else if (TraceGetLevel(NULL) >= 9)
  269. {
  270. TracePrintf_5(NULL, 9, TEXT("%s(%u) : MemFreeEx(%p) (%ld, %ld)\n"),
  271. (LPTSTR) lpszFileName,
  272. (unsigned) uLineNumber,
  273. lpBlock,
  274. lpMem->nBlocks,
  275. lpMem->sizBlocks);
  276. }
  277. return fSuccess ? NULL : lpBlock;
  278. }
  279. // MemSize - get size of memory block
  280. // <hMem> (i) handle returned from MemInit or NULL
  281. // <lpBlock> (i) pointer returned from MemAlloc
  282. // return size of block if success, 0 if error
  283. //
  284. long DLLEXPORT WINAPI MemSize(HMEM hMem, LPVOID lpBlock)
  285. {
  286. BOOL fSuccess = TRUE;
  287. LPMEM lpMem;
  288. long sizBlock;
  289. if ((lpMem = MemGetPtr(hMem)) == NULL)
  290. fSuccess = FALSE;
  291. #ifdef _WIN32
  292. else if ((sizBlock = (long) HeapSize(GetProcessHeap(), 0, lpBlock)) <= 0)
  293. #else
  294. else if ((sizBlock = (long) GlobalSize(GlobalPtrHandle(lpBlock))) <= 0)
  295. #endif
  296. fSuccess = FALSE;
  297. return fSuccess ? sizBlock : 0;
  298. }
  299. #endif // #ifndef NOTRACE
  300. #ifndef _WIN32
  301. static void hmemmove(void _huge *d, const void _huge *s, long len);
  302. #ifndef SIZE_T_MAX
  303. #define SIZE_T_MAX (~((size_t) 0))
  304. #endif
  305. void _huge* DLLEXPORT MemCCpyEx(void _huge* dest, const void _huge* src, int c, long count)
  306. {
  307. if (count <= SIZE_T_MAX)
  308. return _fmemccpy(dest, src, c, (size_t) count);
  309. else
  310. return NULL; //$FIXUP - need to handle large count
  311. }
  312. void _huge* DLLEXPORT MemChrEx(void _huge* buf, int c, long count)
  313. {
  314. if (count <= SIZE_T_MAX)
  315. return _fmemchr(buf, c, (size_t) count);
  316. else
  317. return NULL; //$FIXUP - need to handle large count
  318. }
  319. int DLLEXPORT MemCmpEx(const void _huge* buf1, void _huge* buf2, long count)
  320. {
  321. if (count <= SIZE_T_MAX)
  322. return _fmemcmp(buf1, buf2, (size_t) count);
  323. else
  324. return NULL; //$FIXUP - need to handle large count
  325. }
  326. void _huge* DLLEXPORT MemCpyEx(void _huge* dest, const void _huge* src, long count)
  327. {
  328. if (count <= SIZE_T_MAX)
  329. return _fmemcpy(dest, src, (size_t) count);
  330. else
  331. {
  332. hmemcpy(dest, src, count);
  333. return dest;
  334. }
  335. }
  336. int DLLEXPORT MemICmpEx(const void _huge* buf1, void _huge* buf2, long count)
  337. {
  338. if (count <= SIZE_T_MAX)
  339. return _fmemicmp(buf1, buf2, (size_t) count);
  340. else
  341. return NULL; //$FIXUP - need to handle large count
  342. }
  343. void _huge* DLLEXPORT MemMoveEx(void _huge* dest, const void _huge* src, long count)
  344. {
  345. if (count <= SIZE_T_MAX)
  346. return _fmemmove(dest, src, (size_t) count);
  347. else
  348. {
  349. hmemmove(dest, src, count);
  350. return dest;
  351. }
  352. }
  353. void _huge* DLLEXPORT MemSet(void _huge* dest, int c, long count)
  354. {
  355. if (count <= SIZE_T_MAX)
  356. return _fmemset(dest, c, (size_t) count);
  357. else
  358. {
  359. BYTE _huge* destTemp = dest;
  360. long countTemp = count;
  361. while (countTemp > 0)
  362. {
  363. size_t cb = (size_t) min(SIZE_T_MAX, countTemp);
  364. _fmemset(destTemp, c, cb);
  365. destTemp += cb;
  366. countTemp -= cb;
  367. }
  368. return dest;
  369. }
  370. }
  371. #endif // #ifndef _WIN32
  372. ////
  373. // helper functions
  374. ////
  375. #ifndef NOTRACE
  376. // MemGetPtr - verify that mem handle is valid,
  377. // <hMem> (i) handle returned from MemInit
  378. // return corresponding mem pointer (NULL if error)
  379. //
  380. static LPMEM MemGetPtr(HMEM hMem)
  381. {
  382. BOOL fSuccess = TRUE;
  383. LPMEM lpMem;
  384. // use shared mem handle if no other supplied
  385. //
  386. if (hMem == NULL && lpMemShare != NULL)
  387. lpMem = lpMemShare;
  388. // create shared mem handle if no other supplied
  389. //
  390. else if (hMem == NULL && lpMemShare == NULL &&
  391. (hMem = MemInit(MEM_VERSION, SysGetTaskInstance(NULL))) == NULL)
  392. fSuccess = FALSE;
  393. else if ((lpMem = (LPMEM) hMem) == NULL)
  394. fSuccess = FALSE;
  395. // note: check for good pointer made only if not using lpMemShare
  396. //
  397. else if (lpMem != lpMemShare &&
  398. IsBadWritePtr(lpMem, sizeof(MEM)))
  399. fSuccess = FALSE;
  400. #ifdef CHECKTASK
  401. // make sure current task owns the mem handle
  402. // except when shared mem handle is used
  403. //
  404. if (fSuccess && lpMem != lpMemShare &&
  405. lpMem->hTask != GetCurrentTask())
  406. fSuccess = FALSE;
  407. #endif
  408. return fSuccess ? lpMem : NULL;
  409. }
  410. // MemGetHandle - verify that mem pointer is valid,
  411. // <lpMem> (i) pointer to MEM struct
  412. // return corresponding mem handle (NULL if error)
  413. //
  414. static HMEM MemGetHandle(LPMEM lpMem)
  415. {
  416. BOOL fSuccess = TRUE;
  417. HMEM hMem;
  418. if ((hMem = (HMEM) lpMem) == NULL)
  419. fSuccess = FALSE;
  420. return fSuccess ? hMem : NULL;
  421. }
  422. #endif // #ifndef NOTRACE
  423. #ifndef _WIN32
  424. // from Microsoft Windows SDK KnowledgeBase PSS ID Number: Q117743
  425. //
  426. static void hmemmove(void _huge *d, const void _huge *s, long len)
  427. {
  428. register long i;
  429. long safesize, times;
  430. // There are four cases to consider
  431. // case 1: source and destination are the same
  432. // case 2: source and destination do not overlap
  433. // case 3: source starts at a location before destination in
  434. // linear memory
  435. // case 4: source starts at a location after destination in
  436. // linear memory
  437. // detect case 1 and handle it
  438. if (d == s)
  439. return;
  440. // determine the amount of overlap
  441. if (d > s) // get the absolute difference
  442. safesize = ((unsigned long)d - (unsigned long)s);
  443. else
  444. safesize = ((unsigned long)s - (unsigned long)d);
  445. // detect case 2
  446. if (safesize >= len)
  447. {
  448. hmemcpy(d, s, len); // no overlap
  449. return;
  450. }
  451. times = len/safesize;
  452. // detect case 3 and handle it
  453. if ((s < d) && ((unsigned long)s+len-1) >(unsigned long)d)
  454. {
  455. // copy bytes from the end of source to the end of
  456. // destination in safesize quantum.
  457. for (i = 1; i <= times; i++)
  458. hmemcpy((void _huge *)((unsigned long) d+len-i*safesize),
  459. (void _huge *)((unsigned long)s+len-i*safesize),
  460. safesize);
  461. // copy the bytes remaining to be copied after
  462. // times*safesize bytes have been copied.
  463. if (times*safesize < len)
  464. hmemcpy(d, s, len - times*safesize);
  465. }
  466. else // this is case 4. handle it
  467. {
  468. // ASSERT (s > d) && ((d+len-1) > s))
  469. // copy bytes from the beginning of source to the
  470. // beginning of destination in safesize quantum
  471. for (i = 0; i < times; i++)
  472. hmemcpy((void _huge *)((unsigned long)d+i*safesize),
  473. (void _huge *)((unsigned long)s+i*safesize),
  474. safesize);
  475. // copy the bytes remaining to be copied after
  476. // times*safesize bytes have been copied.
  477. if (times*safesize < len)
  478. hmemcpy((void _huge*)((unsigned long)d+times*safesize),
  479. (void _huge*)((unsigned long)s+times*safesize),
  480. len - times*safesize);
  481. }
  482. return;
  483. }
  484. #endif // #ifndef _WIN32