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.

2285 lines
66 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. (ULONG) 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. DWORD dwRet = 0;
  540. VDATEHEAP();
  541. LEDebugOut((DEB_ITRACE, "%p _IN UtGetTempFilename ( \"%ws\" , "
  542. "\"%ws\")\n", NULL, pszPrefix, pszTempName));
  543. if( (dwRet = GetTempPath(MAX_PATH, szPath)) == 0)
  544. {
  545. UINT uiRet = 0;
  546. LEDebugOut((DEB_WARN, "WARNING: GetTempPath failed!\n"));
  547. if( (uiRet=GetWindowsDirectory(szPath, MAX_PATH)) == 0 )
  548. {
  549. LEDebugOut((DEB_WARN, "WARNING: GetWindowsDirectory"
  550. " failed!!\n"));
  551. hresult = ResultFromScode(E_FAIL);
  552. goto errRtn;
  553. }
  554. else if (uiRet > MAX_PATH)
  555. {
  556. LEDebugOut((DEB_WARN, "WARNING: WindowsDir longer than MAX_PATH!\n"));
  557. hresult = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  558. goto errRtn;
  559. }
  560. }
  561. else if (dwRet > MAX_PATH)
  562. {
  563. LEDebugOut((DEB_WARN, "WARNING: TempDir longer than MAX_PATH!\n"));
  564. hresult = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  565. goto errRtn;
  566. }
  567. if( !GetTempFileName( szPath, pszPrefix, 0, pszTempName ) )
  568. {
  569. LEDebugOut((DEB_WARN, "WARNING: GetTempFileName failed!!\n"));
  570. hresult = ResultFromScode(E_FAIL);
  571. }
  572. errRtn:
  573. LEDebugOut((DEB_ITRACE, "%p OUT UtGetTempFilename ( %lx ) "
  574. "[ \"%ws\" ]\n", NULL, hresult, pszTempName));
  575. return hresult;
  576. }
  577. //+----------------------------------------------------------------------------
  578. //
  579. // Function:
  580. // UtHGLOBALtoStm, internal
  581. //
  582. // Synopsis:
  583. // Write the contents of an HGLOBAL to a stream
  584. //
  585. // Arguments:
  586. // [hdata] -- handle to the data to write out
  587. // [dwSize] -- size of the data to write out
  588. // [pstm] -- stream to write the data out to; on exit, the
  589. // stream is positioned after the written data
  590. //
  591. // Returns:
  592. // HRESULT
  593. //
  594. // Notes:
  595. //
  596. // History:
  597. // 04/10/94 - AlexGo - added call tracing, moved from convert.cpp
  598. // to utils.cpp, misc improvements.
  599. // 11/30/93 - ChrisWe - file inspection and cleanup
  600. //
  601. //-----------------------------------------------------------------------------
  602. HRESULT UtHGLOBALtoStm(HGLOBAL hGlobalSrc, DWORD dwSize, LPSTREAM pstm)
  603. {
  604. HRESULT hresult = NOERROR;
  605. void * lpdata;
  606. ULONG cbWritten;
  607. VDATEHEAP();
  608. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStm ( %lx , %lu , %p )\n",
  609. NULL, hGlobalSrc, dwSize, pstm));
  610. lpdata = GlobalLock(hGlobalSrc);
  611. if (lpdata)
  612. {
  613. hresult = pstm->Write(lpdata, dwSize, &cbWritten);
  614. // if we didn't write enough data, then it's an error
  615. // condition for us.
  616. if( hresult == NOERROR && cbWritten != dwSize )
  617. {
  618. hresult = ResultFromScode(E_FAIL);
  619. }
  620. if( hresult == NOERROR )
  621. {
  622. // this call isn't strictly necessary, but may
  623. // be useful for compacting the size of presentations
  624. // stored on disk (when called by the presentation
  625. // code)
  626. hresult = StSetSize(pstm, 0, TRUE);
  627. }
  628. GlobalUnlock(hGlobalSrc);
  629. }
  630. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStm ( %lx )\n", NULL,
  631. hresult));
  632. return hresult;
  633. }
  634. //+-------------------------------------------------------------------------
  635. //
  636. // Function: UtHGLOBALtoHGLOBAL, internal
  637. //
  638. // Synopsis: Copies the source HGLOBAL into the target HGLOBAL
  639. //
  640. // Effects:
  641. //
  642. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  643. // [dwSize] -- the number of bytes to copy
  644. // [hGlobalTgt] -- the target HGLOBAL
  645. //
  646. // Requires:
  647. //
  648. // Returns: HRESULT
  649. //
  650. // Signals:
  651. //
  652. // Modifies:
  653. //
  654. // Algorithm:
  655. //
  656. // History: dd-mmm-yy Author Comment
  657. // 10-Apr-94 alexgo author
  658. //
  659. // Notes: this function will fail if the target hglobal is not large
  660. // enough
  661. //
  662. //--------------------------------------------------------------------------
  663. HRESULT UtHGLOBALtoHGLOBAL( HGLOBAL hGlobalSrc, DWORD dwSize,
  664. HGLOBAL hGlobalTgt)
  665. {
  666. DWORD cbTarget;
  667. void * pvSrc;
  668. void * pvTgt;
  669. HRESULT hresult = ResultFromScode(E_OUTOFMEMORY);
  670. VDATEHEAP();
  671. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoHGLOBAL ( %lx , %lu , "
  672. "%lx )\n", NULL, hGlobalSrc, dwSize, hGlobalTgt));
  673. cbTarget = (ULONG) GlobalSize(hGlobalTgt);
  674. if( cbTarget == 0 || cbTarget < dwSize )
  675. {
  676. hresult = ResultFromScode(E_FAIL);
  677. goto errRtn;
  678. }
  679. pvSrc = GlobalLock(hGlobalSrc);
  680. if( pvSrc )
  681. {
  682. pvTgt = GlobalLock(hGlobalTgt);
  683. if( pvTgt )
  684. {
  685. _xmemcpy( pvTgt, pvSrc, dwSize);
  686. GlobalUnlock(hGlobalTgt);
  687. hresult = NOERROR;
  688. }
  689. GlobalUnlock(hGlobalSrc);
  690. }
  691. errRtn:
  692. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoHGLOBAL ( %lx )\n",
  693. NULL, hresult));
  694. return hresult;
  695. }
  696. //+-------------------------------------------------------------------------
  697. //
  698. // Function: UtHGLOBALtoStorage, internal
  699. //
  700. // Synopsis: Copies the source HGLOBAL into the target storage
  701. //
  702. // Effects:
  703. //
  704. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  705. // [pStgTgt] -- the target storage
  706. //
  707. // Requires:
  708. //
  709. // Returns: HRESULT
  710. //
  711. // Signals:
  712. //
  713. // Modifies:
  714. //
  715. // Algorithm:
  716. //
  717. // History: dd-mmm-yy Author Comment
  718. // 10-Apr-94 alexgo author
  719. //
  720. // Notes: this function will fail if the source HGLOBAL did not
  721. // originally have a storage layered on top of it.
  722. //
  723. //--------------------------------------------------------------------------
  724. HRESULT UtHGLOBALtoStorage( HGLOBAL hGlobalSrc, IStorage *pStgTgt)
  725. {
  726. HRESULT hresult;
  727. ILockBytes * pLockBytes = NULL;
  728. IStorage * pStgSrc;
  729. ULONG cRefs;
  730. VDATEHEAP();
  731. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoStroage ( %lx , %p )"
  732. "\n", NULL, hGlobalSrc, pStgTgt));
  733. hresult = CreateILockBytesOnHGlobal(hGlobalSrc,
  734. FALSE /*fDeleteOnRelease*/, &pLockBytes);
  735. if( hresult != NOERROR )
  736. {
  737. goto errRtn;
  738. }
  739. // now we make sure that the hglobal really has a storage
  740. // in it
  741. if( StgIsStorageILockBytes(pLockBytes) != NOERROR )
  742. {
  743. hresult = ResultFromScode(E_FAIL);
  744. goto errRtn;
  745. }
  746. hresult = StgOpenStorageOnILockBytes( pLockBytes, NULL,
  747. STGM_SALL, NULL, 0, &pStgSrc);
  748. if( hresult == NOERROR )
  749. {
  750. hresult = pStgSrc->CopyTo( 0, NULL, NULL, pStgTgt);
  751. // no matter what the result, we want to free the
  752. // source storage
  753. pStgSrc->Release();
  754. }
  755. errRtn:
  756. if( pLockBytes )
  757. {
  758. cRefs = pLockBytes->Release();
  759. Assert(cRefs == 0);
  760. }
  761. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoStorage ( %lx ) "
  762. "[ %p ]\n", NULL, hresult));
  763. return hresult;
  764. }
  765. //+-------------------------------------------------------------------------
  766. //
  767. // Function: UtHGLOBALtoFile, internal
  768. //
  769. // Synopsis: Copies the source HGLOBAL into the target file
  770. //
  771. // Effects:
  772. //
  773. // Arguments: [hGlobalSrc] -- the source HGLOBAL
  774. // [dwSize] -- the number of bytes to copy
  775. // [pszFileName] -- the target file
  776. //
  777. // Requires:
  778. //
  779. // Returns: HRESULT
  780. //
  781. // Signals:
  782. //
  783. // Modifies:
  784. //
  785. // Algorithm:
  786. //
  787. // History: dd-mmm-yy Author Comment
  788. // 10-Apr-94 alexgo author
  789. //
  790. // Notes: if the file already exists, we simply append to it
  791. //
  792. //--------------------------------------------------------------------------
  793. HRESULT UtHGLOBALtoFile( HGLOBAL hGlobalSrc, DWORD dwSize,
  794. LPCOLESTR pszFileName)
  795. {
  796. HRESULT hresult;
  797. HANDLE hFile;
  798. void * pvSrc;
  799. DWORD cbWritten;
  800. VDATEHEAP();
  801. LEDebugOut((DEB_ITRACE, "%p _IN UtHGLOBALtoFile ( %lx , %lu , "
  802. "\"%ws\" )\n", NULL, hGlobalSrc, dwSize, pszFileName));
  803. hresult = ResultFromScode(E_NOTIMPL);
  804. (void)hFile;
  805. (void)pvSrc;
  806. (void)cbWritten;
  807. // this doesn't compile for chicago [, but we don't need this anyway]
  808. #ifdef LATER
  809. pvSrc = GlobalLock(hGlobalSrc);
  810. if( !pvSrc )
  811. {
  812. hresult = ResultFromScode(E_OUTOFMEMORY);
  813. goto errRtn;
  814. }
  815. // open the file for append, creating if it doesn't already exist.
  816. hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL,
  817. OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
  818. if( hFile != INVALID_HANDLE_VALUE )
  819. {
  820. if( !WriteFile( hFile, pvSrc, dwSize, &cbWritten, NULL) )
  821. {
  822. LEDebugOut((DEB_WARN, "WARNING: WriteFile failed!\n"));
  823. hresult = HRESULT_FROM_WIN32(GetLastError());
  824. }
  825. if( cbWritten != dwSize && hresult == NOERROR )
  826. {
  827. // still an error if we didn't write all the bytes
  828. // we wanted
  829. hresult = ResultFromScode(E_FAIL);
  830. }
  831. if( !CloseHandle(hFile) )
  832. {
  833. AssertSz(0, "CloseFile failed! Should not happen!");
  834. // if there's no error yet, set the error
  835. if( hresult == NOERROR )
  836. {
  837. hresult = HRESULT_FROM_WIN32(GetLastError());
  838. }
  839. }
  840. }
  841. else
  842. {
  843. LEDebugOut((DEB_WARN, "WARNING: CreateFile failed!!\n"));
  844. hresult = HRESULT_FROM_WIN32(GetLastError());
  845. }
  846. GlobalUnlock(hGlobalSrc);
  847. errRtn:
  848. #endif // LATER
  849. LEDebugOut((DEB_ITRACE, "%p OUT UtHGLOBALtoFile ( %lx )\n", NULL,
  850. hresult));
  851. return hresult;
  852. }
  853. //+-------------------------------------------------------------------------
  854. //
  855. // Function: UtGetDvtd16Info
  856. //
  857. // Synopsis: Fills in pdvdtInfo
  858. //
  859. // Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
  860. // [pdvtdInfo] -- pointer to DVDT_INFO block
  861. //
  862. // Requires:
  863. //
  864. // Returns: HRESULT
  865. //
  866. // Modifies: pdvtdInfo
  867. //
  868. // Algorithm:
  869. //
  870. // History: 06-May-94 AlexT Created from DrewB's original functions
  871. // 10-Jul-94 AlexT Make sure DEVMODE ends up DWORD aligned
  872. //
  873. // Notes: Do we need to do any error checking on the strings?
  874. //
  875. //--------------------------------------------------------------------------
  876. // We can't use sizeof(DV_TARGETDEVICE) because MIDL keeps flipping back
  877. // and forth over whether to make the embedded array size 0 or size 1
  878. #define UT_DVTARGETDEVICE_SIZE (sizeof(DWORD) + sizeof(WORD) * 4)
  879. // tdSize td...Offset's
  880. #define DVTD_MINSIZE (sizeof(DWORD) + 4 * sizeof(WORD))
  881. extern "C" HRESULT UtGetDvtd16Info(DVTARGETDEVICE const UNALIGNED *pdvtd16,
  882. PDVTDINFO pdvtdInfo)
  883. {
  884. LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd16Info (%p, %p)\n",
  885. NULL, pdvtd16, pdvtdInfo));
  886. DEVMODEA UNALIGNED *pdm16;
  887. // Let's do some sanity checking on the incoming DVTARGETDEVICE
  888. if (pdvtd16->tdSize < DVTD_MINSIZE)
  889. {
  890. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdSize\n"));
  891. return(E_INVALIDARG);
  892. }
  893. // We need at least a DVTARGETDEVICE
  894. pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
  895. // Compute required size for Drv, Device, Port names
  896. if (pdvtd16->tdDriverNameOffset != 0)
  897. {
  898. if (pdvtd16->tdDriverNameOffset > pdvtd16->tdSize ||
  899. pdvtd16->tdDriverNameOffset < DVTD_MINSIZE)
  900. {
  901. // Offset can't be larger than size or fall within base
  902. // structure
  903. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDriverNameOffset\n"));
  904. return(E_INVALIDARG);
  905. }
  906. pdvtdInfo->cchDrvName = (UINT) strlen((char *)pdvtd16 +
  907. pdvtd16->tdDriverNameOffset) + 1;
  908. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
  909. }
  910. else
  911. {
  912. pdvtdInfo->cchDrvName = 0;
  913. }
  914. if (pdvtd16->tdDeviceNameOffset != 0)
  915. {
  916. if (pdvtd16->tdDeviceNameOffset > pdvtd16->tdSize ||
  917. pdvtd16->tdDeviceNameOffset < DVTD_MINSIZE)
  918. {
  919. // Offset can't be larger than size or fall within base
  920. // structure
  921. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdDeviceNameOffset\n"));
  922. return(E_INVALIDARG);
  923. }
  924. pdvtdInfo->cchDevName = (UINT) strlen((char *)pdvtd16 +
  925. pdvtd16->tdDeviceNameOffset) + 1;
  926. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
  927. }
  928. else
  929. {
  930. pdvtdInfo->cchDevName = 0;
  931. }
  932. if (pdvtd16->tdPortNameOffset != 0)
  933. {
  934. if (pdvtd16->tdPortNameOffset > pdvtd16->tdSize ||
  935. pdvtd16->tdPortNameOffset < DVTD_MINSIZE)
  936. {
  937. // Offset can't be larger than size or fall within base
  938. // structure
  939. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdPortNameOffset\n"));
  940. return(E_INVALIDARG);
  941. }
  942. pdvtdInfo->cchPortName = (UINT) strlen((char *)pdvtd16 +
  943. pdvtd16->tdPortNameOffset) + 1;
  944. pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
  945. }
  946. else
  947. {
  948. pdvtdInfo->cchPortName = 0;
  949. }
  950. if (pdvtd16->tdExtDevmodeOffset != 0)
  951. {
  952. if (pdvtd16->tdExtDevmodeOffset > pdvtd16->tdSize ||
  953. pdvtd16->tdExtDevmodeOffset < DVTD_MINSIZE)
  954. {
  955. // Offset can't be larger than size or fall within base
  956. // structure
  957. LEDebugOut((DEB_WARN, "UtGetDvtd16Info - bad pdvtd16->tdExtDevmodeOffset\n"));
  958. return(E_INVALIDARG);
  959. }
  960. // The DEVMODEW structure needs to be DWORD aligned, so here we make
  961. // sure cbConvertSize (which will be the beginning of DEVMODEW) is
  962. // DWORD aligned
  963. pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
  964. pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
  965. // Now compute the space needed for the DEVMODE
  966. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16 + pdvtd16->tdExtDevmodeOffset);
  967. // We start with a basic DEVMODEW
  968. pdvtdInfo->cbConvertSize += sizeof(DEVMODEW);
  969. if (pdm16->dmSize > sizeof(DEVMODEA))
  970. {
  971. // The input DEVMODEA is larger than a standard DEVMODEA, so
  972. // add space for the extra amount
  973. pdvtdInfo->cbConvertSize += pdm16->dmSize - sizeof(DEVMODEA);
  974. }
  975. // Finally we account for the extra driver data
  976. pdvtdInfo->cbConvertSize += pdm16->dmDriverExtra;
  977. }
  978. LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd16Info (%lx) [%ld]\n",
  979. NULL, S_OK, pdvtdInfo->cbConvertSize));
  980. return(S_OK);
  981. }
  982. //+-------------------------------------------------------------------------
  983. //
  984. // Function: UtConvertDvtd16toDvtd32
  985. //
  986. // Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
  987. // DVTARGETDEVICE
  988. //
  989. // Arguments: [pdvtd16] -- pointer to ANSI DVTARGETDEVICE
  990. // [pdvtdInfo] -- pointer to DVDT_INFO block
  991. // [pdvtd32] -- pointer to UNICODE DVTARGETDEVICE
  992. //
  993. // Requires: pdvtdInfo must have been filled in by a previous call to
  994. // UtGetDvtd16Info
  995. //
  996. // pdvtd32 must be at least pdvtdInfo->cbConvertSize bytes long
  997. //
  998. // Returns: HRESULT
  999. //
  1000. // Modifies: pdvtd32
  1001. //
  1002. // Algorithm:
  1003. //
  1004. // History: 06-May-94 AlexT Created from DrewB's original functions
  1005. // 10-Jul-94 AlexT Make sure DEVMODEW is DWORD aligned
  1006. //
  1007. // Notes: Do we need to do any error checking on the strings?
  1008. //
  1009. //--------------------------------------------------------------------------
  1010. extern "C" HRESULT UtConvertDvtd16toDvtd32(DVTARGETDEVICE const UNALIGNED *pdvtd16,
  1011. DVTDINFO const *pdvtdInfo,
  1012. DVTARGETDEVICE *pdvtd32)
  1013. {
  1014. LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd16toDvtd32 (%p, %p, %p)\n",
  1015. NULL, pdvtd16, pdvtdInfo, pdvtd32));
  1016. #if DBG==1
  1017. {
  1018. // Verify the passed in pdvtdInfo is what we expect
  1019. DVTDINFO dbgDvtdInfo;
  1020. Assert(UtGetDvtd16Info(pdvtd16, &dbgDvtdInfo) == S_OK);
  1021. Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
  1022. }
  1023. #endif
  1024. HRESULT hr = S_OK;
  1025. USHORT cbOffset;
  1026. int cchWritten;
  1027. DEVMODEA UNALIGNED *pdm16;
  1028. DEVMODEW *pdm32;
  1029. UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  1030. memset(pdvtd32, 0, pdvtdInfo->cbConvertSize);
  1031. cbOffset = UT_DVTARGETDEVICE_SIZE;
  1032. if (pdvtdInfo->cchDrvName != 0)
  1033. {
  1034. pdvtd32->tdDriverNameOffset = cbOffset;
  1035. cchWritten = MultiByteToWideChar(
  1036. CP_ACP, 0,
  1037. (char *)pdvtd16+pdvtd16->tdDriverNameOffset,
  1038. pdvtdInfo->cchDrvName,
  1039. (LPOLESTR)((BYTE *)pdvtd32 +
  1040. pdvtd32->tdDriverNameOffset),
  1041. pdvtdInfo->cchDrvName);
  1042. if (0 == cchWritten)
  1043. {
  1044. hr = E_UNEXPECTED;
  1045. goto ErrRtn;
  1046. }
  1047. cbOffset = cbOffset + (USHORT)(cchWritten * sizeof(WCHAR));
  1048. }
  1049. if (pdvtdInfo->cchDevName != 0)
  1050. {
  1051. pdvtd32->tdDeviceNameOffset = cbOffset;
  1052. cchWritten = MultiByteToWideChar(
  1053. nCodePage, 0,
  1054. (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
  1055. pdvtdInfo->cchDevName,
  1056. (LPOLESTR)((BYTE *)pdvtd32 +
  1057. pdvtd32->tdDeviceNameOffset),
  1058. pdvtdInfo->cchDevName);
  1059. if (0 == cchWritten)
  1060. {
  1061. hr = E_UNEXPECTED;
  1062. goto ErrRtn;
  1063. }
  1064. cbOffset = cbOffset + (USHORT)(cchWritten * sizeof(WCHAR));
  1065. }
  1066. if (pdvtdInfo->cchPortName != 0)
  1067. {
  1068. pdvtd32->tdPortNameOffset = cbOffset;
  1069. cchWritten = MultiByteToWideChar(
  1070. nCodePage, 0,
  1071. (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
  1072. pdvtdInfo->cchPortName,
  1073. (LPOLESTR)((BYTE *)pdvtd32 +
  1074. pdvtd32->tdPortNameOffset),
  1075. pdvtdInfo->cchPortName);
  1076. if (0 == cchWritten)
  1077. {
  1078. hr = E_UNEXPECTED;
  1079. goto ErrRtn;
  1080. }
  1081. cbOffset = cbOffset + (USHORT)(cchWritten * sizeof(WCHAR));
  1082. }
  1083. if (pdvtd16->tdExtDevmodeOffset != 0)
  1084. {
  1085. // Make sure DEVMODEW will be DWORD aligned
  1086. cbOffset += (sizeof(DWORD) - 1);
  1087. cbOffset &= ~(sizeof(DWORD) - 1);
  1088. pdvtd32->tdExtDevmodeOffset = cbOffset;
  1089. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1090. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
  1091. // The incoming DEVMODEA can have one of the following two forms:
  1092. //
  1093. // 1) 32 chars for dmDeviceName
  1094. // m bytes worth of fixed size data (where m <= 38)
  1095. // n bytes of dmDriverExtra data
  1096. //
  1097. // and dmSize will be 32+m
  1098. //
  1099. // 2) 32 chars for dmDeviceName
  1100. // 38 bytes worth of fixed size data
  1101. // 32 chars for dmFormName
  1102. // m additional bytes of fixed size data
  1103. // n bytes of dmDriverExtra data
  1104. //
  1105. // and dmSize will be 32 + 38 + 32 + m
  1106. //
  1107. // We have to be careful to translate the dmFormName string, if it
  1108. // exists
  1109. // First, translate the dmDeviceName
  1110. if (MultiByteToWideChar(nCodePage, 0, (char *)pdm16->dmDeviceName,
  1111. CCHDEVICENAME,
  1112. pdm32->dmDeviceName, CCHDEVICENAME) == 0)
  1113. {
  1114. hr = E_UNEXPECTED;
  1115. goto ErrRtn;
  1116. }
  1117. // Now check to see if we have a dmFormName to translate
  1118. if (pdm16->dmSize <= FIELD_OFFSET(DEVMODEA, dmFormName))
  1119. {
  1120. // No dmFormName, just copy the remaining m bytes
  1121. memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
  1122. pdm16->dmSize - CCHDEVICENAME);
  1123. }
  1124. else
  1125. {
  1126. // There is a dmFormName; copy the bytes between the names first
  1127. memcpy(&pdm32->dmSpecVersion, &pdm16->dmSpecVersion,
  1128. FIELD_OFFSET(DEVMODEA, dmFormName) -
  1129. FIELD_OFFSET(DEVMODEA, dmSpecVersion));
  1130. // Now translate the dmFormName
  1131. if (MultiByteToWideChar(CP_ACP, 0, (char *)pdm16->dmFormName,
  1132. CCHFORMNAME,
  1133. pdm32->dmFormName, CCHFORMNAME) == 0)
  1134. {
  1135. hr = E_UNEXPECTED;
  1136. goto ErrRtn;
  1137. }
  1138. // Now copy the remaining m bytes
  1139. if (pdm16->dmSize > FIELD_OFFSET(DEVMODEA, dmLogPixels))
  1140. {
  1141. memcpy(&pdm32->dmLogPixels, &pdm16->dmLogPixels,
  1142. pdm16->dmSize - FIELD_OFFSET(DEVMODEA, dmLogPixels));
  1143. }
  1144. }
  1145. pdm32->dmSize = sizeof(DEVMODEW);
  1146. if (pdm16->dmSize > sizeof(DEVMODEA))
  1147. {
  1148. pdm32->dmSize += pdm16->dmSize - sizeof(DEVMODEA);
  1149. }
  1150. // Copy the extra driver bytes
  1151. memcpy(((BYTE*)pdm32) + pdm32->dmSize, ((BYTE*)pdm16) + pdm16->dmSize,
  1152. pdm16->dmDriverExtra);
  1153. cbOffset += pdm32->dmSize + pdm32->dmDriverExtra;
  1154. }
  1155. // Finally, set pdvtd32's size
  1156. pdvtd32->tdSize = cbOffset;
  1157. ErrRtn:
  1158. LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd16toDvtd32 (%lx)\n",
  1159. NULL, hr));
  1160. return hr;
  1161. }
  1162. //+-------------------------------------------------------------------------
  1163. //
  1164. // Function: UtGetDvtd32Info
  1165. //
  1166. // Synopsis: Fills in pdvdtInfo
  1167. //
  1168. // Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
  1169. // [pdvtdInfo] -- pointer to DVDT_INFO block
  1170. //
  1171. // Requires:
  1172. //
  1173. // Returns: HRESULT
  1174. //
  1175. // Modifies: pdvtdInfo
  1176. //
  1177. // Algorithm:
  1178. //
  1179. // History: 06-May-94 AlexT Created from DrewB's original functions
  1180. //
  1181. // Notes: Do we need to do any error checking on the strings?
  1182. //
  1183. //--------------------------------------------------------------------------
  1184. extern "C" HRESULT UtGetDvtd32Info(DVTARGETDEVICE const *pdvtd32, PDVTDINFO pdvtdInfo)
  1185. {
  1186. LEDebugOut((DEB_ITRACE, "%p _IN UtGetDvtd32Info (%p, %p)\n",
  1187. NULL, pdvtd32, pdvtdInfo));
  1188. DEVMODEW *pdm32;
  1189. // Let's do some sanity checking on the incoming DVTARGETDEVICE
  1190. if (pdvtd32->tdSize < DVTD_MINSIZE)
  1191. {
  1192. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdSize\n"));
  1193. return(E_INVALIDARG);
  1194. }
  1195. pdvtdInfo->cbConvertSize = UT_DVTARGETDEVICE_SIZE;
  1196. // Compute required size for Drv, Device, Port names
  1197. if (pdvtd32->tdDriverNameOffset != 0)
  1198. {
  1199. if (pdvtd32->tdDriverNameOffset > pdvtd32->tdSize ||
  1200. pdvtd32->tdDriverNameOffset < DVTD_MINSIZE)
  1201. {
  1202. // Offset can't be larger than size or fall within base
  1203. // structure
  1204. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDriverNameOffset\n"));
  1205. return(E_INVALIDARG);
  1206. }
  1207. pdvtdInfo->cchDrvName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1208. pdvtd32->tdDriverNameOffset)) + 1;
  1209. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDrvName * sizeof(WCHAR);
  1210. }
  1211. else
  1212. {
  1213. pdvtdInfo->cchDrvName = 0;
  1214. }
  1215. if (pdvtd32->tdDeviceNameOffset != 0)
  1216. {
  1217. if (pdvtd32->tdDeviceNameOffset > pdvtd32->tdSize ||
  1218. pdvtd32->tdDeviceNameOffset < DVTD_MINSIZE)
  1219. {
  1220. // Offset can't be larger than size or fall within base
  1221. // structure
  1222. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdDeviceNameOffset\n"));
  1223. return(E_INVALIDARG);
  1224. }
  1225. pdvtdInfo->cchDevName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1226. pdvtd32->tdDeviceNameOffset)) + 1;
  1227. pdvtdInfo->cbConvertSize += pdvtdInfo->cchDevName * sizeof(WCHAR);
  1228. }
  1229. else
  1230. {
  1231. pdvtdInfo->cchDevName = 0;
  1232. }
  1233. if (pdvtd32->tdPortNameOffset != 0)
  1234. {
  1235. if (pdvtd32->tdPortNameOffset > pdvtd32->tdSize ||
  1236. pdvtd32->tdPortNameOffset < DVTD_MINSIZE)
  1237. {
  1238. // Offset can't be larger than size or fall within base
  1239. // structure
  1240. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdPortNameOffset\n"));
  1241. return(E_INVALIDARG);
  1242. }
  1243. pdvtdInfo->cchPortName = lstrlenW((WCHAR *)((BYTE *)pdvtd32 +
  1244. pdvtd32->tdPortNameOffset)) + 1;
  1245. pdvtdInfo->cbConvertSize += pdvtdInfo->cchPortName * sizeof(WCHAR);
  1246. }
  1247. else
  1248. {
  1249. pdvtdInfo->cchPortName = 0;
  1250. }
  1251. // Now compute the space needed for the DEVMODE
  1252. if (pdvtd32->tdExtDevmodeOffset != 0)
  1253. {
  1254. if (pdvtd32->tdExtDevmodeOffset > pdvtd32->tdSize ||
  1255. pdvtd32->tdExtDevmodeOffset < DVTD_MINSIZE)
  1256. {
  1257. // Offset can't be larger than size or fall within base
  1258. // structure
  1259. LEDebugOut((DEB_WARN, "UtGetDvtd32Info - bad pdvtd32->tdExtDevmodeOffset\n"));
  1260. return(E_INVALIDARG);
  1261. }
  1262. // The DEVMODEA structure needs to be DWORD aligned, so here we make
  1263. // sure cbConvertSize (which will be the beginning of DEVMODEA) is
  1264. // DWORD aligned
  1265. pdvtdInfo->cbConvertSize += (sizeof(DWORD) - 1);
  1266. pdvtdInfo->cbConvertSize &= ~(sizeof(DWORD) - 1);
  1267. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1268. // We start with a basic DEVMODEA
  1269. pdvtdInfo->cbConvertSize += sizeof(DEVMODEA);
  1270. if (pdm32->dmSize > sizeof(DEVMODEW))
  1271. {
  1272. // The input DEVMODEW is larger than a standard DEVMODEW, so
  1273. // add space for the extra amount
  1274. pdvtdInfo->cbConvertSize += pdm32->dmSize - sizeof(DEVMODEW);
  1275. }
  1276. // Finally we account for the extra driver data
  1277. pdvtdInfo->cbConvertSize += pdm32->dmDriverExtra;
  1278. }
  1279. LEDebugOut((DEB_ITRACE, "%p OUT UtGetDvtd32Info (%lx) [%ld]\n",
  1280. NULL, S_OK, pdvtdInfo->cbConvertSize));
  1281. return(S_OK);
  1282. }
  1283. //+-------------------------------------------------------------------------
  1284. //
  1285. // Function: UtConvertDvtd32toDvtd16
  1286. //
  1287. // Synopsis: Fills in a 32-bit DVTARGETDEVICE based on a 16-bit
  1288. // DVTARGETDEVICE
  1289. //
  1290. // Arguments: [pdvtd32] -- pointer to ANSI DVTARGETDEVICE
  1291. // [pdvtdInfo] -- pointer to DVDT_INFO block
  1292. // [pdvtd16] -- pointer to UNICODE DVTARGETDEVICE
  1293. //
  1294. // Requires: pdvtdInfo must have been filled in by a previous call to
  1295. // UtGetDvtd32Info
  1296. //
  1297. // pdvtd16 must be at least pdvtdInfo->cbSizeConvert bytes long
  1298. //
  1299. // Returns: HRESULT
  1300. //
  1301. // Modifies: pdvtd16
  1302. //
  1303. // Algorithm:
  1304. //
  1305. // History: 06-May-94 AlexT Created from DrewB's original functions
  1306. //
  1307. // Notes: Do we need to do any error checking on the strings?
  1308. //
  1309. // On Chicago we'll have to provide helper code to do this
  1310. // translation
  1311. //
  1312. //--------------------------------------------------------------------------
  1313. extern "C" HRESULT UtConvertDvtd32toDvtd16(DVTARGETDEVICE const *pdvtd32,
  1314. DVTDINFO const *pdvtdInfo,
  1315. DVTARGETDEVICE UNALIGNED *pdvtd16)
  1316. {
  1317. LEDebugOut((DEB_ITRACE, "%p _IN UtConvertDvtd32toDvtd16 (%p, %p, %p)\n",
  1318. NULL, pdvtd32, pdvtdInfo, pdvtd16));
  1319. #if DBG==1
  1320. {
  1321. // Verify the passed in pdvtdInfo is what we expect
  1322. DVTDINFO dbgDvtdInfo;
  1323. Assert(UtGetDvtd32Info(pdvtd32, &dbgDvtdInfo) == S_OK);
  1324. Assert(0 == memcmp(&dbgDvtdInfo, pdvtdInfo, sizeof(DVTDINFO)));
  1325. }
  1326. #endif
  1327. HRESULT hr = S_OK;
  1328. USHORT cbOffset;
  1329. int cbWritten;
  1330. DEVMODEA UNALIGNED *pdm16;
  1331. DEVMODEW *pdm32;
  1332. UINT nCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  1333. memset(pdvtd16, 0, pdvtdInfo->cbConvertSize);
  1334. cbOffset = UT_DVTARGETDEVICE_SIZE;
  1335. if (pdvtdInfo->cchDrvName != 0)
  1336. {
  1337. pdvtd16->tdDriverNameOffset = cbOffset;
  1338. cbWritten = WideCharToMultiByte(CP_ACP, 0,
  1339. (WCHAR *)((BYTE *)pdvtd32 +
  1340. pdvtd32->tdDriverNameOffset),
  1341. pdvtdInfo->cchDrvName,
  1342. (char *)pdvtd16 + pdvtd16->tdDriverNameOffset,
  1343. pdvtdInfo->cchDrvName * sizeof(WCHAR),
  1344. NULL, NULL);
  1345. if (0 == cbWritten)
  1346. {
  1347. hr = E_UNEXPECTED;
  1348. goto ErrRtn;
  1349. }
  1350. cbOffset = cbOffset + (USHORT) cbWritten;
  1351. }
  1352. if (pdvtdInfo->cchDevName != 0)
  1353. {
  1354. pdvtd16->tdDeviceNameOffset = cbOffset;
  1355. cbWritten = WideCharToMultiByte(
  1356. nCodePage, 0,
  1357. (WCHAR *)((BYTE *)pdvtd32 +
  1358. pdvtd32->tdDeviceNameOffset),
  1359. pdvtdInfo->cchDevName,
  1360. (char *)pdvtd16 + pdvtd16->tdDeviceNameOffset,
  1361. pdvtdInfo->cchDevName * sizeof(WCHAR),
  1362. NULL, NULL);
  1363. if (0 == cbWritten)
  1364. {
  1365. hr = E_UNEXPECTED;
  1366. goto ErrRtn;
  1367. }
  1368. cbOffset = cbOffset + (USHORT) cbWritten;
  1369. }
  1370. if (pdvtdInfo->cchPortName != 0)
  1371. {
  1372. pdvtd16->tdPortNameOffset = cbOffset;
  1373. cbWritten = WideCharToMultiByte(nCodePage, 0,
  1374. (WCHAR *)((BYTE *)pdvtd32 +
  1375. pdvtd32->tdPortNameOffset),
  1376. pdvtdInfo->cchPortName,
  1377. (char *)pdvtd16 + pdvtd16->tdPortNameOffset,
  1378. pdvtdInfo->cchPortName * sizeof(WCHAR),
  1379. NULL, NULL);
  1380. if (0 == cbWritten)
  1381. {
  1382. hr = E_UNEXPECTED;
  1383. goto ErrRtn;
  1384. }
  1385. cbOffset = cbOffset + (USHORT) cbWritten;
  1386. }
  1387. if (pdvtd32->tdExtDevmodeOffset != 0)
  1388. {
  1389. // Make sure DEVMODEA will be DWORD aligned
  1390. cbOffset += (sizeof(DWORD) - 1);
  1391. cbOffset &= ~(sizeof(DWORD) - 1);
  1392. pdvtd16->tdExtDevmodeOffset = cbOffset;
  1393. pdm16 = (DEVMODEA *)((BYTE *)pdvtd16+pdvtd16->tdExtDevmodeOffset);
  1394. pdm32 = (DEVMODEW *)((BYTE *)pdvtd32+pdvtd32->tdExtDevmodeOffset);
  1395. // The incoming DEVMODEW can have one of the following two forms:
  1396. //
  1397. // 1) 32 WCHARs for dmDeviceName
  1398. // m bytes worth of fixed size data (where m <= 38)
  1399. // n bytes of dmDriverExtra data
  1400. //
  1401. // and dmSize will be 64+m
  1402. //
  1403. // 2) 32 WCHARs for dmDeviceName
  1404. // 38 bytes worth of fixed size data
  1405. // 32 WCHARs for dmFormName
  1406. // m additional bytes of fixed size data
  1407. // n bytes of dmDriverExtra data
  1408. //
  1409. // and dmSize will be 64 + 38 + 64 + m
  1410. //
  1411. // We have to be careful to translate the dmFormName string, if it
  1412. // exists
  1413. // Need to attempt to copy the entire buffer since old UI lib does a memcmp to verify if ptd's are equal
  1414. if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,CCHDEVICENAME,
  1415. (char *)pdm16->dmDeviceName, CCHDEVICENAME,
  1416. NULL, NULL) == 0)
  1417. {
  1418. // in DBCS case we can run out of pdm16->dmDeviceName buffer space
  1419. // Current Implementation of WideCharToMultiByte copies in what fit before error
  1420. // but in case this behavior changes copy again up to NULL char if error out above
  1421. if (WideCharToMultiByte(nCodePage, 0, pdm32->dmDeviceName,-1,
  1422. (char *)pdm16->dmDeviceName, CCHDEVICENAME,
  1423. NULL, NULL) == 0)
  1424. {
  1425. hr = E_UNEXPECTED;
  1426. goto ErrRtn;
  1427. }
  1428. }
  1429. // Now check to see if we have a dmFormName to translate
  1430. if (pdm32->dmSize <= FIELD_OFFSET(DEVMODEW, dmFormName))
  1431. {
  1432. // No dmFormName, just copy the remaining m bytes
  1433. memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
  1434. pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmSpecVersion));
  1435. }
  1436. else
  1437. {
  1438. // There is a dmFormName; copy the bytes between the names first
  1439. memcpy(&pdm16->dmSpecVersion, &pdm32->dmSpecVersion,
  1440. FIELD_OFFSET(DEVMODEW, dmFormName) -
  1441. FIELD_OFFSET(DEVMODEW, dmSpecVersion));
  1442. // Now translate the dmFormName
  1443. if (WideCharToMultiByte(CP_ACP, 0,
  1444. pdm32->dmFormName, CCHFORMNAME,
  1445. (char *) pdm16->dmFormName, CCHFORMNAME,
  1446. NULL, NULL) == 0)
  1447. {
  1448. if (WideCharToMultiByte(CP_ACP, 0,
  1449. pdm32->dmFormName, -1,
  1450. (char *) pdm16->dmFormName, CCHFORMNAME,
  1451. NULL, NULL) == 0)
  1452. {
  1453. hr = E_UNEXPECTED;
  1454. goto ErrRtn;
  1455. }
  1456. }
  1457. // Now copy the remaining m bytes
  1458. if (pdm32->dmSize > FIELD_OFFSET(DEVMODEW, dmLogPixels))
  1459. {
  1460. memcpy(&pdm16->dmLogPixels, &pdm32->dmLogPixels,
  1461. pdm32->dmSize - FIELD_OFFSET(DEVMODEW, dmLogPixels));
  1462. }
  1463. }
  1464. pdm16->dmSize = sizeof(DEVMODEA);
  1465. if (pdm32->dmSize > sizeof(DEVMODEW))
  1466. {
  1467. pdm16->dmSize += pdm32->dmSize - sizeof(DEVMODEW);
  1468. }
  1469. // Copy the extra driver bytes
  1470. memcpy(((BYTE*)pdm16) + pdm16->dmSize, ((BYTE*)pdm32) + pdm32->dmSize,
  1471. pdm32->dmDriverExtra);
  1472. cbOffset += pdm16->dmSize + pdm16->dmDriverExtra;
  1473. }
  1474. // Finally, set pdvtd16's size
  1475. pdvtd16->tdSize = cbOffset;
  1476. ErrRtn:
  1477. LEDebugOut((DEB_ITRACE, "%p OUT UtConvertDvtd32toDvtd16 (%lx)\n",
  1478. NULL, hr));
  1479. return hr;
  1480. }
  1481. //+-------------------------------------------------------------------------
  1482. //
  1483. // Function: UtGetUNICODEData, PRIVATE INTERNAL
  1484. //
  1485. // Synopsis: Given a string length, and two pointers (one ANSI, one
  1486. // OLESTR), returns the UNICODE version of whichever string
  1487. // is valid.
  1488. //
  1489. // Effects: Memory is allocated on the caller's pointer for new OLESTR
  1490. //
  1491. // Arguments: [ulLength] -- length of string in CHARACTERS (not bytes)
  1492. // (including terminator)
  1493. // [szANSI] -- candidate ANSI string
  1494. // [szOLESTR] -- candidate OLESTR string
  1495. // [pstr] -- OLESTR OUT parameter
  1496. //
  1497. // Returns: NOERROR on success
  1498. // E_OUTOFMEMORY on allocation failure
  1499. // E_ANSITOUNICODE if ANSI cannot be converted to UNICODE
  1500. //
  1501. // Algorithm: If szOLESTR is available, a simple copy is performed
  1502. // If szOLESTR is not available, szANSI is converted to UNICODE
  1503. // and the result is copied.
  1504. //
  1505. // History: dd-mmm-yy Author Comment
  1506. // 08-Mar-94 davepl Created
  1507. //
  1508. // Notes: Only one of the two input strings (ANSI or UNICODE) should
  1509. // be set on entry.
  1510. //
  1511. //--------------------------------------------------------------------------
  1512. INTERNAL UtGetUNICODEData
  1513. ( ULONG ulLength,
  1514. LPSTR szANSI,
  1515. LPOLESTR szOLESTR,
  1516. LPOLESTR * pstr )
  1517. {
  1518. VDATEHEAP();
  1519. // This fn is only called when one of the input strings
  1520. // has valid data... assert the impossible.
  1521. Win4Assert(pstr); // must have an out string
  1522. Win4Assert(ulLength); // must have a non-zero length
  1523. Win4Assert(szANSI || szOLESTR); // must have at least one source string
  1524. // If neither the ANSI nor the OLESTR version has data,
  1525. // there is nothing to return.
  1526. if (!(szANSI || szOLESTR))
  1527. {
  1528. *pstr = NULL;
  1529. }
  1530. // Allocate memory for the UNICODE return string
  1531. *pstr = (LPOLESTR) PubMemAlloc((ulLength+1) * sizeof(OLECHAR));
  1532. if (NULL == *pstr)
  1533. {
  1534. return ResultFromScode(E_OUTOFMEMORY);
  1535. }
  1536. // Trivial case: we already have UNICODE, just copy it
  1537. if (szOLESTR)
  1538. {
  1539. _xstrcpy(*pstr, szOLESTR);
  1540. return(NOERROR);
  1541. }
  1542. // Otherwise, we have to convert the ANSI string to UNICODE
  1543. // and return that.
  1544. else
  1545. {
  1546. if (FALSE == MultiByteToWideChar(CP_ACP, // Code page ANSI
  1547. 0, // Flags (none)
  1548. szANSI, // Source ANSI str
  1549. ulLength, // length of string
  1550. *pstr, // Dest UNICODE buffer
  1551. ulLength )) // size of UNICODE buffer
  1552. {
  1553. PubMemFree(*pstr);
  1554. *pstr = NULL;
  1555. return ResultFromScode(E_UNSPEC);
  1556. }
  1557. }
  1558. return NOERROR;
  1559. }
  1560. //+-------------------------------------------------------------------------
  1561. //
  1562. // Function: UtPutUNICODEData, PRIVATE INTERNAL
  1563. //
  1564. // Synopsis: Given an OLESTR and two possible buffer pointer, one ANSI
  1565. // and the other OLESTR, this fn tries to convert the string
  1566. // down to ANSI. If it succeeds, it allocates memory on the
  1567. // ANSI ptr for the result. If it fails, it allocates memory
  1568. // on the UNICODE ptr and copies the input string over. The
  1569. // length of the final result (ANSI or UNICODE) is returned
  1570. // in dwResultLen.
  1571. //
  1572. // Arguments: [ulLength] -- input length of OLESTR str
  1573. // NB!!!! this value must include the
  1574. // null terminator character.
  1575. // [str] -- the OLESTR to store
  1576. // [pszANSI] -- candidate ANSI str ptr
  1577. // [pszOLESTR] -- candidate OLESTR str ptr. May be NULL,
  1578. // in which case no copy is made of the
  1579. // original string if the ANSI conversion
  1580. // fails.
  1581. // [pdwResultLen] -- where to store the length of result. This
  1582. // length includes the terminating NULL.
  1583. // Length is in CHARACTERS.
  1584. //
  1585. // Returns: NOERROR on success
  1586. // E_OUTOFMEMORY on allocation failure
  1587. // E_FAIL can't convert ANSI string and no
  1588. // pszOLESTR is NULL
  1589. //
  1590. // History: dd-mmm-yy Author Comment
  1591. // 10-Jun-94 alexgo allow pszOLESTR to be NULL
  1592. // 08-Mar-94 davepl Created
  1593. //
  1594. //--------------------------------------------------------------------------
  1595. // this function is poorly coded. But, it looks like it only gets called when a 1.0
  1596. // clip format is needed. That is not very often!
  1597. INTERNAL UtPutUNICODEData
  1598. ( ULONG ulLength,
  1599. LPOLESTR str,
  1600. LPSTR * pszANSI,
  1601. LPOLESTR * pszOLESTR,
  1602. DWORD * pdwResultLen )
  1603. {
  1604. VDATEHEAP();
  1605. Win4Assert(pszANSI);
  1606. Win4Assert(str);
  1607. Win4Assert(pdwResultLen);
  1608. Win4Assert(ulLength);
  1609. // Free any strings currently attached to these pointers; if we wind
  1610. // up setting one here, we can't leave the other valid.
  1611. if (*pszANSI)
  1612. {
  1613. PubMemFree(*pszANSI);
  1614. *pszANSI = NULL;
  1615. }
  1616. if (pszOLESTR && *pszOLESTR)
  1617. {
  1618. PubMemFree(*pszOLESTR);
  1619. *pszOLESTR = NULL;
  1620. }
  1621. // Create a working buffer for UNICODE->ANSI conversion
  1622. LPSTR szANSITEMP = (LPSTR) PubMemAlloc((ulLength+1) * 2);
  1623. if (NULL == szANSITEMP)
  1624. {
  1625. return ResultFromScode(E_OUTOFMEMORY);
  1626. }
  1627. // Try to convert the UNICODE down to ANSI. If it succeeds,
  1628. // we just copy the result to the ANSI dest. If it fails,
  1629. // we copy the UNICODE version direct to the UNICODE dest.
  1630. LPCSTR pDefault = "?";
  1631. BOOL fUseDef = 0;
  1632. if (FALSE == WideCharToMultiByte (CP_ACP,
  1633. 0,
  1634. str,
  1635. ulLength,
  1636. szANSITEMP,
  1637. (ulLength + 1) * 2,
  1638. pDefault,
  1639. &fUseDef) || fUseDef )
  1640. {
  1641. // UNICODE->ANSI failed!
  1642. // Won't be needing the ANSI buffer anymore...
  1643. PubMemFree(szANSITEMP);
  1644. if( pszOLESTR )
  1645. {
  1646. *pszANSI = NULL;
  1647. *pszOLESTR = (LPOLESTR) PubMemAlloc((ulLength + 1) * sizeof(OLECHAR));
  1648. if (NULL == *pszOLESTR)
  1649. {
  1650. *pdwResultLen = 0;
  1651. return ResultFromScode(E_OUTOFMEMORY);
  1652. }
  1653. // Move the UNICODE source to UNICODE dest
  1654. _xstrcpy(*pszOLESTR, str);
  1655. *pdwResultLen = _xstrlen(str) + 1;
  1656. // That's it... return success
  1657. return(NOERROR);
  1658. }
  1659. else
  1660. {
  1661. return ResultFromScode(E_FAIL);
  1662. }
  1663. }
  1664. // This code path is taken when the conversion to ANSI was
  1665. // successful. We copy the ANSI result to the ANSI dest.
  1666. if( pszOLESTR )
  1667. {
  1668. *pszOLESTR = NULL;
  1669. }
  1670. *pdwResultLen = (DWORD) strlen(szANSITEMP) + 1;
  1671. *pszANSI = (LPSTR) PubMemAlloc(*pdwResultLen);
  1672. if (NULL == *pszANSI)
  1673. {
  1674. *pdwResultLen = 0;
  1675. return ResultFromScode(E_OUTOFMEMORY);
  1676. }
  1677. strcpy(*pszANSI, szANSITEMP);
  1678. PubMemFree(szANSITEMP);
  1679. return(NOERROR);
  1680. }
  1681. //+-------------------------------------------------------------------------
  1682. //
  1683. // Method: CSafeRefCount::SafeRefCount()
  1684. //
  1685. // Purpose: CSafeRefCount implements reference counting rules for objects.
  1686. // It keeps track of reference count and zombie state.
  1687. // It helps object manage their liveness properly.
  1688. //
  1689. // History: dd-mmm-yy Author Comment
  1690. // 16-Jan-97 Gopalk Rewritten to handle aggregation
  1691. //
  1692. //--------------------------------------------------------------------------
  1693. ULONG CSafeRefCount::SafeRelease()
  1694. {
  1695. ULONG cRefs;
  1696. // Decrement ref count
  1697. cRefs = InterlockedDecrement((LONG *) &m_cRefs);
  1698. // Check if this is the last release
  1699. if(cRefs == 0) {
  1700. // As this function is reentrant on the current
  1701. // thread, gaurd against double destruction
  1702. if(!m_fInDelete) {
  1703. // There are no race conditions here
  1704. // Mark object as in destructor
  1705. m_fInDelete = TRUE;
  1706. // Here is the need for the destructor to be virtual
  1707. delete this;
  1708. }
  1709. }
  1710. return cRefs;
  1711. }
  1712. //+-------------------------------------------------------------------------
  1713. //
  1714. // Method: CRefExportCount::SafeRelease
  1715. //
  1716. // Purpose: CRefExportCount implements reference counting rules for server
  1717. // objects that export their nested objects on behalf of their
  1718. // clients like DEFHANDLER abd CACHE. It keeps track of
  1719. // reference count, export count, zombie state, etc.
  1720. // It helps object manage their shutdown logic properly.
  1721. //
  1722. // History: dd-mmm-yy Author Comment
  1723. // 16-Jan-97 Gopalk Creation
  1724. //
  1725. //--------------------------------------------------------------------------
  1726. ULONG CRefExportCount::SafeRelease()
  1727. {
  1728. ULONG cRefs;
  1729. // Decrement ref count
  1730. cRefs = InterlockedDecrement((LONG *) &m_cRefs);
  1731. // Check if ref count has become zero
  1732. if(cRefs == 0) {
  1733. // As this function is reentrant on the current
  1734. // thread, gaurd against double destruction
  1735. if(!m_IsZombie) {
  1736. // There are no race conditions here
  1737. // Mark object as a zombie
  1738. m_IsZombie = TRUE;
  1739. // Call cleanup function while destruction is not allowed
  1740. CleanupFn();
  1741. // Allow destruction
  1742. InterlockedExchange((LONG *) &m_Status, KILL);
  1743. // Check for any exported objects
  1744. if(m_cExportCount == 0) {
  1745. // Gaurd against double destruction
  1746. if(InterlockedExchange((LONG *) &m_Status, DEAD) == KILL) {
  1747. // Here is the need for the destructor to be virtual
  1748. delete this;
  1749. }
  1750. }
  1751. }
  1752. }
  1753. return cRefs;
  1754. }
  1755. //+-------------------------------------------------------------------------
  1756. //
  1757. // Method: CRefExportCount::DecrementExportCount
  1758. //
  1759. // Purpose: CRefExportCount implements reference counting rules for server
  1760. // objects that export their nested objects on behalf of their
  1761. // clients like DEFHANDLER abd CACHE. It keeps track of
  1762. // reference count, export count, zombie state, etc.
  1763. // It helps object manage their shutdown logic properly.
  1764. //
  1765. // History: dd-mmm-yy Author Comment
  1766. // 16-Jan-97 Gopalk Creation
  1767. //
  1768. //--------------------------------------------------------------------------
  1769. ULONG CRefExportCount::DecrementExportCount()
  1770. {
  1771. ULONG cExportCount;
  1772. // Decrement export count
  1773. cExportCount = InterlockedDecrement((LONG *) &m_cExportCount);
  1774. // Check if the export count has become zero
  1775. if(cExportCount == 0) {
  1776. // Check if destruction is allowed
  1777. if(m_Status == KILL) {
  1778. // Gaurd against double destruction
  1779. if(InterlockedExchange((LONG *) &m_Status, DEAD) == KILL) {
  1780. // Here is the need for the destructor to be virtual
  1781. delete this;
  1782. }
  1783. }
  1784. }
  1785. return cExportCount;
  1786. }
  1787. //+-------------------------------------------------------------------------
  1788. //
  1789. // Member: CThreadCheck::VerifyThreadId
  1790. //
  1791. // Synopsis: makes sure that the calling thread is the same as the thread
  1792. // the object was created on if the threading model is *not*
  1793. // free threading.
  1794. //
  1795. // Effects:
  1796. //
  1797. // Arguments: none
  1798. //
  1799. // Requires:
  1800. //
  1801. // Returns: TRUE/FALSE
  1802. //
  1803. // Signals:
  1804. //
  1805. // Modifies:
  1806. //
  1807. // Derivation:
  1808. //
  1809. // Algorithm:
  1810. //
  1811. // History: dd-mmm-yy Author Comment
  1812. // 21-Nov-94 alexgo author
  1813. //
  1814. // Notes:
  1815. //
  1816. //--------------------------------------------------------------------------
  1817. BOOL CThreadCheck::VerifyThreadId( void )
  1818. {
  1819. if( m_tid == GetCurrentThreadId() )
  1820. {
  1821. return TRUE;
  1822. }
  1823. else
  1824. {
  1825. LEDebugOut((DEB_ERROR, "ERROR!: Called on thread %lx, should be"
  1826. " %lx \n", GetCurrentThreadId(), m_tid));
  1827. return FALSE;
  1828. }
  1829. }
  1830. //+-------------------------------------------------------------------------
  1831. //
  1832. // Member: CThreadCheck::Dump, public (_DEBUG only)
  1833. //
  1834. // Synopsis: return a string containing the contents of the data members
  1835. //
  1836. // Effects:
  1837. //
  1838. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1839. // [ulFlag] - flag determining prefix of all newlines of the
  1840. // out character array (default is 0 - no prefix)
  1841. // [nIndentLevel] - will add a indent prefix after the other prefix
  1842. // for ALL newlines (including those with no prefix)
  1843. //
  1844. // Requires:
  1845. //
  1846. // Returns: HRESULT
  1847. //
  1848. // Signals:
  1849. //
  1850. // Modifies: [ppszDump] - argument
  1851. //
  1852. // Derivation:
  1853. //
  1854. // Algorithm: use dbgstream to create a string containing information on the
  1855. // content of data structures
  1856. //
  1857. // History: dd-mmm-yy Author Comment
  1858. // 20-Jan-95 t-ScottH author
  1859. //
  1860. // Notes:
  1861. //
  1862. //--------------------------------------------------------------------------
  1863. #ifdef _DEBUG
  1864. HRESULT CThreadCheck::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1865. {
  1866. int i;
  1867. char *pszPrefix;
  1868. dbgstream dstrPrefix;
  1869. dbgstream dstrDump;
  1870. // determine prefix of newlines
  1871. if ( ulFlag & DEB_VERBOSE )
  1872. {
  1873. dstrPrefix << this << " _VB ";
  1874. }
  1875. // determine indentation prefix for all newlines
  1876. for (i = 0; i < nIndentLevel; i++)
  1877. {
  1878. dstrPrefix << DUMPTAB;
  1879. }
  1880. pszPrefix = dstrPrefix.str();
  1881. // put data members in stream
  1882. dstrDump << pszPrefix << "Thread ID = " << m_tid << endl;
  1883. // clean up and provide pointer to character array
  1884. *ppszDump = dstrDump.str();
  1885. if (*ppszDump == NULL)
  1886. {
  1887. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1888. }
  1889. CoTaskMemFree(pszPrefix);
  1890. return NOERROR;
  1891. }
  1892. #endif //_DEBUG
  1893. //+-------------------------------------------------------------------------
  1894. //
  1895. // Function: DumpCThreadCheck, public (_DEBUG only)
  1896. //
  1897. // Synopsis: calls the CThreadCheck::Dump method, takes care of errors and
  1898. // returns the zero terminated string
  1899. //
  1900. // Effects:
  1901. //
  1902. // Arguments: [pTC] - pointer to CThreadCheck
  1903. // [ulFlag] - flag determining prefix of all newlines of the
  1904. // out character array (default is 0 - no prefix)
  1905. // [nIndentLevel] - will add a indent prefix after the other prefix
  1906. // for ALL newlines (including those with no prefix)
  1907. //
  1908. // Requires:
  1909. //
  1910. // Returns: character array of structure dump or error (null terminated)
  1911. //
  1912. // Signals:
  1913. //
  1914. // Modifies:
  1915. //
  1916. // Algorithm:
  1917. //
  1918. // History: dd-mmm-yy Author Comment
  1919. // 20-Jan-95 t-ScottH author
  1920. //
  1921. // Notes:
  1922. //
  1923. //--------------------------------------------------------------------------
  1924. #ifdef _DEBUG
  1925. char *DumpCThreadCheck(CThreadCheck *pTC, ULONG ulFlag, int nIndentLevel)
  1926. {
  1927. char *pszDump;
  1928. HRESULT hresult;
  1929. if (pTC == NULL)
  1930. {
  1931. return UtDupStringA(szDumpBadPtr);
  1932. }
  1933. hresult = pTC->Dump( &pszDump, ulFlag, nIndentLevel);
  1934. if (hresult != NOERROR)
  1935. {
  1936. CoTaskMemFree(pszDump);
  1937. return DumpHRESULT(hresult);
  1938. }
  1939. return pszDump;
  1940. }
  1941. #endif // _DEBUG