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.

816 lines
21 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // global.cpp
  5. //
  6. // Contents:
  7. // Ut functions that deal with HGlobals for debugging;
  8. // see le2int.h
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. // UtGlobalAlloc
  14. // UtGlobalReAlloc
  15. // UtGlobalLock
  16. // UtGlobalUnlock
  17. // UtGlobalFree
  18. // UtGlobalFlush
  19. // UtSetClipboardData
  20. //
  21. // History:
  22. // 12/20/93 - ChrisWe - created
  23. // 01/11/94 - alexgo - added VDATEHEAP macros to every function
  24. // 02/25/94 AlexT Add some generic integrity checking
  25. // 03/30/94 AlexT Add UtSetClipboardData
  26. //
  27. // Notes:
  28. //
  29. // These routines are designed to catch bugs that corrupt GlobalAlloc memory.
  30. // We cannot guarantee that all global memory will be manipulated with these
  31. // routines (e.g. OLE might allocate a handle and the client application
  32. // might free it), so we can't require that these routines be used in pairs.
  33. //
  34. //-----------------------------------------------------------------------------
  35. #include <le2int.h>
  36. #if DBG==1 && defined(WIN32)
  37. #include <olesem.hxx>
  38. ASSERTDATA
  39. // undefine these, so we don't call ourselves recursively
  40. // if this module is used, these are defined in le2int.h to replace
  41. // the existing allocator with the functions here
  42. #undef GlobalAlloc
  43. #undef GlobalReAlloc
  44. #undef GlobalLock
  45. #undef GlobalUnlock
  46. #undef GlobalFree
  47. #undef SetClipboardData
  48. // Same ones as in memapi.cxx
  49. #define OLEMEM_ALLOCBYTE 0xde
  50. #define OLEMEM_FREEBYTE 0xed
  51. typedef struct s_GlobalAllocInfo
  52. {
  53. HGLOBAL hGlobal; // A GlobalAlloc'd HGLOBAL
  54. SIZE_T cbGlobalSize; // GlobalSize(hGlobal)
  55. SIZE_T cbUser; // size requested by caller
  56. ULONG ulIndex; // allocation index (1st, 2nd...)
  57. struct s_GlobalAllocInfo *pNext;
  58. } SGLOBALALLOCINFO, *PSGLOBALALLOCINFO;
  59. //+-------------------------------------------------------------------------
  60. //
  61. // Class: CGlobalTrack
  62. //
  63. // Purpose: GlobalAlloc memory tracking
  64. //
  65. // History: 25-Feb-94 AlexT Created
  66. //
  67. // Notes:
  68. //
  69. //--------------------------------------------------------------------------
  70. class CGlobalTrack
  71. {
  72. public:
  73. //
  74. // We only have a constructor for debug builds, to ensure this object
  75. // is statically allocated. Statically allocated objects are initialized
  76. // to all zeroes, which is what we need.
  77. //
  78. CGlobalTrack();
  79. HGLOBAL cgtGlobalAlloc(UINT uiFlag, SIZE_T cbUser);
  80. HGLOBAL cgtGlobalReAlloc(HGLOBAL hGlobal, SIZE_T cbUser, UINT uiFlag);
  81. HGLOBAL cgtGlobalFree(HGLOBAL hGlobal);
  82. LPVOID cgtGlobalLock(HGLOBAL hGlobal);
  83. BOOL cgtGlobalUnlock(HGLOBAL hGlobal);
  84. void cgtVerifyAll(void);
  85. void cgtFlushTracking(void);
  86. BOOL cgtStopTracking(HGLOBAL hGlobal);
  87. private:
  88. SIZE_T CalculateAllocSize(SIZE_T cbUser);
  89. void InitializeRegion(HGLOBAL hGlobal, SIZE_T cbStart, SIZE_T cbEnd);
  90. void Track(HGLOBAL hGlobal, SIZE_T cbUser);
  91. void Retrack(HGLOBAL hOld, HGLOBAL hNew);
  92. void VerifyHandle(HGLOBAL hGlobal);
  93. ULONG _ulIndex;
  94. PSGLOBALALLOCINFO _pRoot;
  95. static COleStaticMutexSem _mxsGlobalMemory;
  96. };
  97. COleStaticMutexSem CGlobalTrack::_mxsGlobalMemory;
  98. CGlobalTrack gGlobalTrack;
  99. //+-------------------------------------------------------------------------
  100. //
  101. // Member: CGlobalTrack::CGlobalTrack, public
  102. //
  103. // Synopsis: constructor
  104. //
  105. // History: 28-Feb-94 AlexT Created
  106. //
  107. //--------------------------------------------------------------------------
  108. CGlobalTrack::CGlobalTrack()
  109. {
  110. Win4Assert (g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
  111. Win4Assert (_pRoot == NULL && _ulIndex == 0);
  112. }
  113. //+-------------------------------------------------------------------------
  114. //
  115. // Member: CGlobalTrack::cgtGlobalAlloc, public
  116. //
  117. // Synopsis: Debugging version of GlobalAlloc
  118. //
  119. // Arguments: [uiFlag] -- allocation flags
  120. // [cbUser] -- requested allocation size
  121. //
  122. // Requires: We must return a "real" GlobalAlloc'd pointer, because
  123. // we may not necessarily be the ones to free it.
  124. //
  125. // Returns: HGLOBAL
  126. //
  127. // Algorithm: We allocate an extra amount to form a tail and initialize it
  128. // to a known value.
  129. //
  130. // History: 25-Feb-94 AlexT Added this prologue
  131. //
  132. // Notes:
  133. //
  134. //--------------------------------------------------------------------------
  135. HGLOBAL CGlobalTrack::cgtGlobalAlloc(UINT uiFlag, SIZE_T cbUser)
  136. {
  137. VDATEHEAP();
  138. SIZE_T cbAlloc;
  139. HGLOBAL hGlobal;
  140. cbAlloc = CalculateAllocSize(cbUser);
  141. hGlobal = GlobalAlloc(uiFlag, cbAlloc);
  142. if (NULL == hGlobal)
  143. {
  144. LEDebugOut((DEB_WARN, "GlobalAlloc(%ld) failed - %lx\n", cbAlloc,
  145. GetLastError()));
  146. }
  147. else
  148. {
  149. if (uiFlag & GMEM_ZEROINIT)
  150. {
  151. // Caller asked for zeroinit, so we only initialize the tail
  152. InitializeRegion(hGlobal, cbUser, cbAlloc);
  153. }
  154. else
  155. {
  156. // Caller did not ask for zeroinit, so we initialize the whole
  157. // region
  158. InitializeRegion(hGlobal, 0, cbAlloc);
  159. }
  160. Track(hGlobal, cbUser);
  161. }
  162. return(hGlobal);
  163. }
  164. //+-------------------------------------------------------------------------
  165. //
  166. // Member: CGlobalTrack::cgtGlobalReAlloc, public
  167. //
  168. // Synopsis: Debugging version of GlobalReAlloc
  169. //
  170. // Arguments: [hGlobal] -- handle to reallocate
  171. // [cbUser] -- requested allocation size
  172. // [uiFlag] -- allocation flags
  173. //
  174. // Returns: reallocated handle
  175. //
  176. // Algorithm:
  177. //
  178. // if (modify only)
  179. // reallocate
  180. // else
  181. // reallocate with tail
  182. // initialize tail
  183. //
  184. // update tracking information
  185. //
  186. // History: 25-Feb-94 AlexT Added this prologue
  187. //
  188. // Notes:
  189. //
  190. //--------------------------------------------------------------------------
  191. HGLOBAL CGlobalTrack::cgtGlobalReAlloc(HGLOBAL hGlobal, SIZE_T cbUser, UINT uiFlag)
  192. {
  193. VDATEHEAP();
  194. HGLOBAL hNew;
  195. SIZE_T cbAlloc;
  196. VerifyHandle(hGlobal);
  197. if (uiFlag & GMEM_MODIFY)
  198. {
  199. // We're not changing sizes, so there's no work for us to do
  200. LEDebugOut((DEB_WARN, "UtGlobalReAlloc modifying global handle\n"));
  201. hNew = GlobalReAlloc(hGlobal, cbUser, uiFlag);
  202. }
  203. else
  204. {
  205. cbAlloc = CalculateAllocSize(cbUser);
  206. hNew = GlobalReAlloc(hGlobal, cbAlloc, uiFlag);
  207. if (NULL == hNew)
  208. {
  209. LEDebugOut((DEB_WARN, "GlobalReAlloc failed - %lx\n",
  210. GetLastError()));
  211. }
  212. else
  213. {
  214. InitializeRegion(hNew, cbUser, cbAlloc);
  215. }
  216. }
  217. if (NULL != hNew)
  218. {
  219. if (uiFlag & GMEM_MODIFY)
  220. {
  221. // Retrack will only track hNew if we were tracking hGlobal
  222. Retrack(hGlobal, hNew);
  223. }
  224. else
  225. {
  226. // We've allocated a new block, so we always want to track the
  227. // new one
  228. cgtStopTracking(hGlobal);
  229. Track(hNew, cbUser);
  230. }
  231. }
  232. return(hNew);
  233. }
  234. //+-------------------------------------------------------------------------
  235. //
  236. // Member: CGlobalTrack::cgtGlobalFree, public
  237. //
  238. // Synopsis: Debugging version of GlobalReAlloc
  239. //
  240. // Arguments: [hGlobal] -- global handle to free
  241. //
  242. // Returns: Same as GlobalFree
  243. //
  244. // Algorithm:
  245. //
  246. // History: 25-Feb-94 AlexT Created
  247. //
  248. // Notes:
  249. //
  250. //--------------------------------------------------------------------------
  251. HGLOBAL CGlobalTrack::cgtGlobalFree(HGLOBAL hGlobal)
  252. {
  253. VDATEHEAP();
  254. HGLOBAL hReturn;
  255. VerifyHandle(hGlobal);
  256. hReturn = GlobalFree(hGlobal);
  257. if (NULL == hReturn)
  258. {
  259. cgtStopTracking(hGlobal);
  260. }
  261. else
  262. {
  263. LEDebugOut((DEB_WARN, "GlobalFree did not free %lx\n", hGlobal));
  264. }
  265. return(hReturn);
  266. }
  267. //+-------------------------------------------------------------------------
  268. //
  269. // Member: CGlobalTrack::cgtGlobalLock, public
  270. //
  271. // Synopsis: Debugging version of GlobalLock
  272. //
  273. // Arguments: [hGlobal] -- global memory handle
  274. //
  275. // Returns: Same as GlobalLock
  276. //
  277. // History: 25-Feb-94 AlexT Created
  278. //
  279. // Notes:
  280. //
  281. //--------------------------------------------------------------------------
  282. LPVOID CGlobalTrack::cgtGlobalLock(HGLOBAL hGlobal)
  283. {
  284. VDATEHEAP();
  285. VerifyHandle(hGlobal);
  286. return(GlobalLock(hGlobal));
  287. }
  288. //+-------------------------------------------------------------------------
  289. //
  290. // Member: CGlobalTrack::cgtGlobalUnlock, public
  291. //
  292. // Synopsis: Debugging version of GlobalUnlock
  293. //
  294. // Arguments: [hGlobal] -- global memory handle
  295. //
  296. // Returns: Same as GlobalUnlock
  297. //
  298. // History: 25-Feb-94 AlexT Created
  299. //
  300. // Notes:
  301. //
  302. //--------------------------------------------------------------------------
  303. BOOL CGlobalTrack::cgtGlobalUnlock(HGLOBAL hGlobal)
  304. {
  305. VDATEHEAP();
  306. VerifyHandle(hGlobal);
  307. return(GlobalUnlock(hGlobal));
  308. }
  309. //+-------------------------------------------------------------------------
  310. //
  311. // Member: CGlobalTrack::cgtVerifyAll, public
  312. //
  313. // Synopsis: Verify all tracked handles
  314. //
  315. // History: 28-Feb-94 AlexT Created
  316. //
  317. // Notes:
  318. //
  319. //--------------------------------------------------------------------------
  320. void CGlobalTrack::cgtVerifyAll(void)
  321. {
  322. VerifyHandle(NULL);
  323. }
  324. //+-------------------------------------------------------------------------
  325. //
  326. // Member: CGlobalTrack::cgtFlushTracking
  327. //
  328. // Synopsis: Stops all tracking
  329. //
  330. // Effects: Frees all internal memory
  331. //
  332. // History: 28-Feb-94 AlexT Created
  333. //
  334. // Notes:
  335. //
  336. //--------------------------------------------------------------------------
  337. void CGlobalTrack::cgtFlushTracking(void)
  338. {
  339. COleStaticLock lck(_mxsGlobalMemory);
  340. BOOL bResult;
  341. while (NULL != _pRoot)
  342. {
  343. bResult = cgtStopTracking(_pRoot->hGlobal);
  344. Assert(bResult && "CGT::cgtFlushTracking problem");
  345. }
  346. }
  347. //+-------------------------------------------------------------------------
  348. //
  349. // Member: CGlobalTrack::CalculateAllocSize, private
  350. //
  351. // Synopsis: calculate total allocation size (inluding tail)
  352. //
  353. // Arguments: [cbUser] -- requested size
  354. //
  355. // Returns: total count of bytes to allocate
  356. //
  357. // Algorithm: calculate bytes needed to have at least one guard page at the
  358. // end
  359. //
  360. // History: 28-Feb-94 AlexT Created
  361. //
  362. // Notes: By keeping this calculation in one location we make it
  363. // easier to maintain.
  364. //
  365. //--------------------------------------------------------------------------
  366. SIZE_T CGlobalTrack::CalculateAllocSize(SIZE_T cbUser)
  367. {
  368. SYSTEM_INFO si;
  369. SIZE_T cbAlloc;
  370. GetSystemInfo(&si);
  371. // Calculate how many pages are need to cover cbUser
  372. cbAlloc = ((cbUser + si.dwPageSize - 1) / si.dwPageSize) * si.dwPageSize;
  373. // Add an extra page so that the tail is at least one page long
  374. cbAlloc += si.dwPageSize;
  375. return(cbAlloc);
  376. }
  377. //+-------------------------------------------------------------------------
  378. //
  379. // Member: CGlobalTrack::InitializeRegion, private
  380. //
  381. // Synopsis: initialize region to bad value
  382. //
  383. // Effects: fills in memory region
  384. //
  385. // Arguments: [hGlobal] -- global memory handle
  386. // [cbStart] -- count of bytes to skip
  387. // [cbEnd] -- end offset (exclusive)
  388. //
  389. // Requires: cbEnd > cbStart
  390. //
  391. // Algorithm: fill in hGlobal from cbStart (inclusive) to cbEnd (exclusive)
  392. //
  393. // History: 28-Feb-94 AlexT Created
  394. //
  395. // Notes:
  396. //
  397. //--------------------------------------------------------------------------
  398. void CGlobalTrack::InitializeRegion(HGLOBAL hGlobal, SIZE_T cbStart, SIZE_T cbEnd)
  399. {
  400. BYTE *pbStart;
  401. BYTE *pb;
  402. Assert(cbStart < cbEnd && "illogical parameters");
  403. Assert(cbEnd <= GlobalSize(hGlobal) && "global memory too small");
  404. // GlobalLock on GMEM_FIXED memory is a nop, so this is a safe call
  405. pbStart = (BYTE *) GlobalLock(hGlobal);
  406. if (NULL == pbStart)
  407. {
  408. // Shouldn't have failed - (we allocated > 0 bytes)
  409. LEDebugOut((DEB_WARN, "GlobalLock failed - %lx\n", GetLastError()));
  410. return;
  411. }
  412. // Initialize the tail portion of the memory
  413. for (pb = pbStart + cbStart; pb < pbStart + cbEnd; pb++)
  414. {
  415. *pb = OLEMEM_ALLOCBYTE;
  416. }
  417. GlobalUnlock(hGlobal);
  418. }
  419. //+-------------------------------------------------------------------------
  420. //
  421. // Member: CGlobalTrack::Track, private
  422. //
  423. // Synopsis:
  424. //
  425. // Effects:
  426. //
  427. // Arguments: [hGlobal] -- global memory handle
  428. // [cbUser] -- user allocation size
  429. //
  430. // Requires:
  431. //
  432. // Returns:
  433. //
  434. // Signals:
  435. //
  436. // Modifies:
  437. //
  438. // Derivation:
  439. //
  440. // Algorithm:
  441. //
  442. // History: 28-Feb-94 AlexT Created
  443. //
  444. // Notes:
  445. //
  446. //--------------------------------------------------------------------------
  447. void CGlobalTrack::Track(HGLOBAL hGlobal, SIZE_T cbUser)
  448. {
  449. COleStaticLock lck(_mxsGlobalMemory);
  450. PSGLOBALALLOCINFO pgi;
  451. if (cgtStopTracking(hGlobal))
  452. {
  453. // If it's already in our list, it's possible that someone else
  454. // freed the HGLOBAL without telling us - remove our stale one
  455. LEDebugOut((DEB_WARN, "CGT::Track - %lx was already in list!\n",
  456. hGlobal));
  457. }
  458. pgi = (PSGLOBALALLOCINFO) PrivMemAlloc(sizeof(SGLOBALALLOCINFO));
  459. if (NULL == pgi)
  460. {
  461. LEDebugOut((DEB_WARN, "CGT::Insert - PrivMemAlloc failed\n"));
  462. // Okay fine - we just won't track this one
  463. return;
  464. }
  465. pgi->hGlobal = hGlobal;
  466. pgi->cbGlobalSize = GlobalSize(hGlobal);
  467. Assert((0 == cbUser || pgi->cbGlobalSize > 0) && "GlobalSize failed - bad handle?");
  468. pgi->cbUser = cbUser;
  469. pgi->ulIndex = ++_ulIndex;
  470. pgi->pNext = _pRoot;
  471. _pRoot = pgi;
  472. }
  473. //+-------------------------------------------------------------------------
  474. //
  475. // Member: CGlobalTrack::Retrack, private
  476. //
  477. // Synopsis:
  478. //
  479. // Effects:
  480. //
  481. // Arguments: [hOld] -- previous handle
  482. // [hNew] -- new handle
  483. //
  484. // Modifies:
  485. //
  486. // Algorithm:
  487. //
  488. // History: 28-Feb-94 AlexT Created
  489. //
  490. // Notes:
  491. //
  492. //--------------------------------------------------------------------------
  493. void CGlobalTrack::Retrack(HGLOBAL hOld, HGLOBAL hNew)
  494. {
  495. COleStaticLock lck(_mxsGlobalMemory);
  496. PSGLOBALALLOCINFO pgi;
  497. if (hOld != hNew && cgtStopTracking(hNew))
  498. {
  499. // If hNew was already in the list, it's possible that someone else
  500. // freed the HGLOBAL without telling us so we removed the stale one
  501. LEDebugOut((DEB_WARN, "CGT::Retrack - %lx was already in list!\n", hNew));
  502. }
  503. for (pgi = _pRoot; NULL != pgi; pgi = pgi->pNext)
  504. {
  505. if (pgi->hGlobal == hOld)
  506. {
  507. pgi->hGlobal = hNew;
  508. break;
  509. }
  510. }
  511. if (NULL == pgi)
  512. {
  513. // We didn't find hOld
  514. LEDebugOut((DEB_WARN, "CGT::Retrack - hOld (%lx) not found\n", hOld));
  515. }
  516. }
  517. //+-------------------------------------------------------------------------
  518. //
  519. // Member: CGlobalTrack::cgtStopTracking, public
  520. //
  521. // Synopsis:
  522. //
  523. // Effects:
  524. //
  525. // Arguments: [hGlobal] -- global handle
  526. //
  527. // Modifies:
  528. //
  529. // Algorithm:
  530. //
  531. // History: 28-Feb-94 AlexT Created
  532. //
  533. // Notes:
  534. //
  535. //--------------------------------------------------------------------------
  536. BOOL CGlobalTrack::cgtStopTracking(HGLOBAL hGlobal)
  537. {
  538. COleStaticLock lck(_mxsGlobalMemory);
  539. PSGLOBALALLOCINFO *ppgi = &_pRoot;
  540. PSGLOBALALLOCINFO pgi;
  541. while (*ppgi != NULL && (*ppgi)->hGlobal != hGlobal)
  542. {
  543. ppgi = &((*ppgi)->pNext);
  544. }
  545. if (NULL == *ppgi)
  546. {
  547. return(FALSE);
  548. }
  549. pgi = *ppgi;
  550. Assert(pgi->hGlobal == hGlobal && "CGT::cgtStopTracking search problem");
  551. *ppgi = pgi->pNext;
  552. PrivMemFree(pgi);
  553. return(TRUE);
  554. }
  555. //+-------------------------------------------------------------------------
  556. //
  557. // Member: CGlobalTrack::VerifyHandle, private
  558. //
  559. // Synopsis: Verify global handle
  560. //
  561. // Arguments: [hGlobal] -- global memory handle
  562. //
  563. // Signals: Asserts if bad
  564. //
  565. // Algorithm:
  566. //
  567. // History: 28-Feb-94 AlexT Created
  568. // 22-Jun-94 AlexT Allow for handle to have been freed and
  569. // reallocated under us
  570. //
  571. //--------------------------------------------------------------------------
  572. void CGlobalTrack::VerifyHandle(HGLOBAL hGlobal)
  573. {
  574. COleStaticLock lck(_mxsGlobalMemory);
  575. PSGLOBALALLOCINFO pgi, pgiNext;
  576. SIZE_T cbAlloc;
  577. BYTE *pbStart;
  578. BYTE *pb;
  579. // Note that we use a while loop (recording pgiNext up front) instead
  580. // of a for loop because pgi will get removed from the list if we call
  581. // cgtStopTracking on it
  582. pgi = _pRoot;
  583. while (NULL != pgi)
  584. {
  585. pgiNext = pgi->pNext;
  586. if (NULL == hGlobal || pgi->hGlobal == hGlobal)
  587. {
  588. if (pgi->cbGlobalSize != GlobalSize(pgi->hGlobal))
  589. {
  590. // pgi->hGlobal's size has changed since we started tracking
  591. // it; it must have been freed or reallocated by someone
  592. // else. Stop tracking it.
  593. // This call will remove pgi from the list (so we NULL it to
  594. // make sure we don't try reusing it)!
  595. cgtStopTracking(pgi->hGlobal);
  596. pgi = NULL;
  597. }
  598. else
  599. {
  600. cbAlloc = CalculateAllocSize(pgi->cbUser);
  601. pbStart = (BYTE *) GlobalLock(pgi->hGlobal);
  602. // it is legitimate to have a zero length (NULL memory) handle
  603. if (NULL == pbStart)
  604. {
  605. LEDebugOut((DEB_WARN, "GlobalLock failed - %lx\n",
  606. GetLastError()));
  607. }
  608. else
  609. {
  610. for (pb = pbStart + pgi->cbUser;
  611. pb < pbStart + cbAlloc;
  612. pb++)
  613. {
  614. if (*pb != OLEMEM_ALLOCBYTE)
  615. break;
  616. }
  617. if (pb < pbStart + cbAlloc)
  618. {
  619. // In general an application may have freed and reallocated
  620. // any HGLOBAL, so we can only warn about corruption.
  621. LEDebugOut((DEB_WARN, "HGLOBAL #%ld may be corrupt\n",
  622. pgi->ulIndex));
  623. #ifdef GLOBALDBG
  624. // If GLOBALDBG is true, then all allocations should be
  625. // coming through these routines. In this case we assert
  626. // if we've found corruption.
  627. Assert(0 && "CGlobalTrack::VerifyHandle - HGLOBAL corrupt");
  628. #endif
  629. }
  630. GlobalUnlock(pgi->hGlobal);
  631. }
  632. }
  633. }
  634. pgi = pgiNext;
  635. }
  636. }
  637. //+-------------------------------------------------------------------------
  638. //
  639. // Function: UtGlobalAlloc, ReAlloc, Free, Lock, Unlock
  640. //
  641. // Synopsis: Debug versions of Global memory routines
  642. //
  643. // Arguments: Same as Windows APIs
  644. //
  645. // History: 28-Feb-94 AlexT Created
  646. //
  647. // Notes: These entry points just call the worker routines
  648. //
  649. //--------------------------------------------------------------------------
  650. extern "C" HGLOBAL WINAPI UtGlobalAlloc(UINT uiFlag, SIZE_T cbUser)
  651. {
  652. return gGlobalTrack.cgtGlobalAlloc(uiFlag, cbUser);
  653. }
  654. extern "C" HGLOBAL WINAPI UtGlobalReAlloc(HGLOBAL hGlobal, SIZE_T cbUser, UINT uiFlag)
  655. {
  656. return gGlobalTrack.cgtGlobalReAlloc(hGlobal, cbUser, uiFlag);
  657. }
  658. extern "C" LPVOID WINAPI UtGlobalLock(HGLOBAL hGlobal)
  659. {
  660. return gGlobalTrack.cgtGlobalLock(hGlobal);
  661. }
  662. extern "C" BOOL WINAPI UtGlobalUnlock(HGLOBAL hGlobal)
  663. {
  664. return gGlobalTrack.cgtGlobalUnlock(hGlobal);
  665. }
  666. extern "C" HGLOBAL WINAPI UtGlobalFree(HGLOBAL hGlobal)
  667. {
  668. return gGlobalTrack.cgtGlobalFree(hGlobal);
  669. }
  670. extern "C" void UtGlobalFlushTracking(void)
  671. {
  672. gGlobalTrack.cgtFlushTracking();
  673. }
  674. //+-------------------------------------------------------------------------
  675. //
  676. // Function: UtSetClipboardData
  677. //
  678. // Synopsis: Calls Windows SetClipboardData and stops tracking the handle
  679. //
  680. // Arguments: [uFormat] -- clipboard format
  681. // [hMem] -- data handle
  682. //
  683. // Returns: Same as SetClipboard
  684. //
  685. // Algorithm: If SetClipboardData succeeds, stop tracking the handle
  686. //
  687. // History: 30-Mar-94 AlexT Created
  688. //
  689. // Notes:
  690. //
  691. //--------------------------------------------------------------------------
  692. extern "C" HANDLE WINAPI UtSetClipboardData(UINT uFormat, HANDLE hMem)
  693. {
  694. HANDLE hRet;
  695. hRet = SetClipboardData(uFormat, hMem);
  696. if (NULL != hRet)
  697. {
  698. gGlobalTrack.cgtStopTracking(hMem);
  699. }
  700. return(hRet);
  701. }
  702. #endif // DBG==1 && defined(WIN32)