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.

2299 lines
64 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File:
  4. // utils.cpp
  5. //
  6. // Contents:
  7. // general OLE internal utility routines
  8. //
  9. // Classes:
  10. //
  11. // Functions:
  12. //
  13. // History:
  14. // 23-Jan-95 t-ScottH -added Dump method to CSafeRefCount and
  15. // CThreadCheck class
  16. // -added DumpCSafeRefCount API
  17. // 28-Jul-94 alexgo added object stabilization classes
  18. // 06-May-94 AlexT Add DVTARGET conversion routines
  19. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  20. // memory allocations.
  21. // 01/11/94 - alexgo - added VDATEHEAP macros to every function
  22. // 12/15/93 - ChrisWe - UtDupString has to scale length by
  23. // sizeof(OLECHAR)
  24. // 12/08/93 - ChrisWe - added necessary casts to GlobalLock() calls
  25. // resulting from removing bogus GlobalLock() macros in
  26. // le2int.h
  27. // 11/28/93 - ChrisWe - removed unreferenced define for MAX_STR,
  28. // formatted UtDupGlobal, UtDupString
  29. // 03/02/92 - SriniK - created
  30. //
  31. //-----------------------------------------------------------------------------
  32. #include <le2int.h>
  33. #pragma SEG(utils)
  34. #include <memory.h>
  35. #ifdef _DEBUG
  36. #include "dbgdump.h"
  37. #endif // _DEBUG
  38. NAME_SEG(Utils)
  39. ASSERTDATA
  40. #pragma SEG(UtDupGlobal)
  41. FARINTERNAL_(HANDLE) UtDupGlobal(HANDLE hsrc, UINT uiFlags)
  42. {
  43. VDATEHEAP();
  44. HANDLE hdst = NULL; // the newly create Handle DeSTination
  45. DWORD dwSize; // the size of the global
  46. #ifndef _MAC
  47. void FAR *lpsrc; // a pointer to the source memory
  48. void FAR *lpdst; // a pointer to the destination memory
  49. #endif
  50. // if no source, nothing to duplicate
  51. if (!hsrc)
  52. return(NULL);
  53. #ifdef _MAC
  54. if (!(hdst = NewHandle(dwSize = GetHandleSize(hsrc))))
  55. return(NULL);
  56. BlockMove(*hsrc, *hdst, dwSize);
  57. return(hdst);
  58. #else
  59. // if there's no content, do nothing
  60. if (!(lpsrc = GlobalLock(hsrc)))
  61. goto errRtn;
  62. // allocate a new global
  63. hdst = GlobalAlloc(uiFlags, (dwSize = (ULONG) GlobalSize(hsrc)));
  64. // if the allocation failed, get out
  65. if ((hdst == NULL) || ((lpdst = GlobalLock(hdst)) == NULL))
  66. goto errRtn;
  67. // copy the content
  68. _xmemcpy(lpdst, lpsrc, dwSize);
  69. // unlock the handles
  70. GlobalUnlock(hsrc);
  71. GlobalUnlock(hdst);
  72. return(hdst);
  73. errRtn:
  74. // unlock the source handle
  75. GlobalUnlock(hsrc);
  76. // if we allocated a destination handle, free it
  77. if (hdst)
  78. GlobalFree(hdst);
  79. return(NULL);
  80. #endif // _MAC
  81. }
  82. #pragma SEG(UtDupString)
  83. // copies string using the TASK allocator; returns NULL on out of memory
  84. // often when calling UtDupString, the caller knows the string length.
  85. // a good speed boost would be to call UtDupPtr instead
  86. // lpvIn must be non null
  87. // note: we do an alloc even if dw == 0
  88. FARINTERNAL_(LPVOID) UtDupPtr(LPVOID lpvIn, DWORD dw)
  89. {
  90. VDATEHEAP();
  91. LPVOID lpvOut; // the newly allocated ptr
  92. Assert(lpvIn); // internal fcn, lpvIn must be non-null
  93. if ((lpvOut = PubMemAlloc(dw)) != NULL) {
  94. memcpy(lpvOut, lpvIn, dw);
  95. }
  96. return lpvOut;
  97. }
  98. FARINTERNAL_(LPOLESTR) UtDupString(LPCOLESTR lpszIn)
  99. {
  100. return (LPOLESTR) UtDupPtr( (LPVOID) lpszIn,
  101. (_xstrlen(lpszIn)+1) * sizeof(OLECHAR) );
  102. }
  103. //+-------------------------------------------------------------------------
  104. //
  105. // Function: UtDupStringA
  106. //
  107. // Synopsis: Duplicates an ANSI string using the TASK allocator
  108. //
  109. // Effects:
  110. //
  111. // Arguments: [pszAnsi] -- the string to duplicate
  112. //
  113. // Requires:
  114. //
  115. // Returns: the newly allocated string duplicate or NULL
  116. //
  117. // Signals:
  118. //
  119. // Modifies:
  120. //
  121. // Algorithm:
  122. //
  123. // History: dd-mmm-yy Author Comment
  124. // 04-Jun-94 alexgo author
  125. //
  126. // Notes:
  127. //
  128. //--------------------------------------------------------------------------
  129. LPSTR UtDupStringA( LPCSTR pszAnsi )
  130. {
  131. return (LPSTR) UtDupPtr( (LPVOID) pszAnsi,
  132. strlen(pszAnsi) + 1 );
  133. }
  134. #pragma SEG(UtCopyTargetDevice)
  135. FARINTERNAL_(DVTARGETDEVICE FAR*) UtCopyTargetDevice(DVTARGETDEVICE FAR* ptd)
  136. {
  137. // if nothing to copy, return
  138. if (ptd == NULL)
  139. return(NULL);
  140. return (DVTARGETDEVICE FAR*) UtDupPtr((LPVOID) ptd, ptd->tdSize);
  141. }
  142. #pragma SEG(UtCopyFormatEtc)
  143. FARINTERNAL_(BOOL) UtCopyFormatEtc(FORMATETC FAR* pFetcIn,
  144. FORMATETC FAR* pFetcCopy)
  145. {
  146. VDATEHEAP();
  147. // copy structures
  148. *pFetcCopy = *pFetcIn;
  149. if (pFetcIn->ptd == NULL) {
  150. // all done, return true because the copy succeeded
  151. return TRUE;
  152. }
  153. // create a copy of the td descriptor, which is allocated
  154. pFetcCopy->ptd = UtCopyTargetDevice(pFetcIn->ptd);
  155. // return TRUE if we copied the data if we were supposed to
  156. return(pFetcCopy->ptd != NULL);
  157. }
  158. #pragma SEG(UtCompareFormatEtc)
  159. FARINTERNAL_(int) UtCompareFormatEtc(FORMATETC FAR* pFetcLeft,
  160. FORMATETC FAR* pFetcRight)
  161. {
  162. VDATEHEAP();
  163. int iResult; // indicates whether the match is exact or partial
  164. // if the clipboard formats are different, there is no match
  165. if (pFetcLeft->cfFormat != pFetcRight->cfFormat)
  166. return(UTCMPFETC_NEQ);
  167. // if the target devices don't match, there is no match
  168. if (!UtCompareTargetDevice(pFetcLeft->ptd, pFetcRight->ptd))
  169. return(UTCMPFETC_NEQ);
  170. // compare the aspects for the two formats
  171. if (pFetcLeft->dwAspect == pFetcRight->dwAspect)
  172. {
  173. // the match is exact
  174. iResult = UTCMPFETC_EQ;
  175. }
  176. else if ((pFetcLeft->dwAspect & ~pFetcRight->dwAspect) != 0)
  177. {
  178. // left not subset of aspects of right; not equal
  179. return(UTCMPFETC_NEQ);
  180. }
  181. else
  182. {
  183. // left aspects are a subset of the right aspects
  184. iResult = UTCMPFETC_PARTIAL;
  185. }
  186. // if we get here, iResult is set to one of UPCMPFETC_EQ or _PARTIAL
  187. // compare the media for the two formats
  188. if (pFetcLeft->tymed == pFetcRight->tymed)
  189. {
  190. // same medium flags; do not change value of iResult
  191. ;
  192. }
  193. else if ((pFetcLeft->tymed & ~pFetcRight->tymed) != 0)
  194. {
  195. // left not subset of medium flags of right; not equal
  196. return(UTCMPFETC_NEQ);
  197. }
  198. else
  199. {
  200. // left subset of right
  201. iResult = UTCMPFETC_PARTIAL;
  202. }
  203. return(iResult);
  204. }
  205. //+-------------------------------------------------------------------------
  206. //
  207. // Function: UtCompareTargetDevice
  208. //
  209. // Synopsis: Compare two DVTARGETDEVICEs
  210. //
  211. // Arguments: [ptdLeft] -- comparand
  212. // [ptdRight] -- comparee
  213. //
  214. // Returns: TRUE iff the two target devices are equivalent
  215. //
  216. // Algorithm:
  217. //
  218. // History: 09-May-94 AlexT Rewrote to do more than just a binary
  219. // compare
  220. //
  221. // Notes:
  222. //
  223. //--------------------------------------------------------------------------
  224. #define UT_DM_COMPARISON_FIELDS (DM_ORIENTATION | \
  225. DM_PAPERSIZE | \
  226. DM_PAPERLENGTH | \
  227. DM_PAPERWIDTH | \
  228. DM_SCALE | \
  229. DM_PRINTQUALITY | \
  230. DM_COLOR)
  231. #pragma SEG(UtCompareTargetDevice)
  232. FARINTERNAL_(BOOL) UtCompareTargetDevice(DVTARGETDEVICE FAR* ptdLeft,
  233. DVTARGETDEVICE FAR* ptdRight)
  234. {
  235. LEDebugOut((DEB_ITRACE, "%p _IN UtCompareTargetDevice (%p, %p)\n",
  236. NULL, ptdLeft, ptdRight));
  237. VDATEHEAP();
  238. BOOL bRet = FALSE; // More often than not we return FALSE
  239. // We use a do-while(FALSE) loop so that we can break out to common
  240. // return code at the end (the joys of tracing)
  241. do
  242. {
  243. // if the addresses of the two target device descriptors are the same,
  244. // then they must be the same. Note this handles the two NULL case.
  245. if (ptdLeft == ptdRight)
  246. {
  247. bRet = TRUE;
  248. break;
  249. }
  250. // if either td is NULL, can't compare them
  251. if ((ptdRight == NULL) || (ptdLeft == NULL))
  252. {
  253. AssertSz(bRet == FALSE, "bRet not set correctly");
  254. break;
  255. }
  256. // we ignore device name (My Printer vs. Your Printer doesn't matter)
  257. // check driver name
  258. if (ptdLeft->tdDriverNameOffset != 0)
  259. {
  260. if (ptdRight->tdDriverNameOffset == 0)
  261. {
  262. // Left driver exists, but no right driver
  263. AssertSz(bRet == FALSE, "bRet not set correctly");
  264. break;
  265. }
  266. // Both drivers exist
  267. if (_xstrcmp((LPOLESTR)((BYTE*)ptdLeft +
  268. ptdLeft->tdDriverNameOffset),
  269. (LPOLESTR)((BYTE*)ptdRight +
  270. ptdRight->tdDriverNameOffset)) != 0)
  271. {
  272. // Driver names don't match
  273. AssertSz(bRet == FALSE, "bRet not set correctly");
  274. break;
  275. }
  276. }
  277. else if (ptdRight->tdDriverNameOffset != 0)
  278. {
  279. // Left driver doesn't exist, but right driver does
  280. AssertSz(bRet == FALSE, "bRet not set correctly");
  281. break;
  282. }
  283. // we ignore port name
  284. if (0 == ptdLeft->tdExtDevmodeOffset)
  285. {
  286. if (0 == ptdRight->tdExtDevmodeOffset)
  287. {
  288. // Nothing left to compare
  289. bRet = TRUE;
  290. break;
  291. }
  292. else
  293. {
  294. // Only one Devmode
  295. AssertSz(bRet == FALSE, "bRet not set correctly");
  296. break;
  297. }
  298. }
  299. else if (0 == ptdRight->tdExtDevmodeOffset)
  300. {
  301. // Only one Devmode exists
  302. AssertSz(bRet == FALSE, "bRet not set correctly");
  303. break;
  304. }
  305. // Both TDs have Devmodes
  306. DEVMODEW *pdmLeft, *pdmRight;
  307. pdmLeft = (DEVMODEW *)((BYTE*)ptdLeft +
  308. ptdLeft->tdExtDevmodeOffset);
  309. pdmRight = (DEVMODEW *)((BYTE*)ptdRight +
  310. ptdRight->tdExtDevmodeOffset);
  311. // Check driver version
  312. if (pdmLeft->dmDriverVersion != pdmRight->dmDriverVersion)
  313. {
  314. AssertSz(bRet == FALSE, "bRet not set correctly");
  315. break;
  316. }
  317. // For a successful match, both device mode must specify the same
  318. // values for each of the following:
  319. // DM_ORIENTATION, DM_PAPERSIZE, DM_PAPERLENGTH.
  320. // DM_PAPERWIDTH, DM_SCALE, DM_PRINTQUALITY, DM_COLOR
  321. if ((pdmLeft->dmFields & UT_DM_COMPARISON_FIELDS) ^
  322. (pdmRight->dmFields & UT_DM_COMPARISON_FIELDS))
  323. {
  324. // Only one of pdmLeft and pdmRight specify at least one
  325. // of the comparison fields
  326. AssertSz(bRet == FALSE, "bRet not set correctly");
  327. break;
  328. }
  329. if ((pdmLeft->dmFields & DM_ORIENTATION) &&
  330. pdmLeft->dmOrientation != pdmRight->dmOrientation)
  331. {
  332. AssertSz(bRet == FALSE, "bRet not set correctly");
  333. break;
  334. }
  335. if ((pdmLeft->dmFields & DM_PAPERSIZE) &&
  336. pdmLeft->dmPaperSize != pdmRight->dmPaperSize)
  337. {
  338. AssertSz(bRet == FALSE, "bRet not set correctly");
  339. break;
  340. }
  341. if ((pdmLeft->dmFields & DM_PAPERLENGTH) &&
  342. pdmLeft->dmPaperLength != pdmRight->dmPaperLength)
  343. {
  344. AssertSz(bRet == FALSE, "bRet not set correctly");
  345. break;
  346. }
  347. if ((pdmLeft->dmFields & DM_PAPERWIDTH) &&
  348. pdmLeft->dmPaperWidth != pdmRight->dmPaperWidth)
  349. {
  350. AssertSz(bRet == FALSE, "bRet not set correctly");
  351. break;
  352. }
  353. if ((pdmLeft->dmFields & DM_SCALE) &&
  354. pdmLeft->dmScale != pdmRight->dmScale)
  355. {
  356. AssertSz(bRet == FALSE, "bRet not set correctly");
  357. break;
  358. }
  359. if ((pdmLeft->dmFields & DM_PRINTQUALITY) &&
  360. pdmLeft->dmPrintQuality != pdmRight->dmPrintQuality)
  361. {
  362. AssertSz(bRet == FALSE, "bRet not set correctly");
  363. break;
  364. }
  365. if ((pdmLeft->dmFields & DM_COLOR) &&
  366. pdmLeft->dmColor != pdmRight->dmColor)
  367. {
  368. AssertSz(bRet == FALSE, "bRet not set correctly");
  369. break;
  370. }
  371. bRet = TRUE;
  372. } while (FALSE);
  373. LEDebugOut((DEB_ITRACE, "%p OUT UtCompareTargetDevice (%d)\n",
  374. NULL, bRet));
  375. return(bRet);
  376. }
  377. #pragma SEG(UtCopyStatData)
  378. FARINTERNAL_(BOOL) UtCopyStatData(STATDATA FAR* pSDIn, STATDATA FAR* pSDCopy)
  379. {
  380. VDATEHEAP();
  381. // copy structures
  382. *pSDCopy = *pSDIn;
  383. // create copy of target device description (which is allocated)
  384. pSDCopy->formatetc.ptd = UtCopyTargetDevice(pSDIn->formatetc.ptd);
  385. // if there is an advise sink, account for the copy/reference
  386. if (pSDCopy->pAdvSink != NULL)
  387. pSDCopy->pAdvSink->AddRef();
  388. // return TRUE if the copy was done if it was required
  389. return((pSDCopy->formatetc.ptd != NULL) ==
  390. (pSDIn->formatetc.ptd != NULL));
  391. }
  392. //+-------------------------------------------------------------------------
  393. //
  394. // Function: UtReleaseStatData
  395. //
  396. // Synopsis: nulls && releases members of the given stat data structure
  397. //
  398. // Effects:
  399. //
  400. // Arguments: pStatData
  401. //
  402. // Requires:
  403. //
  404. // Returns: void
  405. //
  406. // Signals:
  407. //
  408. // Modifies:
  409. //
  410. // Algorithm: We copy the data first and NULL out the stat data
  411. // because the Release on the Advise sink could cause us
  412. // to be re-entered.
  413. //
  414. // History: dd-mmm-yy Author Comment
  415. // 20-Jul-94 alexgo made safe for OLE sytle re-entrancy
  416. //
  417. // Notes:
  418. //
  419. //--------------------------------------------------------------------------
  420. FARINTERNAL_(void) UtReleaseStatData(STATDATA FAR* pStatData)
  421. {
  422. STATDATA sd;
  423. VDATEHEAP();
  424. sd = *pStatData;
  425. // zero out the original before doing any work
  426. _xmemset(pStatData, 0, sizeof(STATDATA));
  427. // if there's a target device description, free it
  428. if (sd.formatetc.ptd != NULL)
  429. {
  430. PubMemFree(sd.formatetc.ptd);
  431. }
  432. if( sd.pAdvSink )
  433. {
  434. sd.pAdvSink->Release();
  435. }
  436. }
  437. //+-------------------------------------------------------------------------
  438. //
  439. // Function: UtCreateStorageOnHGlobal
  440. //
  441. // Synopsis: creates a storage on top of an HGlobal
  442. //
  443. // Effects:
  444. //
  445. // Arguments: [hGlobal] -- the memory on which to create the
  446. // storage
  447. // [fDeleteOnRelease] -- if TRUE, then delete the hglobal
  448. // once the storage is released.
  449. // [ppStg] -- where to put the storage interface
  450. // [ppILockBytes] -- where to put the underlying ILockBytes,
  451. // maybe NULL. The ILB must be released.
  452. //
  453. // Requires:
  454. //
  455. // Returns: HRESULT
  456. //
  457. // Signals:
  458. //
  459. // Modifies:
  460. //
  461. // Algorithm: create an ILockBytes on HGLOBAL and then create the docfile
  462. // on top of the ILockBytes
  463. //
  464. // History: dd-mmm-yy Author Comment
  465. // 07-Apr-94 alexgo author
  466. //
  467. // Notes:
  468. //
  469. //--------------------------------------------------------------------------
  470. HRESULT UtCreateStorageOnHGlobal( HGLOBAL hGlobal, BOOL fDeleteOnRelease,
  471. IStorage **ppStg, ILockBytes **ppILockBytes )
  472. {
  473. HRESULT hresult;
  474. ILockBytes * pLockBytes;
  475. VDATEHEAP();
  476. LEDebugOut((DEB_ITRACE, "%p _IN UtCreateStorageOnHGlobal ( %lx , %p )"
  477. "\n", NULL, hGlobal, ppStg));
  478. hresult = CreateILockBytesOnHGlobal(hGlobal, fDeleteOnRelease,
  479. &pLockBytes);
  480. if( hresult == NOERROR )
  481. {
  482. hresult = StgCreateDocfileOnILockBytes( pLockBytes,
  483. STGM_CREATE | STGM_SALL, 0, ppStg);
  484. // no matter what the result of StgCreate is, we want
  485. // to release the LockBytes. If hresult == NOERROR, then
  486. // the final release to the LockBytes will come when the
  487. // created storage is released.
  488. }
  489. if( ppILockBytes )
  490. {
  491. *ppILockBytes = pLockBytes;
  492. }
  493. else if (pLockBytes)
  494. {
  495. // we release here so the final release of the storage
  496. // will be the final release of the lockbytes
  497. pLockBytes->Release();
  498. }
  499. LEDebugOut((DEB_ITRACE, "%p OUT UtCreateStorageOnHGlobal ( %lx ) "
  500. "[ %p ]\n", NULL, hresult, *ppStg));
  501. return hresult;
  502. }
  503. //+-------------------------------------------------------------------------
  504. //
  505. // Function: UtGetTempFileName
  506. //
  507. // Synopsis: retrieves a temporary filename (for use in GetData, TYMED_FILE
  508. // and temporary docfiles)
  509. //
  510. // Effects:
  511. //
  512. // Arguments: [pszPrefix] -- prefix of the temp filename
  513. // [pszTempName] -- buffer that will receive the temp path.
  514. // must be MAX_PATH or greater.
  515. //
  516. // Requires:
  517. //
  518. // Returns: HRESULT;
  519. //
  520. // Signals:
  521. //
  522. // Modifies:
  523. //
  524. // Algorithm: tries to get a file in the temp directory, failing that, in
  525. // the windows directory
  526. //
  527. // History: dd-mmm-yy Author Comment
  528. // 07-Apr-94 alexgo author
  529. //
  530. // Notes: OPTIMIZATION: The storage code has a similar peice of code
  531. // for generating temporary docfiles. We may want to use this
  532. // routine there as well.
  533. //
  534. //--------------------------------------------------------------------------
  535. HRESULT UtGetTempFileName( LPOLESTR pszPrefix, LPOLESTR pszTempName )
  536. {
  537. HRESULT hresult = NOERROR;
  538. OLECHAR szPath[MAX_PATH + 1];
  539. VDATEHEAP();
  540. LEDebugOut((DEB_ITRACE, "%p _IN UtGetTempFilename ( \"%ws\" , "
  541. "\"%ws\")\n", NULL, pszPrefix, pszTempName));
  542. if( !GetTempPath(MAX_PATH, szPath) )
  543. {
  544. LEDebugOut((DEB_WARN, "WARNING: GetTempPath failed!\n"));
  545. if( !GetWindowsDirectory(szPath, MAX_PATH) )
  546. {
  547. LEDebugOut((DEB_WARN, "WARNING: GetWindowsDirectory"
  548. " failed!!\n"));
  549. hresult = ResultFromScode(E_FAIL);
  550. goto errRtn;
  551. }
  552. }
  553. if( !GetTempFileName( szPath, pszPrefix, 0, pszTempName ) )
  554. {
  555. LEDebugOut((DEB_WARN, "WARNING: GetTempFileName failed!!\n"));
  556. hresult = ResultFromScode(E_FAIL);
  557. }
  558. errRtn:
  559. LEDebugOut((DEB_ITRACE, "%p OUT UtGetTempFilename ( %lx ) "
  560. "[ \"%ws\" ]\n", NULL, hresult, pszTempName));
  561. return hresult;
  562. }
  563. //+----------------------------------------------------------------------------
  564. //
  565. // Function:
  566. // UtHGLOBALtoStm, internal
  567. //
  568. // Synopsis:
  569. // Write the contents of an HGLOBAL to a stream
  570. //
  571. // Arguments:
  572. // [hdata] -- handle to the data to write out
  573. // [dwSize] -- size of the data to write out
  574. // [pstm] -- stream to write the data out to; on exit, the
  575. // stream is positioned after the written data
  576. //
  577. // Returns:
  578. // HRESULT
  579. //
  580. // Notes:
  581. //
  582. // History:
  583. // 04/10/94 - AlexGo - added call tracing, moved from convert.cpp
  584. // to utils.cpp, misc improvements.
  585. // 11/30/93 - ChrisWe - file inspection and cleanup
  586. //
  587. //-----------------------------------------------------------------------------
  588. HRESULT UtHGLOBALtoStm(HGLOBAL hGlobalSrc, DWORD dwSize, LPSTREAM pstm)
  589. {
  590. HRESULT hresult = NOERROR;
  591. void * lpdata;
  592. ULONG cbWritten;
  593. VDATEHEAP();
  594. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStm ( %lx , %lu , %p )\n",
  595. NULL, hGlobalSrc, dwSize, pstm));
  596. lpdata = GlobalLock(hGlobalSrc);
  597. if (lpdata)
  598. {
  599. hresult = pstm->Write(lpdata, dwSize, &cbWritten);
  600. // if we didn't write enough data, then it's an error
  601. // condition for us.
  602. if( hresult == NOERROR && cbWritten != dwSize )
  603. {
  604. hresult = ResultFromScode(E_FAIL);
  605. }
  606. if( hresult == NOERROR )
  607. {
  608. // this call isn't strictly necessary, but may
  609. // be useful for compacting the size of presentations
  610. // stored on disk (when called by the presentation
  611. // code)
  612. hresult = StSetSize(pstm, 0, TRUE);
  613. }
  614. GlobalUnlock(hGlobalSrc);
  615. }
  616. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStm ( %lx )\n", NULL,
  617. hresult));
  618. return hresult;
  619. }
  620. //+-------------------------------------------------------------------------
  621. //
  622. // Function: UtHGLOBALtoHGLOBAL, internal
  623. //
  624. // Synopsis: Copies the source HGLOBAL into the target HGLOBAL
  625. //
  626. // Effects:
  627. //
  628. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  629. // [dwSize] -- the number of bytes to copy
  630. // [hGlobalTgt] -- the target HGLOBAL
  631. //
  632. // Requires:
  633. //
  634. // Returns: HRESULT
  635. //
  636. // Signals:
  637. //
  638. // Modifies:
  639. //
  640. // Algorithm:
  641. //
  642. // History: dd-mmm-yy Author Comment
  643. // 10-Apr-94 alexgo author
  644. //
  645. // Notes: this function will fail if the target hglobal is not large
  646. // enough
  647. //
  648. //--------------------------------------------------------------------------
  649. HRESULT UtHGLOBALtoHGLOBAL( HGLOBAL hGlobalSrc, DWORD dwSize,
  650. HGLOBAL hGlobalTgt)
  651. {
  652. DWORD cbTarget;
  653. void * pvSrc;
  654. void * pvTgt;
  655. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  656. VDATEHEAP();
  657. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoHGLOBAL ( %lx , %lu , "
  658. "%lx )\n", NULL, hGlobalSrc, dwSize, hGlobalTgt));
  659. cbTarget = (ULONG) GlobalSize(hGlobalTgt);
  660. if( cbTarget == 0 || cbTarget < dwSize )
  661. {
  662. hresult = ResultFromScode(E_FAIL);
  663. goto errRtn;
  664. }
  665. pvSrc = GlobalLock(hGlobalSrc);
  666. if( pvSrc )
  667. {
  668. pvTgt = GlobalLock(hGlobalTgt);
  669. if( pvTgt )
  670. {
  671. _xmemcpy( pvTgt, pvSrc, dwSize);
  672. GlobalUnlock(hGlobalTgt);
  673. hresult = NOERROR;
  674. }
  675. GlobalUnlock(hGlobalSrc);
  676. }
  677. errRtn:
  678. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoHGLOBAL ( %lx )\n",
  679. NULL, hresult));
  680. return hresult;
  681. }
  682. //+-------------------------------------------------------------------------
  683. //
  684. // Function: UtHGLOBALtoStorage, internal
  685. //
  686. // Synopsis: Copies the source HGLOBAL into the target storage
  687. //
  688. // Effects:
  689. //
  690. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  691. // [pStgTgt] -- the target storage
  692. //
  693. // Requires:
  694. //
  695. // Returns: HRESULT
  696. //
  697. // Signals:
  698. //
  699. // Modifies:
  700. //
  701. // Algorithm:
  702. //
  703. // History: dd-mmm-yy Author Comment
  704. // 10-Apr-94 alexgo author
  705. //
  706. // Notes: this function will fail if the source HGLOBAL did not
  707. // originally have a storage layered on top of it.
  708. //
  709. //--------------------------------------------------------------------------
  710. HRESULT UtHGLOBALtoStorage( HGLOBAL hGlobalSrc, IStorage *pStgTgt)
  711. {
  712. HRESULT hresult;
  713. ILockBytes * pLockBytes = NULL;
  714. IStorage * pStgSrc;
  715. ULONG cRefs;
  716. VDATEHEAP();
  717. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStroage ( %lx , %p )"
  718. "\n", NULL, hGlobalSrc, pStgTgt));
  719. hresult = CreateILockBytesOnHGlobal(hGlobalSrc,
  720. FALSE /*fDeleteOnRelease*/, &pLockBytes);
  721. if( hresult != NOERROR )
  722. {
  723. goto errRtn;
  724. }
  725. // now we make sure that the hglobal really has a storage
  726. // in it
  727. if( StgIsStorageILockBytes(pLockBytes) != NOERROR )
  728. {
  729. hresult = ResultFromScode(E_FAIL);
  730. goto errRtn;
  731. }
  732. hresult = StgOpenStorageOnILockBytes( pLockBytes, NULL,
  733. STGM_SALL, NULL, 0, &pStgSrc);
  734. if( hresult == NOERROR )
  735. {
  736. hresult = pStgSrc->CopyTo( 0, NULL, NULL, pStgTgt);
  737. // no matter what the result, we want to free the
  738. // source storage
  739. pStgSrc->Release();
  740. }
  741. errRtn:
  742. if( pLockBytes )
  743. {
  744. cRefs = pLockBytes->Release();
  745. Assert(cRefs == 0);
  746. }
  747. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStorage ( %lx ) "
  748. "[ %p ]\n", NULL, hresult));
  749. return hresult;
  750. }
  751. //+-------------------------------------------------------------------------
  752. //
  753. // Function: UtHGLOBALtoFile, internal
  754. //
  755. // Synopsis: Copies the source HGLOBAL into the target file
  756. //
  757. // Effects:
  758. //
  759. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  760. // [dwSize] -- the number of bytes to copy
  761. // [pszFileName] -- the target file
  762. //
  763. // Requires:
  764. //
  765. // Returns: HRESULT
  766. //
  767. // Signals:
  768. //
  769. // Modifies:
  770. //
  771. // Algorithm:
  772. //
  773. // History: dd-mmm-yy Author Comment
  774. // 10-Apr-94 alexgo author
  775. //
  776. // Notes: if the file already exists, we simply append to it
  777. //
  778. //--------------------------------------------------------------------------
  779. HRESULT UtHGLOBALtoFile( HGLOBAL hGlobalSrc, DWORD dwSize,
  780. LPCOLESTR pszFileName)
  781. {
  782. HRESULT hresult;
  783. HANDLE hFile;
  784. void * pvSrc;
  785. DWORD cbWritten;
  786. VDATEHEAP();
  787. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoFile ( %lx , %lu , "
  788. "\"%ws\" )\n", NULL, hGlobalSrc, dwSize, pszFileName));
  789. hresult = ResultFromScode(E_NOTIMPL);
  790. (void)hFile;
  791. (void)pvSrc;
  792. (void)cbWritten;
  793. // this doesn't compile for chicago [, but we don't need this anyway]
  794. #ifdef LATER
  795. pvSrc = GlobalLock(hGlobalSrc);
  796. if( !pvSrc )
  797. {
  798. hresult = ResultFromScode(E_OUTOFMEMORY);
  799. goto errRtn;
  800. }
  801. // open the file for append, creating if it doesn't already exist.
  802. hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL,
  803. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  804. if( hFile != INVALID_HANDLE_VALUE )
  805. {
  806. if( !WriteFile( hFile, pvSrc, dwSize, &cbWritten, NULL) )
  807. {
  808. LEDebugOut((DEB_WARN, "WARNING: WriteFile failed!\n"));
  809. hresult = HRESULT_FROM_WIN32(GetLastError());
  810. }
  811. if( cbWritten != dwSize && hresult == NOERROR )
  812. {
  813. // still an error if we didn't write all the bytes
  814. // we wanted
  815. hresult = ResultFromScode(E_FAIL);
  816. }
  817. if( !CloseHandle(hFile) )
  818. {
  819. AssertSz(0, "CloseFile failed! Should not happen!");
  820. // if there's no error yet, set the error
  821. if( hresult == NOERROR )
  822. {
  823. hresult = HRESULT_FROM_WIN32(GetLastError());
  824. }
  825. }
  826. }
  827. else
  828. {
  829. LEDebugOut((DEB_WARN, "WARNING: CreateFile failed!!\n"));
  830. hresult = HRESULT_FROM_WIN32(GetLastError());
  831. }
  832. GlobalUnlock(hGlobalSrc);
  833. errRtn:
  834. #endif // LATER
  835. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoFile ( %lx )\n", NULL,
  836. hresult));
  837. return hresult;
  838. }
  839. //+-------------------------------------------------------------------------
  840. //
  841. // Function: UtGetDvtd16Info
  842. //
  843. // Synopsis: Fills in pdvdtInfo
  844. //
  845. // Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
  846. // [pdvtdInfo] -- pointer to DVDT_INFO block
  847. //
  848. // Requires:
  849. //
  850. // Returns: HRESULT
  851. //
  852. // Modifies: pdvtdInfo
  853. //
  854. // Algorithm:
  855. //
  856. // History: 06-May-94 AlexT Created from DrewB's original functions
  857. // 10-Jul-94 AlexT Make sure DEVMODE ends up DWORD aligned
  858. //
  859. // Notes: Do we need to do any error checking on the strings?
  860. //
  861. //--------------------------------------------------------------------------
  862. // We can't use sizeof(DV_TARGETDEVICE) because MIDL keeps flipping back
  863. // and forth over whether to make the embedded array size 0 or size 1
  864. #define UT_DVTARGETDEVICE_SIZE (sizeof(DWORD) + sizeof(WORD) * 4)
  865. // tdSize td...Offset's
  866. #define DVTD_MINSIZE (sizeof(DWORD) + 4 * sizeof(WORD))
  867. extern "C" HRESULT UtGetDvtd16Info(DVTARGETDEVICE const UNALIGNED *pdvtd16,
  868. PDVTDINFO pdvtdInfo)
  869. {
  870. LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd16Info (%p, %p)\n",
  871. NULL, pdvtd16, pdvtdInfo));
  872. DEVMODEA UNALIGNED *pdm16;
  873. // Let's do some sanity checking on the incoming DVTARGETDEVICE
  874. if (pdvtd16->tdSize < DVTD_MINSIZE)
  875. {
  876. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdSize\n"));
  877. return(E_INVALIDARG);
  878. }
  879. // We need at least a DVTARGETDEVICE
  880. pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
  881. // Compute required size for Drv, Device, Port names
  882. if (pdvtd16->tdDriverNameOffset != 0)
  883. {
  884. if (pdvtd16->tdDriverNameOffset > pdvtd16->tdSize ||
  885. pdvtd16->tdDriverNameOffset < DVTD_MINSIZE)
  886. {
  887. // Offset can't be larger than size or fall within base
  888. // structure
  889. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDriverNameOffset\n"));
  890. return(E_INVALIDARG);
  891. }
  892. pdvtdInfo->cchDrvName = strlen((char *)pdvtd16 +
  893. pdvtd16->tdDriverNameOffset) + 1;
  894. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
  895. }
  896. else
  897. {
  898. pdvtdInfo->cchDrvName = 0;
  899. }
  900. if (pdvtd16->tdDeviceNameOffset != 0)
  901. {
  902. if (pdvtd16->tdDeviceNameOffset > pdvtd16->tdSize ||
  903. pdvtd16->tdDeviceNameOffset < DVTD_MINSIZE)
  904. {
  905. // Offset can't be larger than size or fall within base
  906. // structure
  907. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDeviceNameOffset\n"));
  908. return(E_INVALIDARG);
  909. }
  910. pdvtdInfo->cchDevName = strlen((char *)pdvtd16 +
  911. pdvtd16->tdDeviceNameOffset) + 1;
  912. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
  913. }
  914. else
  915. {
  916. pdvtdInfo->cchDevName = 0;
  917. }
  918. if (pdvtd16->tdPortNameOffset != 0)
  919. {
  920. if (pdvtd16->tdPortNameOffset > pdvtd16->tdSize ||
  921. pdvtd16->tdPortNameOffset < DVTD_MINSIZE)
  922. {
  923. // Offset can't be larger than size or fall within base
  924. // structure
  925. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdPortNameOffset\n"));
  926. return(E_INVALIDARG);
  927. }
  928. pdvtdInfo->cchPortName = strlen((char *)pdvtd16 +
  929. pdvtd16->tdPortNameOffset) + 1;
  930. pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
  931. }
  932. else
  933. {
  934. pdvtdInfo->cchPortName = 0;
  935. }
  936. if (pdvtd16->tdExtDevmodeOffset != 0)
  937. {
  938. if (pdvtd16->tdExtDevmodeOffset > pdvtd16->tdSize ||
  939. pdvtd16->tdExtDevmodeOffset < DVTD_MINSIZE)
  940. {
  941. // Offset can't be larger than size or fall within base
  942. // structure
  943. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdExtDevmodeOffset\n"));
  944. return(E_INVALIDARG);
  945. }
  946. // The DEVMODEW structure needs to be DWORD aligned, so here we make
  947. // sure cbConvertSize (which will be the beginning of DEVMODEW) is
  948. // DWORD aligned
  949. pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
  950. pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
  951. // Now compute the space needed for the DEVMODE
  952. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16 + pdvtd16->tdExtDevmodeOffset);
  953. // We start with a basic DEVMODEW
  954. pdvtdInfo->cbConvertSize += sizeof(DEVMODEW);
  955. if (pdm16->dmSize > sizeof(DEVMODEA))
  956. {
  957. // The input DEVMODEA is larger than a standard DEVMODEA, so
  958. // add space for the extra amount
  959. pdvtdInfo->cbConvertSize += pdm16->dmSize - sizeof(DEVMODEA);
  960. }
  961. // Finally we account for the extra driver data
  962. pdvtdInfo->cbConvertSize += pdm16->dmDriverExtra;
  963. }
  964. LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd16Info (%lx) [%ld]\n",
  965. NULL, S_OK, pdvtdInfo->cbConvertSize));
  966. return(S_OK);
  967. }
  968. //+-------------------------------------------------------------------------
  969. //
  970. // Function: UtConvertDvtd16toDvtd32
  971. //
  972. // Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
  973. // DVTARGETDEVICE
  974. //
  975. // Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
  976. // [pdvtdInfo] -- pointer to DVDT_INFO block
  977. // [pdvtd32] -- pointer to UNICODE DVTARGETDEVICE
  978. //
  979. // Requires: pdvtdInfo must have been filled in by a previous call to
  980. // UtGetDvtd16Info
  981. //
  982. // pdvtd32 must be at least pdvtdInfo->cbConvertSize bytes long
  983. //
  984. // Returns: HRESULT
  985. //
  986. // Modifies: pdvtd32
  987. //
  988. // Algorithm:
  989. //
  990. // History: 06-May-94 AlexT Created from DrewB's original functions
  991. // 10-Jul-94 AlexT Make sure DEVMODEW is DWORD aligned
  992. //
  993. // Notes: Do we need to do any error checking on the strings?
  994. //
  995. //--------------------------------------------------------------------------
  996. extern "C" HRESULT UtConvertDvtd16toDvtd32(DVTARGETDEVICE const UNALIGNED *pdvtd16,
  997. DVTDINFO const *pdvtdInfo,
  998. DVTARGETDEVICE *pdvtd32)
  999. {
  1000. LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd16toDvtd32 (%p, %p, %p)\n",
  1001. NULL, pdvtd16, pdvtdInfo, pdvtd32));
  1002. #if DBG==1
  1003. {
  1004. // Verify the passed in pdvtdInfo is what we expect
  1005. DVTDINFO dbgDvtdInfo;
  1006. Assert(UtGetDvtd16Info(pdvtd16, &dbgDvtdInfo) == S_OK);
  1007. Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
  1008. }
  1009. #endif
  1010. HRESULT hr = S_OK;
  1011. USHORT cbOffset;
  1012. int cchWritten;
  1013. DEVMODEA UNALIGNED *pdm16;
  1014. DEVMODEW *pdm32;
  1015. UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  1016. memset(pdvtd32, 0, pdvtdInfo->cbConvertSize);
  1017. cbOffset = UT_DVTARGETDEVICE_SIZE;
  1018. if (pdvtdInfo->cchDrvName != 0)
  1019. {
  1020. pdvtd32->tdDriverNameOffset = cbOffset;
  1021. cchWritten = MultiByteToWideChar(
  1022. CP_ACP, 0,
  1023. (char *)pdvtd16+pdvtd16->tdDriverNameOffset,
  1024. pdvtdInfo->cchDrvName,
  1025. (LPOLESTR)((BYTE *)pdvtd32 +
  1026. pdvtd32->tdDriverNameOffset),
  1027. pdvtdInfo->cchDrvName);
  1028. if (0 == cchWritten)
  1029. {
  1030. hr = E_UNEXPECTED;
  1031. goto ErrRtn;
  1032. }
  1033. cbOffset += (USHORT)(cchWritten * sizeof(WCHAR));
  1034. }
  1035. if (pdvtdInfo->cchDevName != 0)
  1036. {
  1037. pdvtd32->tdDeviceNameOffset = cbOffset;
  1038. cchWritten = MultiByteToWideChar(
  1039. nCodePage, 0,
  1040. (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
  1041. pdvtdInfo->cchDevName,
  1042. (LPOLESTR)((BYTE *)pdvtd32 +
  1043. pdvtd32->tdDeviceNameOffset),
  1044. pdvtdInfo->cchDevName);
  1045. if (0 == cchWritten)
  1046. {
  1047. hr = E_UNEXPECTED;
  1048. goto ErrRtn;
  1049. }
  1050. cbOffset += (USHORT)(cchWritten * sizeof(WCHAR));
  1051. }
  1052. if (pdvtdInfo->cchPortName != 0)
  1053. {
  1054. pdvtd32->tdPortNameOffset = cbOffset;
  1055. cchWritten = MultiByteToWideChar(
  1056. nCodePage, 0,
  1057. (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
  1058. pdvtdInfo->cchPortName,
  1059. (LPOLESTR)((BYTE *)pdvtd32 +
  1060. pdvtd32->tdPortNameOffset),
  1061. pdvtdInfo->cchPortName);
  1062. if (0 == cchWritten)
  1063. {
  1064. hr = E_UNEXPECTED;
  1065. goto ErrRtn;
  1066. }
  1067. cbOffset += (USHORT)(cchWritten * sizeof(WCHAR));
  1068. }
  1069. if (pdvtd16->tdExtDevmodeOffset != 0)
  1070. {
  1071. // Make sure DEVMODEW will be DWORD aligned
  1072. cbOffset += (sizeof(DWORD) - 1);
  1073. cbOffset &= ~(sizeof(DWORD) - 1);
  1074. pdvtd32->tdExtDevmodeOffset = cbOffset;
  1075. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1076. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
  1077. // The incoming DEVMODEA can have one of the following two forms:
  1078. //
  1079. // 1) 32 chars for dmDeviceName
  1080. // m bytes worth of fixed size data (where m <= 38)
  1081. // n bytes of dmDriverExtra data
  1082. //
  1083. // and dmSize will be 32+m
  1084. //
  1085. // 2) 32 chars for dmDeviceName
  1086. // 38 bytes worth of fixed size data
  1087. // 32 chars for dmFormName
  1088. // m additional bytes of fixed size data
  1089. // n bytes of dmDriverExtra data
  1090. //
  1091. // and dmSize will be 32 + 38 + 32 + m
  1092. //
  1093. // We have to be careful to translate the dmFormName string, if it
  1094. // exists
  1095. // First, translate the dmDeviceName
  1096. if (MultiByteToWideChar(nCodePage, 0, (char *)pdm16->dmDeviceName,
  1097. CCHDEVICENAME,
  1098. pdm32->dmDeviceName, CCHDEVICENAME) == 0)
  1099. {
  1100. hr = E_UNEXPECTED;
  1101. goto ErrRtn;
  1102. }
  1103. // Now check to see if we have a dmFormName to translate
  1104. if (pdm16->dmSize <= FIELD_OFFSET(DEVMODEA, dmFormName))
  1105. {
  1106. // No dmFormName, just copy the remaining m bytes
  1107. memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
  1108. pdm16->dmSize - CCHDEVICENAME);
  1109. }
  1110. else
  1111. {
  1112. // There is a dmFormName; copy the bytes between the names first
  1113. memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
  1114. FIELD_OFFSET(DEVMODEA, dmFormName) -
  1115. FIELD_OFFSET(DEVMODEA, dmSpecVersion));
  1116. // Now translate the dmFormName
  1117. if (MultiByteToWideChar(CP_ACP, 0, (char *)pdm16->dmFormName,
  1118. CCHFORMNAME,
  1119. pdm32->dmFormName, CCHFORMNAME) == 0)
  1120. {
  1121. hr = E_UNEXPECTED;
  1122. goto ErrRtn;
  1123. }
  1124. // Now copy the remaining m bytes
  1125. if (pdm16->dmSize > FIELD_OFFSET(DEVMODEA, dmLogPixels))
  1126. {
  1127. memcpy(&pdm32->dmLogPixels, &pdm16->dmLogPixels,
  1128. pdm16->dmSize - FIELD_OFFSET(DEVMODEA, dmLogPixels));
  1129. }
  1130. }
  1131. pdm32->dmSize = sizeof(DEVMODEW);
  1132. if (pdm16->dmSize > sizeof(DEVMODEA))
  1133. {
  1134. pdm32->dmSize += pdm16->dmSize - sizeof(DEVMODEA);
  1135. }
  1136. // Copy the extra driver bytes
  1137. memcpy(((BYTE*)pdm32) + pdm32->dmSize, ((BYTE*)pdm16) + pdm16->dmSize,
  1138. pdm16->dmDriverExtra);
  1139. cbOffset += pdm32->dmSize + pdm32->dmDriverExtra;
  1140. }
  1141. // Finally, set pdvtd32's size
  1142. pdvtd32->tdSize = cbOffset;
  1143. ErrRtn:
  1144. LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd16toDvtd32 (%lx)\n",
  1145. NULL, hr));
  1146. return hr;
  1147. }
  1148. //+-------------------------------------------------------------------------
  1149. //
  1150. // Function: UtGetDvtd32Info
  1151. //
  1152. // Synopsis: Fills in pdvdtInfo
  1153. //
  1154. // Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
  1155. // [pdvtdInfo] -- pointer to DVDT_INFO block
  1156. //
  1157. // Requires:
  1158. //
  1159. // Returns: HRESULT
  1160. //
  1161. // Modifies: pdvtdInfo
  1162. //
  1163. // Algorithm:
  1164. //
  1165. // History: 06-May-94 AlexT Created from DrewB's original functions
  1166. //
  1167. // Notes: Do we need to do any error checking on the strings?
  1168. //
  1169. //--------------------------------------------------------------------------
  1170. extern "C" HRESULT UtGetDvtd32Info(DVTARGETDEVICE const *pdvtd32, PDVTDINFO pdvtdInfo)
  1171. {
  1172. LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd32Info (%p, %p)\n",
  1173. NULL, pdvtd32, pdvtdInfo));
  1174. DEVMODEW *pdm32;
  1175. // Let's do some sanity checking on the incoming DVTARGETDEVICE
  1176. if (pdvtd32->tdSize < DVTD_MINSIZE)
  1177. {
  1178. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdSize\n"));
  1179. return(E_INVALIDARG);
  1180. }
  1181. pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
  1182. // Compute required size for Drv, Device, Port names
  1183. if (pdvtd32->tdDriverNameOffset != 0)
  1184. {
  1185. if (pdvtd32->tdDriverNameOffset > pdvtd32->tdSize ||
  1186. pdvtd32->tdDriverNameOffset < DVTD_MINSIZE)
  1187. {
  1188. // Offset can't be larger than size or fall within base
  1189. // structure
  1190. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDriverNameOffset\n"));
  1191. return(E_INVALIDARG);
  1192. }
  1193. pdvtdInfo->cchDrvName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1194. pdvtd32->tdDriverNameOffset)) + 1;
  1195. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
  1196. }
  1197. else
  1198. {
  1199. pdvtdInfo->cchDrvName = 0;
  1200. }
  1201. if (pdvtd32->tdDeviceNameOffset != 0)
  1202. {
  1203. if (pdvtd32->tdDeviceNameOffset > pdvtd32->tdSize ||
  1204. pdvtd32->tdDeviceNameOffset < DVTD_MINSIZE)
  1205. {
  1206. // Offset can't be larger than size or fall within base
  1207. // structure
  1208. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDeviceNameOffset\n"));
  1209. return(E_INVALIDARG);
  1210. }
  1211. pdvtdInfo->cchDevName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1212. pdvtd32->tdDeviceNameOffset)) + 1;
  1213. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
  1214. }
  1215. else
  1216. {
  1217. pdvtdInfo->cchDevName = 0;
  1218. }
  1219. if (pdvtd32->tdPortNameOffset != 0)
  1220. {
  1221. if (pdvtd32->tdPortNameOffset > pdvtd32->tdSize ||
  1222. pdvtd32->tdPortNameOffset < DVTD_MINSIZE)
  1223. {
  1224. // Offset can't be larger than size or fall within base
  1225. // structure
  1226. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdPortNameOffset\n"));
  1227. return(E_INVALIDARG);
  1228. }
  1229. pdvtdInfo->cchPortName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1230. pdvtd32->tdPortNameOffset)) + 1;
  1231. pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
  1232. }
  1233. else
  1234. {
  1235. pdvtdInfo->cchPortName = 0;
  1236. }
  1237. // Now compute the space needed for the DEVMODE
  1238. if (pdvtd32->tdExtDevmodeOffset != 0)
  1239. {
  1240. if (pdvtd32->tdExtDevmodeOffset > pdvtd32->tdSize ||
  1241. pdvtd32->tdExtDevmodeOffset < DVTD_MINSIZE)
  1242. {
  1243. // Offset can't be larger than size or fall within base
  1244. // structure
  1245. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdExtDevmodeOffset\n"));
  1246. return(E_INVALIDARG);
  1247. }
  1248. // The DEVMODEA structure needs to be DWORD aligned, so here we make
  1249. // sure cbConvertSize (which will be the beginning of DEVMODEA) is
  1250. // DWORD aligned
  1251. pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
  1252. pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
  1253. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1254. // We start with a basic DEVMODEA
  1255. pdvtdInfo->cbConvertSize += sizeof(DEVMODEA);
  1256. if (pdm32->dmSize > sizeof(DEVMODEW))
  1257. {
  1258. // The input DEVMODEW is larger than a standard DEVMODEW, so
  1259. // add space for the extra amount
  1260. pdvtdInfo->cbConvertSize += pdm32->dmSize - sizeof(DEVMODEW);
  1261. }
  1262. // Finally we account for the extra driver data
  1263. pdvtdInfo->cbConvertSize += pdm32->dmDriverExtra;
  1264. }
  1265. LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd32Info (%lx) [%ld]\n",
  1266. NULL, S_OK, pdvtdInfo->cbConvertSize));
  1267. return(S_OK);
  1268. }
  1269. //+-------------------------------------------------------------------------
  1270. //
  1271. // Function: UtConvertDvtd32toDvtd16
  1272. //
  1273. // Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
  1274. // DVTARGETDEVICE
  1275. //
  1276. // Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
  1277. // [pdvtdInfo] -- pointer to DVDT_INFO block
  1278. // [pdvtd16] -- pointer to UNICODE DVTARGETDEVICE
  1279. //
  1280. // Requires: pdvtdInfo must have been filled in by a previous call to
  1281. // UtGetDvtd32Info
  1282. //
  1283. // pdvtd16 must be at least pdvtdInfo->cbSizeConvert bytes long
  1284. //
  1285. // Returns: HRESULT
  1286. //
  1287. // Modifies: pdvtd16
  1288. //
  1289. // Algorithm:
  1290. //
  1291. // History: 06-May-94 AlexT Created from DrewB's original functions
  1292. //
  1293. // Notes: Do we need to do any error checking on the strings?
  1294. //
  1295. // On Chicago we'll have to provide helper code to do this
  1296. // translation
  1297. //
  1298. //--------------------------------------------------------------------------
  1299. extern "C" HRESULT UtConvertDvtd32toDvtd16(DVTARGETDEVICE const *pdvtd32,
  1300. DVTDINFO const *pdvtdInfo,
  1301. DVTARGETDEVICE UNALIGNED *pdvtd16)
  1302. {
  1303. LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd32toDvtd16 (%p, %p, %p)\n",
  1304. NULL, pdvtd32, pdvtdInfo, pdvtd16));
  1305. #if DBG==1
  1306. {
  1307. // Verify the passed in pdvtdInfo is what we expect
  1308. DVTDINFO dbgDvtdInfo;
  1309. Assert(UtGetDvtd32Info(pdvtd32, &dbgDvtdInfo) == S_OK);
  1310. Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
  1311. }
  1312. #endif
  1313. HRESULT hr = S_OK;
  1314. USHORT cbOffset;
  1315. int cbWritten;
  1316. DEVMODEA UNALIGNED *pdm16;
  1317. DEVMODEW *pdm32;
  1318. UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  1319. memset(pdvtd16, 0, pdvtdInfo->cbConvertSize);
  1320. cbOffset = UT_DVTARGETDEVICE_SIZE;
  1321. if (pdvtdInfo->cchDrvName != 0)
  1322. {
  1323. pdvtd16->tdDriverNameOffset = cbOffset;
  1324. cbWritten = WideCharToMultiByte(CP_ACP, 0,
  1325. (WCHAR *)((BYTE *)pdvtd32 +
  1326. pdvtd32->tdDriverNameOffset),
  1327. pdvtdInfo->cchDrvName,
  1328. (char *)pdvtd16 + pdvtd16->tdDriverNameOffset,
  1329. pdvtdInfo->cchDrvName * sizeof(WCHAR),
  1330. NULL, NULL);
  1331. if (0 == cbWritten)
  1332. {
  1333. hr = E_UNEXPECTED;
  1334. goto ErrRtn;
  1335. }
  1336. cbOffset += (USHORT) cbWritten;
  1337. }
  1338. if (pdvtdInfo->cchDevName != 0)
  1339. {
  1340. pdvtd16->tdDeviceNameOffset = cbOffset;
  1341. cbWritten = WideCharToMultiByte(
  1342. nCodePage, 0,
  1343. (WCHAR *)((BYTE *)pdvtd32 +
  1344. pdvtd32->tdDeviceNameOffset),
  1345. pdvtdInfo->cchDevName,
  1346. (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
  1347. pdvtdInfo->cchDevName * sizeof(WCHAR),
  1348. NULL, NULL);
  1349. if (0 == cbWritten)
  1350. {
  1351. hr = E_UNEXPECTED;
  1352. goto ErrRtn;
  1353. }
  1354. cbOffset += (USHORT) cbWritten;
  1355. }
  1356. if (pdvtdInfo->cchPortName != 0)
  1357. {
  1358. pdvtd16->tdPortNameOffset = cbOffset;
  1359. cbWritten = WideCharToMultiByte(nCodePage, 0,
  1360. (WCHAR *)((BYTE *)pdvtd32 +
  1361. pdvtd32->tdPortNameOffset),
  1362. pdvtdInfo->cchPortName,
  1363. (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
  1364. pdvtdInfo->cchPortName * sizeof(WCHAR),
  1365. NULL, NULL);
  1366. if (0 == cbWritten)
  1367. {
  1368. hr = E_UNEXPECTED;
  1369. goto ErrRtn;
  1370. }
  1371. cbOffset += (USHORT) cbWritten;
  1372. }
  1373. if (pdvtd32->tdExtDevmodeOffset != 0)
  1374. {
  1375. // Make sure DEVMODEA will be DWORD aligned
  1376. cbOffset += (sizeof(DWORD) - 1);
  1377. cbOffset &= ~(sizeof(DWORD) - 1);
  1378. pdvtd16->tdExtDevmodeOffset = cbOffset;
  1379. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
  1380. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1381. // The incoming DEVMODEW can have one of the following two forms:
  1382. //
  1383. // 1) 32 WCHARs for dmDeviceName
  1384. // m bytes worth of fixed size data (where m <= 38)
  1385. // n bytes of dmDriverExtra data
  1386. //
  1387. // and dmSize will be 64+m
  1388. //
  1389. // 2) 32 WCHARs for dmDeviceName
  1390. // 38 bytes worth of fixed size data
  1391. // 32 WCHARs for dmFormName
  1392. // m additional bytes of fixed size data
  1393. // n bytes of dmDriverExtra data
  1394. //
  1395. // and dmSize will be 64 + 38 + 64 + m
  1396. //
  1397. // We have to be careful to translate the dmFormName string, if it
  1398. // exists
  1399. // Need to attempt to copy the entire buffer since old UI lib does a memcmp to verify if ptd's are equal
  1400. if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,CCHDEVICENAME,
  1401. (char *)pdm16->dmDeviceName, CCHDEVICENAME,
  1402. NULL, NULL) == 0)
  1403. {
  1404. // in DBCS case we can run out of pdm16->dmDeviceName buffer space
  1405. // Current Implementation of WideCharToMultiByte copies in what fit before error
  1406. // but in case this behavior changes copy again up to NULL char if error out above
  1407. if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,-1,
  1408. (char *)pdm16->dmDeviceName, CCHDEVICENAME,
  1409. NULL, NULL) == 0)
  1410. {
  1411. hr = E_UNEXPECTED;
  1412. goto ErrRtn;
  1413. }
  1414. }
  1415. // Now check to see if we have a dmFormName to translate
  1416. if (pdm32->dmSize <= FIELD_OFFSET(DEVMODEW, dmFormName))
  1417. {
  1418. // No dmFormName, just copy the remaining m bytes
  1419. memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
  1420. pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
  1421. }
  1422. else
  1423. {
  1424. // There is a dmFormName; copy the bytes between the names first
  1425. memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
  1426. FIELD_OFFSET(DEVMODEW, dmFormName) -
  1427. FIELD_OFFSET(DEVMODEW, dmSpecVersion));
  1428. // Now translate the dmFormName
  1429. if (WideCharToMultiByte(CP_ACP, 0,
  1430. pdm32->dmFormName, CCHFORMNAME,
  1431. (char *) pdm16->dmFormName, CCHFORMNAME,
  1432. NULL, NULL) == 0)
  1433. {
  1434. if (WideCharToMultiByte(CP_ACP, 0,
  1435. pdm32->dmFormName, -1,
  1436. (char *) pdm16->dmFormName, CCHFORMNAME,
  1437. NULL, NULL) == 0)
  1438. {
  1439. hr = E_UNEXPECTED;
  1440. goto ErrRtn;
  1441. }
  1442. }
  1443. // Now copy the remaining m bytes
  1444. if (pdm32->dmSize > FIELD_OFFSET(DEVMODEW, dmLogPixels))
  1445. {
  1446. memcpy(&pdm16->dmLogPixels, &pdm32->dmLogPixels,
  1447. pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
  1448. }
  1449. }
  1450. pdm16->dmSize = sizeof(DEVMODEA);
  1451. if (pdm32->dmSize > sizeof(DEVMODEW))
  1452. {
  1453. pdm16->dmSize += pdm32->dmSize - sizeof(DEVMODEW);
  1454. }
  1455. // Copy the extra driver bytes
  1456. memcpy(((BYTE*)pdm16) + pdm16->dmSize, ((BYTE*)pdm32) + pdm32->dmSize,
  1457. pdm32->dmDriverExtra);
  1458. cbOffset += pdm16->dmSize + pdm16->dmDriverExtra;
  1459. }
  1460. // Finally, set pdvtd16's size
  1461. pdvtd16->tdSize = cbOffset;
  1462. ErrRtn:
  1463. LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd32toDvtd16 (%lx)\n",
  1464. NULL, hr));
  1465. return hr;
  1466. }
  1467. //+-------------------------------------------------------------------------
  1468. //
  1469. // Function: UtGetUNICODEData, PRIVATE INTERNAL
  1470. //
  1471. // Synopsis: Given a string length, and two pointers (one ANSI, one
  1472. // OLESTR), returns the UNICODE version of whichever string
  1473. // is valid.
  1474. //
  1475. // Effects: Memory is allocated on the caller's pointer for new OLESTR
  1476. //
  1477. // Arguments: [ulLength] -- length of string in CHARACTERS (not bytes)
  1478. // (including terminator)
  1479. // [szANSI] -- candidate ANSI string
  1480. // [szOLESTR] -- candidate OLESTR string
  1481. // [pstr] -- OLESTR OUT parameter
  1482. //
  1483. // Returns: NOERROR on success
  1484. // E_OUTOFMEMORY on allocation failure
  1485. // E_ANSITOUNICODE if ANSI cannot be converted to UNICODE
  1486. //
  1487. // Algorithm: If szOLESTR is available, a simple copy is performed
  1488. // If szOLESTR is not available, szANSI is converted to UNICODE
  1489. // and the result is copied.
  1490. //
  1491. // History: dd-mmm-yy Author Comment
  1492. // 08-Mar-94 davepl Created
  1493. //
  1494. // Notes: Only one of the two input strings (ANSI or UNICODE) should
  1495. // be set on entry.
  1496. //
  1497. //--------------------------------------------------------------------------
  1498. INTERNAL UtGetUNICODEData
  1499. ( ULONG ulLength,
  1500. LPSTR szANSI,
  1501. LPOLESTR szOLESTR,
  1502. LPOLESTR * pstr )
  1503. {
  1504. VDATEHEAP();
  1505. // This fn is only called when one of the input strings
  1506. // has valid data... assert the impossible.
  1507. Win4Assert(pstr); // must have an out string
  1508. Win4Assert(ulLength); // must have a non-zero length
  1509. Win4Assert(szANSI || szOLESTR); // must have at least one source string
  1510. // If neither the ANSI nor the OLESTR version has data,
  1511. // there is nothing to return.
  1512. #if 0
  1513. // This is no better than what was there!!!
  1514. *pstr = NULL;
  1515. if (szOLESTR) {
  1516. *pstr = (LPOLESTR) UtDupPtr(szOLESTR, ulLength * sizeof(OLECHAR));
  1517. }
  1518. else if (szANSI) {
  1519. if (FALSE == MultiByteToWideChar(CP_ACP, // Code page ANSI
  1520. 0, // Flags (none)
  1521. szANSI, // Source ANSI str
  1522. ulLength, // length of string
  1523. *pstr, // Dest UNICODE buffer
  1524. ulLength * sizeof(OLECHAR) )) // size of UNICODE buffer
  1525. {
  1526. PubMemFree(*pstr);
  1527. *pstr = NULL;
  1528. return ResultFromScode(E_UNSPEC);
  1529. }
  1530. }
  1531. if (NULL == *pstr)
  1532. {
  1533. return ResultFromScode(E_OUTOFMEMORY);
  1534. }
  1535. #else
  1536. if (!(szANSI || szOLESTR))
  1537. {
  1538. *pstr = NULL;
  1539. }
  1540. // Allocate memory for the UNICODE return string
  1541. *pstr = (LPOLESTR) PubMemAlloc(ulLength * sizeof(OLECHAR));
  1542. if (NULL == *pstr)
  1543. {
  1544. return ResultFromScode(E_OUTOFMEMORY);
  1545. }
  1546. // Trivial case: we already have UNICODE, just copy it
  1547. if (szOLESTR)
  1548. {
  1549. _xstrcpy(*pstr, szOLESTR);
  1550. return(NOERROR);
  1551. }
  1552. // Otherwise, we have to convert the ANSI string to UNICODE
  1553. // and return that.
  1554. else
  1555. {
  1556. if (FALSE == MultiByteToWideChar(CP_ACP, // Code page ANSI
  1557. 0, // Flags (none)
  1558. szANSI, // Source ANSI str
  1559. ulLength, // length of string
  1560. *pstr, // Dest UNICODE buffer
  1561. ulLength * sizeof(OLECHAR) )) // size of UNICODE buffer
  1562. {
  1563. PubMemFree(*pstr);
  1564. *pstr = NULL;
  1565. return ResultFromScode(E_UNSPEC);
  1566. }
  1567. }
  1568. return NOERROR;
  1569. #endif
  1570. }
  1571. //+-------------------------------------------------------------------------
  1572. //
  1573. // Function: UtPutUNICODEData, PRIVATE INTERNAL
  1574. //
  1575. // Synopsis: Given an OLESTR and two possible buffer pointer, one ANSI
  1576. // and the other OLESTR, this fn tries to convert the string
  1577. // down to ANSI. If it succeeds, it allocates memory on the
  1578. // ANSI ptr for the result. If it fails, it allocates memory
  1579. // on the UNICODE ptr and copies the input string over. The
  1580. // length of the final result (ANSI or UNICODE) is returned
  1581. // in dwResultLen.
  1582. //
  1583. // Arguments: [ulLength] -- input length of OLESTR str
  1584. // NB!!!! this value must include the
  1585. // null terminator character.
  1586. // [str] -- the OLESTR to store
  1587. // [pszANSI] -- candidate ANSI str ptr
  1588. // [pszOLESTR] -- candidate OLESTR str ptr. May be NULL,
  1589. // in which case no copy is made of the
  1590. // original string if the ANSI conversion
  1591. // fails.
  1592. // [pdwResultLen] -- where to store the length of result. This
  1593. // length includes the terminating NULL.
  1594. // Length is in CHARACTERS.
  1595. //
  1596. // Returns: NOERROR on success
  1597. // E_OUTOFMEMORY on allocation failure
  1598. // E_FAIL can't convert ANSI string and no
  1599. // pszOLESTR is NULL
  1600. //
  1601. // History: dd-mmm-yy Author Comment
  1602. // 10-Jun-94 alexgo allow pszOLESTR to be NULL
  1603. // 08-Mar-94 davepl Created
  1604. //
  1605. //--------------------------------------------------------------------------
  1606. // this function is poorly coded. But, it looks like it only gets called when a 1.0
  1607. // clip format is needed. That is not very often!
  1608. INTERNAL UtPutUNICODEData
  1609. ( ULONG ulLength,
  1610. LPOLESTR str,
  1611. LPSTR * pszANSI,
  1612. LPOLESTR * pszOLESTR,
  1613. DWORD * pdwResultLen )
  1614. {
  1615. VDATEHEAP();
  1616. Win4Assert(pszANSI);
  1617. Win4Assert(str);
  1618. Win4Assert(pdwResultLen);
  1619. Win4Assert(ulLength);
  1620. // Free any strings currently attached to these pointers; if we wind
  1621. // up setting one here, we can't leave the other valid.
  1622. if (*pszANSI)
  1623. {
  1624. PubMemFree(*pszANSI);
  1625. *pszANSI = NULL;
  1626. }
  1627. if (pszOLESTR && *pszOLESTR)
  1628. {
  1629. PubMemFree(*pszOLESTR);
  1630. *pszOLESTR = NULL;
  1631. }
  1632. // Create a working buffer for UNICODE->ANSI conversion
  1633. LPSTR szANSITEMP = (LPSTR) PubMemAlloc((ulLength+1) * 2);
  1634. if (NULL == szANSITEMP)
  1635. {
  1636. return ResultFromScode(E_OUTOFMEMORY);
  1637. }
  1638. // Try to convert the UNICODE down to ANSI. If it succeeds,
  1639. // we just copy the result to the ANSI dest. If it fails,
  1640. // we copy the UNICODE version direct to the UNICODE dest.
  1641. LPCSTR pDefault = "?";
  1642. BOOL fUseDef = 0;
  1643. if (FALSE == WideCharToMultiByte (CP_ACP,
  1644. 0,
  1645. str,
  1646. ulLength,
  1647. szANSITEMP,
  1648. (ulLength + 1) * 2,
  1649. pDefault,
  1650. &fUseDef) || fUseDef )
  1651. {
  1652. // UNICODE->ANSI failed!
  1653. // Won't be needing the ANSI buffer anymore...
  1654. PubMemFree(szANSITEMP);
  1655. if( pszOLESTR )
  1656. {
  1657. *pszANSI = NULL;
  1658. *pszOLESTR = (LPOLESTR) PubMemAlloc((ulLength + 1) * sizeof(OLECHAR));
  1659. if (NULL == *pszOLESTR)
  1660. {
  1661. *pdwResultLen = 0;
  1662. return ResultFromScode(E_OUTOFMEMORY);
  1663. }
  1664. // Move the UNICODE source to UNICODE dest
  1665. _xstrcpy(*pszOLESTR, str);
  1666. *pdwResultLen = _xstrlen(str) + 1;
  1667. // That's it... return success
  1668. return(NOERROR);
  1669. }
  1670. else
  1671. {
  1672. return ResultFromScode(E_FAIL);
  1673. }
  1674. }
  1675. // This code path is taken when the conversion to ANSI was
  1676. // successful. We copy the ANSI result to the ANSI dest.
  1677. if( pszOLESTR )
  1678. {
  1679. *pszOLESTR = NULL;
  1680. }
  1681. *pdwResultLen = strlen(szANSITEMP) + 1;
  1682. *pszANSI = (LPSTR) PubMemAlloc(*pdwResultLen);
  1683. if (NULL == *pszANSI)
  1684. {
  1685. *pdwResultLen = 0;
  1686. return ResultFromScode(E_OUTOFMEMORY);
  1687. }
  1688. strcpy(*pszANSI, szANSITEMP);
  1689. PubMemFree(szANSITEMP);
  1690. return(NOERROR);
  1691. }
  1692. //+-------------------------------------------------------------------------
  1693. //
  1694. // Method: CSafeRefCount::SafeRefCount()
  1695. //
  1696. // Purpose: CSafeRefCount implements reference counting rules for objects.
  1697. // It keeps track of reference count and zombie state.
  1698. // It helps object manage their liveness properly.
  1699. //
  1700. // History: dd-mmm-yy Author Comment
  1701. // 16-Jan-97 Gopalk Rewritten to handle aggregation
  1702. //
  1703. //--------------------------------------------------------------------------
  1704. ULONG CSafeRefCount::SafeRelease()
  1705. {
  1706. ULONG cRefs;
  1707. // Decrement ref count
  1708. cRefs = InterlockedDecrement((LONG *) &m_cRefs);
  1709. // Check if this is the last release
  1710. if(cRefs == 0) {
  1711. // As this function is reentrant on the current
  1712. // thread, gaurd against double destruction
  1713. if(!m_fInDelete) {
  1714. // There are no race conditions here
  1715. // Mark object as in destructor
  1716. m_fInDelete = TRUE;
  1717. // Here is the need for the destructor to be virtual
  1718. delete this;
  1719. }
  1720. }
  1721. return cRefs;
  1722. }
  1723. //+-------------------------------------------------------------------------
  1724. //
  1725. // Method: CRefExportCount::SafeRelease
  1726. //
  1727. // Purpose: CRefExportCount implements reference counting rules for server
  1728. // objects that export their nested objects on behalf of their
  1729. // clients like DEFHANDLER abd CACHE. It keeps track of
  1730. // reference count, export count, zombie state, etc.
  1731. // It helps object manage their shutdown logic properly.
  1732. //
  1733. // History: dd-mmm-yy Author Comment
  1734. // 16-Jan-97 Gopalk Creation
  1735. //
  1736. //--------------------------------------------------------------------------
  1737. ULONG CRefExportCount::SafeRelease()
  1738. {
  1739. ULONG cRefs;
  1740. // Decrement ref count
  1741. cRefs = InterlockedDecrement((LONG *) &m_cRefs);
  1742. // Check if ref count has become zero
  1743. if(cRefs == 0) {
  1744. // As this function is reentrant on the current
  1745. // thread, gaurd against double destruction
  1746. if(!m_IsZombie) {
  1747. // There are no race conditions here
  1748. // Mark object as a zombie
  1749. m_IsZombie = TRUE;
  1750. // Call cleanup function while destruction is not allowed
  1751. CleanupFn();
  1752. // Allow destruction
  1753. InterlockedExchange((LONG *) &m_Status, KILL);
  1754. // Check for any exported objects
  1755. if(m_cExportCount == 0) {
  1756. // Gaurd against double destruction
  1757. if(InterlockedExchange((LONG *) &m_Status, DEAD) == KILL) {
  1758. // Here is the need for the destructor to be virtual
  1759. delete this;
  1760. }
  1761. }
  1762. }
  1763. }
  1764. return cRefs;
  1765. }
  1766. //+-------------------------------------------------------------------------
  1767. //
  1768. // Method: CRefExportCount::DecrementExportCount
  1769. //
  1770. // Purpose: CRefExportCount implements reference counting rules for server
  1771. // objects that export their nested objects on behalf of their
  1772. // clients like DEFHANDLER abd CACHE. It keeps track of
  1773. // reference count, export count, zombie state, etc.
  1774. // It helps object manage their shutdown logic properly.
  1775. //
  1776. // History: dd-mmm-yy Author Comment
  1777. // 16-Jan-97 Gopalk Creation
  1778. //
  1779. //--------------------------------------------------------------------------
  1780. ULONG CRefExportCount::DecrementExportCount()
  1781. {
  1782. ULONG cExportCount;
  1783. // Decrement export count
  1784. cExportCount = InterlockedDecrement((LONG *) &m_cExportCount);
  1785. // Check if the export count has become zero
  1786. if(cExportCount == 0) {
  1787. // Check if destruction is allowed
  1788. if(m_Status == KILL) {
  1789. // Gaurd against double destruction
  1790. if(InterlockedExchange((LONG *) &m_Status, DEAD) == KILL) {
  1791. // Here is the need for the destructor to be virtual
  1792. delete this;
  1793. }
  1794. }
  1795. }
  1796. return cExportCount;
  1797. }
  1798. //+-------------------------------------------------------------------------
  1799. //
  1800. // Member: CThreadCheck::VerifyThreadId
  1801. //
  1802. // Synopsis: makes sure that the calling thread is the same as the thread
  1803. // the object was created on if the threading model is *not*
  1804. // free threading.
  1805. //
  1806. // Effects:
  1807. //
  1808. // Arguments: none
  1809. //
  1810. // Requires:
  1811. //
  1812. // Returns: TRUE/FALSE
  1813. //
  1814. // Signals:
  1815. //
  1816. // Modifies:
  1817. //
  1818. // Derivation:
  1819. //
  1820. // Algorithm:
  1821. //
  1822. // History: dd-mmm-yy Author Comment
  1823. // 21-Nov-94 alexgo author
  1824. //
  1825. // Notes:
  1826. //
  1827. //--------------------------------------------------------------------------
  1828. BOOL CThreadCheck::VerifyThreadId( void )
  1829. {
  1830. if( m_tid == GetCurrentThreadId() )
  1831. {
  1832. return TRUE;
  1833. }
  1834. else
  1835. {
  1836. LEDebugOut((DEB_ERROR, "ERROR!: Called on thread %lx, should be"
  1837. " %lx \n", GetCurrentThreadId(), m_tid));
  1838. return FALSE;
  1839. }
  1840. }
  1841. //+-------------------------------------------------------------------------
  1842. //
  1843. // Member: CThreadCheck::Dump, public (_DEBUG only)
  1844. //
  1845. // Synopsis: return a string containing the contents of the data members
  1846. //
  1847. // Effects:
  1848. //
  1849. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1850. // [ulFlag] - flag determining prefix of all newlines of the
  1851. // out character array (default is 0 - no prefix)
  1852. // [nIndentLevel] - will add a indent prefix after the other prefix
  1853. // for ALL newlines (including those with no prefix)
  1854. //
  1855. // Requires:
  1856. //
  1857. // Returns: HRESULT
  1858. //
  1859. // Signals:
  1860. //
  1861. // Modifies: [ppszDump] - argument
  1862. //
  1863. // Derivation:
  1864. //
  1865. // Algorithm: use dbgstream to create a string containing information on the
  1866. // content of data structures
  1867. //
  1868. // History: dd-mmm-yy Author Comment
  1869. // 20-Jan-95 t-ScottH author
  1870. //
  1871. // Notes:
  1872. //
  1873. //--------------------------------------------------------------------------
  1874. #ifdef _DEBUG
  1875. HRESULT CThreadCheck::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1876. {
  1877. int i;
  1878. char *pszPrefix;
  1879. dbgstream dstrPrefix;
  1880. dbgstream dstrDump;
  1881. // determine prefix of newlines
  1882. if ( ulFlag & DEB_VERBOSE )
  1883. {
  1884. dstrPrefix << this << " _VB ";
  1885. }
  1886. // determine indentation prefix for all newlines
  1887. for (i = 0; i < nIndentLevel; i++)
  1888. {
  1889. dstrPrefix << DUMPTAB;
  1890. }
  1891. pszPrefix = dstrPrefix.str();
  1892. // put data members in stream
  1893. dstrDump << pszPrefix << "Thread ID = " << m_tid << endl;
  1894. // clean up and provide pointer to character array
  1895. *ppszDump = dstrDump.str();
  1896. if (*ppszDump == NULL)
  1897. {
  1898. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1899. }
  1900. CoTaskMemFree(pszPrefix);
  1901. return NOERROR;
  1902. }
  1903. #endif //_DEBUG
  1904. //+-------------------------------------------------------------------------
  1905. //
  1906. // Function: DumpCThreadCheck, public (_DEBUG only)
  1907. //
  1908. // Synopsis: calls the CThreadCheck::Dump method, takes care of errors and
  1909. // returns the zero terminated string
  1910. //
  1911. // Effects:
  1912. //
  1913. // Arguments: [pTC] - pointer to CThreadCheck
  1914. // [ulFlag] - flag determining prefix of all newlines of the
  1915. // out character array (default is 0 - no prefix)
  1916. // [nIndentLevel] - will add a indent prefix after the other prefix
  1917. // for ALL newlines (including those with no prefix)
  1918. //
  1919. // Requires:
  1920. //
  1921. // Returns: character array of structure dump or error (null terminated)
  1922. //
  1923. // Signals:
  1924. //
  1925. // Modifies:
  1926. //
  1927. // Algorithm:
  1928. //
  1929. // History: dd-mmm-yy Author Comment
  1930. // 20-Jan-95 t-ScottH author
  1931. //
  1932. // Notes:
  1933. //
  1934. //--------------------------------------------------------------------------
  1935. #ifdef _DEBUG
  1936. char *DumpCThreadCheck(CThreadCheck *pTC, ULONG ulFlag, int nIndentLevel)
  1937. {
  1938. char *pszDump;
  1939. HRESULT hresult;
  1940. if (pTC == NULL)
  1941. {
  1942. return UtDupStringA(szDumpBadPtr);
  1943. }
  1944. hresult = pTC->Dump( &pszDump, ulFlag, nIndentLevel);
  1945. if (hresult != NOERROR)
  1946. {
  1947. CoTaskMemFree(pszDump);
  1948. return DumpHRESULT(hresult);
  1949. }
  1950. return pszDump;
  1951. }
  1952. #endif // _DEBUG