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.

807 lines
16 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: utils.c
  3. *
  4. * Purpose: Conatains all the utility routines
  5. *
  6. * Created: 1990
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Raor, srinik (../../1990,91) Designed and coded
  12. * curts created portable version for WIN16/32
  13. *
  14. \***************************************************************************/
  15. #include <windows.h>
  16. #include "dll.h"
  17. #define KB_64 65536
  18. #define NULL_WORD 0x0000
  19. extern ATOM aPackage;
  20. extern OLEOBJECTVTBL vtblMF, vtblBM, vtblDIB, vtblGEN;
  21. // QuerySize API support
  22. DWORD dwObjSize = 0;
  23. OLESTREAMVTBL dllStreamVtbl;
  24. OLESTREAM dllStream;
  25. #ifdef WIN16
  26. #pragma alloc_text(_DDETEXT, UtilMemClr, MapStrToH, MapExtToClass, FileExists)
  27. #endif
  28. BOOL PutStrWithLen(
  29. LPOLESTREAM lpstream,
  30. LPSTR lpbytes
  31. ){
  32. LONG len;
  33. len = (LONG) lstrlen(lpbytes) + 1;
  34. if (PutBytes (lpstream, (LPSTR)&len, sizeof(len)))
  35. return TRUE;
  36. return PutBytes(lpstream, lpbytes, len);
  37. }
  38. BOOL GetStrWithLen(
  39. LPOLESTREAM lpstream,
  40. LPSTR lpbytes
  41. ){
  42. if (GetBytes (lpstream, lpbytes, sizeof(LONG)))
  43. return TRUE;
  44. return GetBytes (lpstream, lpbytes + sizeof(LONG), (*(LONG FAR *)lpbytes));
  45. }
  46. ATOM GetAtomFromStream(
  47. LPOLESTREAM lpstream
  48. ){
  49. BOOL err = TRUE;
  50. LONG len;
  51. char str[MAX_STR+1];
  52. if (GetBytes (lpstream, (LPSTR)&len, sizeof(len)))
  53. return (ATOM)0;
  54. if (len == 0)
  55. return (ATOM)0;
  56. if (GetBytes(lpstream, (LPSTR)str, len))
  57. return (ATOM)0;
  58. return GlobalAddAtom(str);
  59. }
  60. BOOL PutAtomIntoStream(
  61. LPOLESTREAM lpstream,
  62. ATOM at
  63. ){
  64. LONG len = 0;
  65. char buf[MAX_STR + 1];
  66. if (at == 0)
  67. return (PutBytes (lpstream, (LPSTR)&len, sizeof(len)));
  68. len = GlobalGetAtomName (at,(LPSTR)buf, MAX_STR) + 1;
  69. if (PutBytes (lpstream, (LPSTR)&len, sizeof(len)))
  70. return TRUE;
  71. return PutBytes(lpstream, buf, len);
  72. }
  73. // DuplicateAtom: Bump the use count up on a global atom.
  74. ATOM FARINTERNAL DuplicateAtom (
  75. ATOM atom
  76. ){
  77. char buffer[MAX_ATOM+1];
  78. Puts("DuplicateAtom");
  79. if (!atom)
  80. return (ATOM)0;
  81. GlobalGetAtomName (atom, buffer, MAX_ATOM);
  82. return GlobalAddAtom (buffer);
  83. }
  84. BOOL GetBytes(
  85. LPOLESTREAM lpstream,
  86. LPSTR lpstr,
  87. LONG len
  88. ){
  89. ASSERT (lpstream->lpstbl->Get , "stream get function is null");
  90. return (((*lpstream->lpstbl->Get)(lpstream, lpstr, (DWORD)len)) != (DWORD)len);
  91. }
  92. BOOL PutBytes(
  93. LPOLESTREAM lpstream,
  94. LPSTR lpstr,
  95. LONG len
  96. ){
  97. ASSERT (lpstream->lpstbl->Put , "stream get function is null");
  98. return (((*lpstream->lpstbl->Put)(lpstream, lpstr, (DWORD)len)) != (DWORD)len);
  99. }
  100. BOOL FARINTERNAL UtilMemCmp (
  101. LPSTR lpmem1,
  102. LPSTR lpmem2,
  103. DWORD dwCount
  104. ){
  105. UINT HUGE_T * hpmem1;
  106. UINT HUGE_T * hpmem2;
  107. DWORD words;
  108. DWORD bytes;
  109. bytes = dwCount % MAPVALUE(2,4);
  110. words = dwCount >> MAPVALUE(1,2);//* we compare DWORDS
  111. //* in the 32 bit version
  112. #ifdef WIN16
  113. if (dwCount <= KB_64) {
  114. UINT FAR * lpwMem1 = (WORD FAR *) lpmem1;
  115. UINT FAR * lpwMem2 = (WORD FAR *) lpmem2;
  116. while (words--) {
  117. if (*lpwMem1++ != *lpwMem2++)
  118. return FALSE;
  119. }
  120. if (bytes) {
  121. if (* (char FAR *) lpwMem1 != *(char FAR *) lpwMem2)
  122. return FALSE;
  123. }
  124. }
  125. else
  126. #endif
  127. {
  128. hpmem1 = (UINT HUGE_T *) lpmem1;
  129. hpmem2 = (UINT HUGE_T *) lpmem2;
  130. while (words--) {
  131. if (*hpmem1++ != *hpmem2++)
  132. return FALSE;
  133. }
  134. lpmem1 = (LPSTR)hpmem1;
  135. lpmem2 = (LPSTR)hpmem2;
  136. for (; bytes-- ; ) {
  137. if ( *lpmem1++ != *lpmem2++ )
  138. return FALSE;
  139. }
  140. }
  141. return TRUE;
  142. }
  143. void FARINTERNAL UtilMemCpy (
  144. LPSTR lpdst,
  145. LPSTR lpsrc,
  146. DWORD dwCount
  147. ){
  148. UINT HUGE_T * hpdst;
  149. UINT HUGE_T * hpsrc;
  150. DWORD words;
  151. DWORD bytes;
  152. bytes = dwCount % MAPVALUE(2,4);
  153. words = dwCount >> MAPVALUE(1,2);//* we compare DWORDS
  154. //* in the 32 bit version
  155. #ifdef WIN16
  156. if (dwCount <= KB_64) {
  157. UINT FAR * lpwDst = (UINT FAR *) lpdst;
  158. UINT FAR * lpwSrc = (UINT FAR *) lpsrc;
  159. while (words--)
  160. *lpwDst++ = *lpwSrc++;
  161. if (bytes)
  162. * (char FAR *) lpwDst = * (char FAR *) lpwSrc;
  163. }
  164. else
  165. #endif
  166. {
  167. hpdst = (UINT HUGE_T *) lpdst;
  168. hpsrc = (UINT HUGE_T *) lpsrc;
  169. for(;words--; )
  170. *hpdst++ = *hpsrc++;
  171. lpdst = (LPSTR)hpdst;
  172. lpsrc = (LPSTR)hpsrc;
  173. for (;bytes--;)
  174. *lpdst++ = *lpsrc++;
  175. }
  176. }
  177. //DuplicateData: Duplicates a given Global data handle.
  178. HANDLE FARINTERNAL DuplicateGlobal (
  179. HANDLE hdata,
  180. UINT flags
  181. ){
  182. LPSTR lpdst = NULL;
  183. LPSTR lpsrc = NULL;
  184. HANDLE hdup = NULL;
  185. DWORD size;
  186. BOOL err = TRUE;
  187. if (!hdata)
  188. return NULL;
  189. if(!(lpsrc = GlobalLock (hdata)))
  190. return NULL;
  191. hdup = GlobalAlloc (flags, (size = (DWORD)GlobalSize(hdata)));
  192. if(!(lpdst = GlobalLock (hdup)))
  193. goto errRtn;;
  194. err = FALSE;
  195. UtilMemCpy (lpdst, lpsrc, size);
  196. errRtn:
  197. if(lpsrc)
  198. GlobalUnlock (hdata);
  199. if(lpdst)
  200. GlobalUnlock (hdup);
  201. if (err && hdup) {
  202. GlobalFree (hdup);
  203. hdup = NULL;
  204. }
  205. return hdup;
  206. }
  207. BOOL FARINTERNAL CmpGlobals (
  208. HANDLE hdata1,
  209. HANDLE hdata2
  210. ){
  211. LPSTR lpdata1 = NULL;
  212. LPSTR lpdata2 = NULL;
  213. DWORD size1;
  214. DWORD size2;
  215. BOOL retval = FALSE;
  216. size1 = (DWORD)GlobalSize (hdata1);
  217. size2 = (DWORD)GlobalSize (hdata2);
  218. if (size1 != size2)
  219. return FALSE;
  220. if (!(lpdata1 = GlobalLock (hdata1)))
  221. goto errRtn;
  222. if (!(lpdata2 = GlobalLock (hdata2)))
  223. goto errRtn;
  224. retval = UtilMemCmp (lpdata1, lpdata2, size1);
  225. errRtn:
  226. if (lpdata1)
  227. GlobalUnlock (hdata1);
  228. if (lpdata2)
  229. GlobalUnlock (hdata2);
  230. return retval;
  231. }
  232. int FARINTERNAL GlobalGetAtomLen (
  233. ATOM aItem
  234. ){
  235. // !!! Change this
  236. char buf[MAX_STR];
  237. if (!aItem)
  238. return 0;
  239. return (GlobalGetAtomName (aItem, (LPSTR)buf, MAX_STR));
  240. }
  241. BOOL FARINTERNAL MapExtToClass (
  242. LPSTR lptemplate,
  243. LPSTR lpbuf,
  244. int len
  245. ){
  246. LONG cb;
  247. LPSTR lpstrBack = NULL;
  248. while (*lptemplate)
  249. {
  250. if ((*lptemplate) == '\\'){
  251. lpstrBack = lptemplate ;
  252. }
  253. lptemplate ++ ;
  254. }
  255. while (lpstrBack && *lpstrBack && *lpstrBack != '.')
  256. lpstrBack++ ;
  257. cb = len;
  258. if (lpstrBack == NULL || *(lpstrBack+1) == '\0')
  259. return FALSE;
  260. if (RegQueryValue (HKEY_CLASSES_ROOT, lpstrBack, lpbuf, &cb))
  261. return FALSE;
  262. return TRUE;
  263. }
  264. // Get exe name from aClass and set it as aServer
  265. void INTERNAL SetExeAtom (
  266. LPOBJECT_LE lpobj
  267. ){
  268. char key[MAX_STR];
  269. // if old link object assume the class same as the exe file name.
  270. if (lpobj->bOldLink)
  271. lpobj->aServer = DuplicateAtom (lpobj->app);
  272. else {
  273. if (GlobalGetAtomName (lpobj->app, key, sizeof(key)))
  274. lpobj->aServer = GetAppAtom ((LPSTR)key);
  275. }
  276. }
  277. ATOM FARINTERNAL GetAppAtom (
  278. LPCSTR lpclass
  279. ){
  280. char buf1[MAX_STR];
  281. if (!QueryApp (lpclass, PROTOCOL_EDIT, buf1)) {
  282. return (ATOM)0;
  283. }
  284. return GlobalAddAtom ((LPSTR)buf1);
  285. }
  286. BOOL FARINTERNAL QueryVerb (
  287. LPOBJECT_LE lpobj,
  288. UINT verb,
  289. LPSTR lpbuf,
  290. LONG cbmax
  291. ){
  292. LONG cb = MAX_STR;
  293. char key[MAX_STR];
  294. // do not need 256 bytes buffer
  295. char class[MAX_STR];
  296. int len;
  297. if (!GlobalGetAtomName (lpobj->app, (LPSTR)class, sizeof(class)))
  298. return FALSE;
  299. lstrcpy (key, (LPSTR)class);
  300. lstrcat (key, "\\protocol\\StdFileEditing\\verb\\");
  301. len = lstrlen (key);
  302. key [len++] = (char) ('0' + verb);
  303. key [len++] = 0;
  304. if (RegQueryValue (HKEY_CLASSES_ROOT, key, lpbuf, &cbmax))
  305. return FALSE;
  306. return TRUE;
  307. }
  308. BOOL QueryApp (
  309. LPCSTR lpclass,
  310. LPCSTR lpprotocol,
  311. LPSTR lpbuf
  312. ){
  313. LONG cb = MAX_STR;
  314. char key[MAX_STR];
  315. lstrcpy (key, lpclass);
  316. lstrcat (key, "\\protocol\\");
  317. lstrcat (key, lpprotocol);
  318. lstrcat (key, "\\server");
  319. if (RegQueryValue (HKEY_CLASSES_ROOT, key, lpbuf, &cb))
  320. return FALSE;
  321. return TRUE;
  322. }
  323. HANDLE MapStrToH (
  324. LPSTR lpstr
  325. ){
  326. HANDLE hdata = NULL;
  327. LPSTR lpdata = NULL;
  328. hdata = GlobalAlloc (GMEM_DDESHARE, lstrlen (lpstr) + 1);
  329. if (hdata == NULL || (lpdata = (LPSTR)GlobalLock (hdata)) == NULL)
  330. goto errRtn;
  331. lstrcpy (lpdata, lpstr);
  332. GlobalUnlock (hdata);
  333. return hdata;
  334. errRtn:
  335. if (lpdata)
  336. GlobalUnlock (hdata);
  337. if (hdata)
  338. GlobalFree (hdata);
  339. return NULL;
  340. }
  341. HANDLE FARINTERNAL CopyData (
  342. LPSTR lpsrc,
  343. DWORD dwBytes
  344. ){
  345. HANDLE hnew;
  346. LPSTR lpnew;
  347. BOOL retval = FALSE;
  348. if (hnew = GlobalAlloc (GMEM_MOVEABLE, dwBytes)){
  349. if (lpnew = GlobalLock (hnew)){
  350. UtilMemCpy (lpnew, lpsrc, dwBytes);
  351. GlobalUnlock (hnew);
  352. return hnew;
  353. }
  354. else
  355. GlobalFree (hnew);
  356. }
  357. return NULL;
  358. }
  359. void UtilMemClr (
  360. PSTR pstr,
  361. UINT size
  362. ){
  363. while (size--)
  364. *pstr++ = 0;
  365. }
  366. OLESTATUS FAR PASCAL ObjQueryName (
  367. LPOLEOBJECT lpobj,
  368. LPSTR lpBuf,
  369. UINT FAR * lpcbBuf
  370. ){
  371. if (lpobj->ctype != CT_LINK && lpobj->ctype != CT_EMBEDDED
  372. && lpobj->ctype != CT_STATIC)
  373. return OLE_ERROR_OBJECT;
  374. PROBE_WRITE(lpBuf);
  375. if (!*lpcbBuf)
  376. return OLE_ERROR_SIZE;
  377. if (!CheckPointer(lpBuf+*lpcbBuf-1, WRITE_ACCESS))
  378. return OLE_ERROR_SIZE;
  379. ASSERT(lpobj->aObjName, "object name ATOM is NULL\n");
  380. *lpcbBuf = GlobalGetAtomName (lpobj->aObjName, lpBuf, *lpcbBuf);
  381. return OLE_OK;
  382. }
  383. OLESTATUS FAR PASCAL ObjRename (
  384. LPOLEOBJECT lpobj,
  385. LPCSTR lpNewName
  386. ){
  387. if (lpobj->ctype != CT_LINK && lpobj->ctype != CT_EMBEDDED
  388. && lpobj->ctype != CT_STATIC)
  389. return OLE_ERROR_OBJECT;
  390. PROBE_READ(lpNewName);
  391. if (!lpNewName[0])
  392. return OLE_ERROR_NAME;
  393. if (lpobj->aObjName)
  394. GlobalDeleteAtom (lpobj->aObjName);
  395. lpobj->aObjName = GlobalAddAtom (lpNewName);
  396. return OLE_OK;
  397. }
  398. BOOL QueryHandler(
  399. UINT cfFormat
  400. ){
  401. HANDLE hInfo = NULL;
  402. LPSTR lpInfo = NULL;
  403. BOOL fRet = FALSE, fOpen = FALSE;
  404. LONG cb = MAX_STR;
  405. char str[MAX_STR];
  406. HKEY hKey;
  407. // we don't have the client app window handle, use the screen handle
  408. fOpen = OpenClipboard (NULL);
  409. if (!(hInfo = GetClipboardData (cfFormat)))
  410. goto errRtn;
  411. if (!(lpInfo = GlobalLock(hInfo)))
  412. goto errRtn;
  413. // First string of lpInfo is CLASS. See whether any handler is installed
  414. // for this class.
  415. lstrcpy (str, lpInfo);
  416. lstrcat (str, "\\protocol\\StdFileEditing\\handler");
  417. if (RegOpenKey (HKEY_CLASSES_ROOT, str, &hKey))
  418. goto errRtn;
  419. RegCloseKey (hKey);
  420. fRet = TRUE;
  421. errRtn:
  422. if (lpInfo)
  423. GlobalUnlock (hInfo);
  424. if (fOpen)
  425. CloseClipboard();
  426. return fRet;
  427. }
  428. OLESTATUS INTERNAL FileExists (
  429. LPOBJECT_LE lpobj
  430. ){
  431. char filename[MAX_STR];
  432. OFSTRUCT ofstruct;
  433. if (!GlobalGetAtomName (lpobj->topic, filename, MAX_STR))
  434. return OLE_ERROR_MEMORY;
  435. // For package with link we append "/LINK" to the filename. We don't want
  436. // to check for it's existence here.
  437. if (lpobj->app != aPackage) {
  438. // when OF_EXIST is specified, file is opened and closed immediately
  439. if (OpenFile (filename, &ofstruct, OF_EXIST) == -1)
  440. return OLE_ERROR_OPEN;
  441. }
  442. return OLE_OK;
  443. }
  444. BOOL FARINTERNAL UtilQueryProtocol (
  445. LPOBJECT_LE lpobj,
  446. LPCSTR lpprotocol
  447. ){
  448. char buf[MAX_STR];
  449. ATOM aExe;
  450. if (!GlobalGetAtomName (lpobj->app, (LPSTR) buf, MAX_STR))
  451. return FALSE;
  452. if (!QueryApp (buf, lpprotocol, (LPSTR) buf))
  453. return FALSE;
  454. aExe = GlobalAddAtom (buf);
  455. if (aExe)
  456. GlobalDeleteAtom (aExe);
  457. if (aExe != lpobj->aServer)
  458. return FALSE;
  459. return TRUE;
  460. }
  461. #ifdef WIN16
  462. WORD FARINTERNAL FarCheckPointer (lp, iAccessType)
  463. LPVOID lp;
  464. int iAccessType;
  465. {
  466. return (CheckPointer (lp, iAccessType));
  467. }
  468. #endif
  469. DWORD PASCAL FAR DllPut (
  470. LPOLESTREAM lpstream,
  471. OLE_CONST void FAR *lpstr,
  472. DWORD dwSize
  473. ){
  474. UNREFERENCED_PARAMETER(lpstream);
  475. UNREFERENCED_PARAMETER(lpstr);
  476. dwObjSize += dwSize;
  477. return dwSize;
  478. }
  479. OLESTATUS FARINTERNAL ObjQueryType (
  480. LPOLEOBJECT lpobj,
  481. LPLONG lptype
  482. ){
  483. Puts("ObjQueryType");
  484. if (lpobj->ctype != CT_STATIC)
  485. return OLE_ERROR_OBJECT;
  486. *lptype = lpobj->ctype;
  487. return OLE_OK;
  488. }
  489. OLESTATUS FARINTERNAL ObjQuerySize (
  490. LPOLEOBJECT lpobj,
  491. DWORD FAR * lpdwSize
  492. ){
  493. Puts("ObjQuerySize");
  494. *lpdwSize = dwObjSize = 0;
  495. if ((*lpobj->lpvtbl->SaveToStream) (lpobj, &dllStream) == OLE_OK) {
  496. *lpdwSize = dwObjSize;
  497. return OLE_OK;
  498. }
  499. return OLE_ERROR_BLANK;
  500. }
  501. BOOL FARINTERNAL IsObjectBlank (
  502. LPOBJECT_LE lpobj
  503. ){
  504. LPOLEOBJECT lpPictObj;
  505. BOOL retval=FALSE;
  506. // Cleaner way is to provide a method like QueryBlank()
  507. if (!lpobj->hnative)
  508. return TRUE;
  509. if (!(lpPictObj = lpobj->lpobjPict))
  510. return FALSE;
  511. if (lpPictObj->lpvtbl == (LPOLEOBJECTVTBL)&vtblMF)
  512. retval = (((LPOBJECT_MF)lpPictObj)->hmfp != NULL);
  513. else if (lpPictObj->lpvtbl == (LPOLEOBJECTVTBL)&vtblBM)
  514. retval = (((LPOBJECT_BM)lpPictObj)->hBitmap != NULL);
  515. if (lpPictObj->lpvtbl == (LPOLEOBJECTVTBL)&vtblDIB)
  516. retval = (((LPOBJECT_DIB)lpPictObj)->hDIB != NULL);
  517. if (lpPictObj->lpvtbl == (LPOLEOBJECTVTBL)&vtblGEN)
  518. retval = (((LPOBJECT_GEN)lpPictObj)->hData != NULL);
  519. return retval;
  520. }
  521. BOOL FAR PASCAL OleIsDcMeta (HDC hdc)
  522. {
  523. #ifdef WIN16
  524. if (!bWLO && (wWinVer == 0x0003)) {
  525. WORD wDsAlias, wGDIcs = HIWORD(SaveDC);
  526. WORD wOffset = LOWORD(((DWORD)SaveDC));
  527. WORD FAR PASCAL AllocCStoDSAlias (WORD);
  528. WORD FAR PASCAL FreeSelector (WORD);
  529. if (!wGDIds) {
  530. wDsAlias = AllocCStoDSAlias (wGDIcs);
  531. wGDIds = GetGDIds (MAKELONG(wOffset, wDsAlias));
  532. FreeSelector (wDsAlias);
  533. }
  534. return IsMetaDC (hdc, wGDIds);
  535. }
  536. else
  537. #endif
  538. return (GetDeviceCaps (hdc, TECHNOLOGY) == DT_METAFILE);
  539. }
  540. void ConvertBM32to16(
  541. LPBITMAP lpsrc,
  542. LPWIN16BITMAP lpdest
  543. ){
  544. #ifdef WIN32
  545. lpdest->bmType = (short)lpsrc->bmType;
  546. lpdest->bmWidth = (short)lpsrc->bmWidth;
  547. lpdest->bmHeight = (short)lpsrc->bmHeight;
  548. lpdest->bmWidthBytes = (short)lpsrc->bmWidthBytes;
  549. lpdest->bmPlanes = (BYTE)lpsrc->bmPlanes;
  550. lpdest->bmBitsPixel = (BYTE)lpsrc->bmBitsPixel;
  551. #endif
  552. #ifdef WIN16
  553. *lpdest = *lpsrc;
  554. #endif
  555. }
  556. void ConvertBM16to32(
  557. LPWIN16BITMAP lpsrc,
  558. LPBITMAP lpdest
  559. ){
  560. #ifdef WIN32
  561. lpdest->bmType = MAKELONG(lpsrc->bmType,NULL_WORD);
  562. lpdest->bmWidth = MAKELONG(lpsrc->bmWidth,NULL_WORD);
  563. lpdest->bmHeight = MAKELONG(lpsrc->bmHeight,NULL_WORD);
  564. lpdest->bmWidthBytes = MAKELONG(lpsrc->bmWidthBytes,NULL_WORD);
  565. lpdest->bmPlanes = (WORD)lpsrc->bmPlanes;
  566. lpdest->bmBitsPixel = (WORD)lpsrc->bmBitsPixel;
  567. #endif
  568. #ifdef WIN16
  569. *lpdest = *lpsrc;
  570. #endif
  571. }
  572. void ConvertMF16to32(
  573. LPWIN16METAFILEPICT lpsrc,
  574. LPMETAFILEPICT lpdest
  575. ){
  576. #ifdef WIN32
  577. lpdest->mm = (DWORD)lpsrc->mm;
  578. lpdest->xExt = (DWORD)MAKELONG(lpsrc->xExt,NULL_WORD);
  579. lpdest->yExt = (DWORD)MAKELONG(lpsrc->yExt,NULL_WORD);
  580. #endif
  581. #ifdef WIN16
  582. *lpdest = *lpsrc;
  583. #endif
  584. }
  585. void ConvertMF32to16(
  586. LPMETAFILEPICT lpsrc,
  587. LPWIN16METAFILEPICT lpdest
  588. ){
  589. #ifdef WIN32
  590. lpdest->mm = (short)lpsrc->mm;
  591. lpdest->xExt = (short)lpsrc->xExt;
  592. lpdest->yExt = (short)lpsrc->yExt;
  593. #endif
  594. #ifdef WIN16
  595. *lpdest = *lpsrc;
  596. #endif
  597. }
  598. DWORD INTERNAL GetFileVersion(LPOLEOBJECT lpoleobj)
  599. {
  600. if (lpoleobj->lhclientdoc)
  601. return ((LPCLIENTDOC)(lpoleobj->lhclientdoc))->dwFileVer;
  602. if (lpoleobj->lpParent)
  603. return GetFileVersion(lpoleobj->lpParent);
  604. return (DWORD)MAKELONG(wReleaseVer,OS_WIN32);
  605. }