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.

781 lines
20 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: MAIN.C
  3. *
  4. * PURPOSE: WinMain, WEP and some other misc routines
  5. *
  6. * Created: 1991
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Srinik (04/01/91) Pulled some routines, into this, from ole.c.
  12. *
  13. \***************************************************************************/
  14. #include <windows.h>
  15. #include <shellapi.h>
  16. #include "dll.h"
  17. #ifndef WF_WLO
  18. #define WF_WLO 0x8000
  19. #endif
  20. // ordinal number new win31 API IsTask
  21. #define ORD_IsTask 320
  22. #define NUM_DLL 30 /* space for this many DLL_ENTRYs is created on */
  23. /* each alloc/realloc */
  24. OLECLIPFORMAT cfOwnerLink = 0; // global variables for clip frmats
  25. OLECLIPFORMAT cfObjectLink = 0;
  26. OLECLIPFORMAT cfLink = 0;
  27. OLECLIPFORMAT cfNative = 0;
  28. OLECLIPFORMAT cfBinary = 0;
  29. OLECLIPFORMAT cfFileName = 0;
  30. OLECLIPFORMAT cfNetworkName = 0;
  31. ATOM aStdHostNames;
  32. ATOM aStdTargetDevice ;
  33. ATOM aStdDocDimensions;
  34. ATOM aStdDocName;
  35. ATOM aStdColorScheme;
  36. ATOM aNullArg = 0;
  37. ATOM aSave;
  38. ATOM aChange;
  39. ATOM aClose;
  40. ATOM aSystem;
  41. ATOM aOle;
  42. ATOM aClipDoc;
  43. ATOM aPackage;
  44. // Used in work around for MSDraw bug
  45. ATOM aMSDraw;
  46. extern LPCLIENTDOC lpHeadDoc;
  47. extern LPCLIENTDOC lpTailDoc;
  48. extern RENDER_ENTRY stdRender[];
  49. HANDLE hInstDLL;
  50. BOOL bProtMode;
  51. BOOL bWLO = FALSE;
  52. /* HANDLE hDllTable; !!! Add this when bug in WEP is fixed */
  53. DLL_ENTRY lpDllTable[NUM_DLL]; //!!! change this when WEP bug is fixed
  54. DWORD dllTableSize;
  55. int iLast = 0;
  56. int iMax = NUM_DLL -1;
  57. int iUnloadableDll = NULL; // index to handler than can be freed up
  58. char packageClass[] = "Package";
  59. // For QuerySize() API & methods.
  60. extern OLESTREAMVTBL dllStreamVtbl;
  61. extern CLIENTDOC lockDoc;
  62. #ifdef FIREWALLS
  63. BOOL bShowed = FALSE;
  64. char szDebugBuffer[80];
  65. short ole_flags;
  66. void FARINTERNAL ShowVersion (void);
  67. void FARINTERNAL SetOleFlags(void);
  68. #endif
  69. // LOWWORD - BYTE 0 major verision, BYTE1 minor version,
  70. // HIWORD reserved
  71. DWORD dwOleVer = 0x2001L; // change this when we want to update dll version
  72. // number
  73. DWORD dwVerToFile = 0x0501L; // This is used while object is being saved to
  74. // file. There is no need to change this value
  75. // whenever we change ole dll version number
  76. static BOOL bLibInit = FALSE;
  77. WORD wWinVer;
  78. HANDLE hModule;
  79. #define MAX_HIMETRIC 0x7FFF
  80. int maxPixelsX = MAX_HIMETRIC;
  81. int maxPixelsY = MAX_HIMETRIC;
  82. void SetMaxPixel (void);
  83. VOID FAR PASCAL WEP (int);
  84. #pragma alloc_text(WEP_TEXT, WEP)
  85. FARPROC lpfnIsTask = NULL; // the API IsTask() became available from
  86. // win31 onwards, hence we are trying to
  87. // get it's address through GetProcAddress
  88. //////////////////////////////////////////////////////////////////////////////
  89. //
  90. // int FAR PASCAL LibMain (hInst, wDataSeg, cbHeapSize, lpszCmdLine)
  91. //
  92. // The main library entry point. This routine is called when the library
  93. // is loaded.
  94. //
  95. // Arguments:
  96. //
  97. // hInst - dll's instance handle
  98. // wDataSeg - DS register value
  99. // cbHeapSize - heap size defined def file
  100. // lpszCmdLine - command line info
  101. //
  102. // Returns:
  103. //
  104. // 0 - failure
  105. // 1 - success
  106. //
  107. // Effects:
  108. //
  109. //////////////////////////////////////////////////////////////////////////////
  110. int FAR PASCAL LibMain (hInst, wDataSeg, cbHeapSize, lpszCmdLine)
  111. HANDLE hInst;
  112. WORD wDataSeg;
  113. WORD cbHeapSize;
  114. LPSTR lpszCmdLine;
  115. {
  116. WNDCLASS wc;
  117. int i;
  118. Puts("LibMain");
  119. #ifdef FIREWALLS
  120. SetOleFlags();
  121. #endif
  122. bLibInit = TRUE;
  123. hInstDLL = hInst;
  124. hModule = GetModuleHandle ("OLECLI");
  125. bProtMode = (BOOL) (GetWinFlags() & WF_PMODE);
  126. bWLO = (BOOL) (GetWinFlags() & WF_WLO);
  127. wWinVer = (WORD) GetVersion();
  128. // REGISTER LINK FORMAT
  129. cfObjectLink = RegisterClipboardFormat("ObjectLink");
  130. cfLink = RegisterClipboardFormat("Link");
  131. cfOwnerLink = RegisterClipboardFormat("OwnerLink");
  132. cfNative = RegisterClipboardFormat("Native");
  133. cfBinary = RegisterClipboardFormat("Binary");
  134. cfFileName = RegisterClipboardFormat("FileName");
  135. cfNetworkName = RegisterClipboardFormat("NetworkName");
  136. if (!(cfObjectLink && cfOwnerLink && cfNative && cfLink))
  137. return 0;
  138. // SET UP OLEWNDCLASS
  139. wc.style = NULL;
  140. wc.lpfnWndProc = DocWndProc;
  141. wc.cbClsExtra = 0;
  142. wc.cbWndExtra = sizeof(LONG); //we are storing longs
  143. wc.hInstance = hInst;
  144. wc.hIcon = NULL;
  145. wc.hCursor = NULL;
  146. wc.hbrBackground= NULL;
  147. wc.lpszMenuName = NULL;
  148. wc.lpszClassName= "OleDocWndClass";
  149. if (!RegisterClass(&wc))
  150. return 0;
  151. wc.lpfnWndProc = SrvrWndProc;
  152. wc.lpszClassName = "OleSrvrWndClass";
  153. if (!RegisterClass(&wc))
  154. return 0;
  155. /*
  156. // !!! Add this when bug in WEP is fixed.
  157. // Allocate memory for DLL table
  158. dllTableSize = NUM_DLL * sizeof(DLL_ENTRY);
  159. if (!(hDllTable = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT,
  160. dllTableSize)))
  161. return 0;
  162. if (!(lpDllTable = (DLL_ENTRY FAR *) GlobalLock (hDllTable)))
  163. return 0;
  164. */
  165. // !!! remove the following when WEP bug is fixed
  166. for (i = 0; i < NUM_DLL; i++)
  167. lpDllTable[i].aDll = 0;
  168. // !!! BEGIN hack for Pbrush.
  169. lpDllTable[0].hDll = NULL;
  170. lpDllTable[0].aDll = GlobalAddAtom ((LPSTR) "ole");
  171. lpDllTable[0].Load = PbLoadFromStream;
  172. lpDllTable[0].Clip = PbCreateFromClip;
  173. lpDllTable[0].Link = PbCreateLinkFromClip;
  174. lpDllTable[0].Create = PbCreate;
  175. lpDllTable[0].CreateFromTemplate = PbCreateFromTemplate;
  176. lpDllTable[0].CreateFromFile = PbCreateFromFile;
  177. lpDllTable[0].CreateLinkFromFile = PbCreateLinkFromFile;
  178. lpDllTable[0].CreateInvisible = PbCreateInvisible;
  179. // !!! END hack for pbrush
  180. // For ObjectSize API
  181. dllStream.lpstbl = (LPOLESTREAMVTBL) &dllStreamVtbl;
  182. dllStream.lpstbl->Put = DllPut;
  183. // add the atoms required.
  184. aStdDocName = GlobalAddAtom ((LPSTR)"StdDocumentName");
  185. aSave = GlobalAddAtom ((LPSTR)"Save");
  186. aChange = GlobalAddAtom ((LPSTR)"Change");
  187. aClose = GlobalAddAtom ((LPSTR)"Close");
  188. aSystem = GlobalAddAtom ((LPSTR)"System");
  189. aOle = GlobalAddAtom ((LPSTR)"OLEsystem");
  190. aPackage = GlobalAddAtom ((LPSTR) packageClass);
  191. // Used in work around for MSDraw bug
  192. aMSDraw = GlobalAddAtom ((LPSTR) "MSDraw");
  193. // clipboard document name atom
  194. aClipDoc = GlobalAddAtom ((LPSTR)"Clipboard");
  195. stdRender[0].aClass = GlobalAddAtom ("METAFILEPICT");
  196. stdRender[1].aClass = GlobalAddAtom ("DIB");
  197. stdRender[2].aClass = GlobalAddAtom ("BITMAP");
  198. SetMaxPixel();
  199. if (wWinVer != 0x0003) {
  200. HANDLE hModule;
  201. if (hModule = GetModuleHandle ("KERNEL"))
  202. lpfnIsTask = GetProcAddress (hModule,
  203. (LPSTR) MAKELONG (ORD_IsTask, 0));
  204. }
  205. if (cbHeapSize != 0)
  206. UnlockData(0);
  207. return 1;
  208. }
  209. //////////////////////////////////////////////////////////////////////////////
  210. //
  211. // VOID FAR PASCAL WEP (nParameter)
  212. //
  213. // Called just before the library is being unloaded. Delete all the atoms
  214. // added by this dll and also frees up all unloaded handler dlls.
  215. //
  216. // Arguments:
  217. //
  218. // nParameter - Termination code
  219. //
  220. // Returns:
  221. //
  222. // none
  223. //
  224. // Effects:
  225. //
  226. //////////////////////////////////////////////////////////////////////////////
  227. VOID FAR PASCAL WEP (nParameter)
  228. int nParameter;
  229. {
  230. int i;
  231. Puts("LibExit");
  232. // case when the DLLs are missing
  233. if (!bLibInit)
  234. return;
  235. if (nParameter == WEP_SYSTEM_EXIT)
  236. DEBUG_OUT ("---L&E DLL EXIT on system exit---",0)
  237. else if (nParameter == WEP_FREE_DLL)
  238. DEBUG_OUT ("---L&E DLL EXIT---\n",0)
  239. else
  240. return;
  241. // Delete atoms added by us
  242. for (i = 0; i < NUM_RENDER; i++) {
  243. if (stdRender[i].aClass)
  244. GlobalDeleteAtom (stdRender[i].aClass);
  245. }
  246. if (aStdDocName)
  247. GlobalDeleteAtom (aStdDocName);
  248. if (aSave)
  249. GlobalDeleteAtom (aSave);
  250. if (aChange)
  251. GlobalDeleteAtom (aChange);
  252. if (aClose)
  253. GlobalDeleteAtom (aClose);
  254. if (aSystem)
  255. GlobalDeleteAtom (aSystem);
  256. if (aOle)
  257. GlobalDeleteAtom (aOle);
  258. if (aPackage)
  259. GlobalDeleteAtom (aPackage);
  260. if (aClipDoc)
  261. GlobalDeleteAtom (aClipDoc);
  262. if (aMSDraw)
  263. GlobalDeleteAtom (aMSDraw);
  264. // Free handler dlls if there are any still loaded. Entry 0 is used for
  265. // Pbrush handler which is part of this dll.
  266. for (i = 0; i <= iLast; i++) {
  267. if (lpDllTable[i].aDll)
  268. GlobalDeleteAtom (lpDllTable[i].aDll);
  269. if (lpDllTable[i].hDll)
  270. FreeLibrary (lpDllTable[i].hDll);
  271. }
  272. #ifdef FIREWALLS
  273. ASSERT(!lpHeadDoc, "Some client doc structures are not deleted");
  274. ASSERT(!lockDoc.lpHeadObj, "Some servers are left in a locked state");
  275. #endif
  276. /* !!! Add this when bug in WEP is fixed
  277. if (lpDllTable)
  278. GlobalUnlock (hDllTable);
  279. if (hDllTable)
  280. GlobalFree (hDllTable);
  281. */
  282. }
  283. //////////////////////////////////////////////////////////////////////////////
  284. //
  285. // void FARINTERNAL SetOleFlags()
  286. //
  287. // Sets the debug level flags for controlling the level of debug information
  288. // on the comm terminal. This will be included only in the debug version.
  289. //
  290. // Arguments:
  291. //
  292. // none
  293. //
  294. // Returns:
  295. //
  296. // none
  297. //
  298. // Effects:
  299. //
  300. //////////////////////////////////////////////////////////////////////////////
  301. #ifdef FIREWALLS
  302. void FARINTERNAL SetOleFlags()
  303. {
  304. char buffer[80];
  305. if(GetProfileString ("OLE",
  306. "Puts","", (LPSTR)buffer, 80))
  307. ole_flags = DEBUG_PUTS;
  308. else
  309. ole_flags = 0;
  310. if(GetProfileString ("OLE",
  311. "DEBUG_OUT","", (LPSTR)buffer, 80))
  312. ole_flags |= DEBUG_DEBUG_OUT;
  313. if(GetProfileString ("OLE",
  314. "MESSAGEBOX","", (LPSTR)buffer, 80))
  315. ole_flags |= DEBUG_MESSAGEBOX;
  316. }
  317. //////////////////////////////////////////////////////////////////////////////
  318. //
  319. // void FARINTERNAL ShowVersion (void)
  320. //
  321. // Displays version, date, time and copyright info in client app's window.
  322. // Called by all the object create functions after checking the flag bShowed.
  323. // This will be included only in the debug version.
  324. //
  325. // Arguments:
  326. //
  327. // none
  328. //
  329. // Returns:
  330. //
  331. // none
  332. //
  333. // Effects:
  334. //
  335. // sets bShowed
  336. //
  337. //////////////////////////////////////////////////////////////////////////////
  338. void FARINTERNAL ShowVersion ()
  339. {
  340. if (!bShowed && (ole_flags & DEBUG_MESSAGEBOX)) {
  341. MessageBox (NULL, "\
  342. VER: 1.09.000\n\
  343. TIME: 16:00:00\n\
  344. DATE: 01/31/1992\n\
  345. Copyright (c) 1990, 1991 Microsoft Corp.\n\
  346. All Rights Reserved.",
  347. "Ole Client Library",
  348. MB_OK | MB_TASKMODAL);
  349. bShowed = TRUE;
  350. }
  351. }
  352. #endif
  353. int FARINTERNAL LoadDll (lpClass)
  354. LPSTR lpClass;
  355. {
  356. char str[MAX_STR];
  357. char str1[MAX_STR];
  358. ATOM aDll = NULL;
  359. int index;
  360. int iEmpty;
  361. BOOL found = FALSE;
  362. HANDLE hDll;
  363. int refcnt;
  364. LONG cb = MAX_STR;
  365. if (!lstrcmpi (lpClass, "Pbrush"))
  366. return 0;
  367. lstrcpy (str, lpClass);
  368. lstrcat (str, "\\protocol\\StdFileEditing\\handler");
  369. if (RegQueryValue (HKEY_CLASSES_ROOT, str, str1, &cb))
  370. return INVALID_INDEX;
  371. if (aDll = GlobalFindAtom (str1)) {
  372. for (index = 1; index <= iLast; index++) {
  373. if (lpDllTable[index].aDll == aDll) { // Dll already loaded
  374. lpDllTable[index].cObj ++;
  375. if (index == iUnloadableDll) {
  376. // since the object count is not zero anymore, this
  377. // handler can not be freed up.
  378. iUnloadableDll = NULL;
  379. }
  380. return index;
  381. }
  382. }
  383. }
  384. aDll = GlobalAddAtom (str1);
  385. // Look for an empty entry
  386. for (iEmpty = 1; iEmpty <= iLast; iEmpty++) {
  387. if (!lpDllTable[iEmpty].aDll) {
  388. found = TRUE;
  389. break;
  390. }
  391. }
  392. if (iEmpty > iMax)
  393. goto errLoad;
  394. /*
  395. if (!found) {// no empty entry exists create a new one if necessary.
  396. if (iEmpty > iMax) {
  397. dllTableSize += (blockSize = NUM_DLL * sizeof(DLL_ENTRY));
  398. hTable = GlobalReAlloc (hDllTable, dllTableSize,
  399. GMEM_MOVEABLE | GMEM_ZEROINIT);
  400. if (hTable == hDllTable)
  401. iMax += NUM_DLL;
  402. else {
  403. dllTableSize -= blockSize;
  404. iEmpty = INVALID_INDEX;
  405. }
  406. }
  407. }
  408. */
  409. // !!! reference count of OLECLI is increasing by 2 when the handlers are
  410. // are loaded, looks like windows bug. Following is a temporary fix.
  411. refcnt = GetModuleUsage (hModule);
  412. hDll = LoadLibrary ((LPSTR) str1);
  413. refcnt = (GetModuleUsage (hModule) - refcnt);
  414. while (refcnt > 1) {
  415. FreeModule (hModule);
  416. refcnt--;
  417. }
  418. if (hDll < 32)
  419. goto errLoad;
  420. if (!(lpDllTable[iEmpty].Load = GetProcAddress (hDll,
  421. "DllLoadFromStream")))
  422. goto errLoad;
  423. if (!(lpDllTable[iEmpty].Clip = GetProcAddress (hDll,
  424. "DllCreateFromClip")))
  425. goto errLoad;
  426. if (!(lpDllTable[iEmpty].Link = GetProcAddress (hDll,
  427. "DllCreateLinkFromClip")))
  428. goto errLoad;
  429. if (!(lpDllTable[iEmpty].CreateFromTemplate = GetProcAddress (hDll,
  430. "DllCreateFromTemplate")))
  431. goto errLoad;
  432. if (!(lpDllTable[iEmpty].Create = GetProcAddress (hDll, "DllCreate")))
  433. goto errLoad;
  434. if (!(lpDllTable[iEmpty].CreateFromFile = GetProcAddress (hDll,
  435. "DllCreateFromFile")))
  436. goto errLoad;
  437. if (!(lpDllTable[iEmpty].CreateLinkFromFile = GetProcAddress (hDll,
  438. "DllCreateLinkFromFile")))
  439. goto errLoad;
  440. lpDllTable[iEmpty].CreateInvisible = GetProcAddress (hDll,
  441. "DllCreateInvisible");
  442. lpDllTable[iEmpty].aDll = aDll;
  443. lpDllTable[iEmpty].cObj = 1;
  444. lpDllTable[iEmpty].hDll = hDll;
  445. if (iEmpty > iLast)
  446. iLast++;
  447. return iEmpty;
  448. errLoad:
  449. if (aDll)
  450. GlobalDeleteAtom (aDll);
  451. if (hDll >= 32)
  452. FreeLibrary (hDll);
  453. return INVALID_INDEX;
  454. }
  455. // unload the the handler that can be free up (whose object count is NULL)
  456. void FARINTERNAL UnloadDll ()
  457. {
  458. if (!iUnloadableDll)
  459. return;
  460. if (iUnloadableDll == iLast)
  461. iLast--;
  462. if (lpDllTable[iUnloadableDll].aDll)
  463. GlobalDeleteAtom (lpDllTable[iUnloadableDll].aDll);
  464. lpDllTable[iUnloadableDll].aDll = NULL;
  465. FreeLibrary (lpDllTable[iUnloadableDll].hDll);
  466. lpDllTable[iUnloadableDll].hDll = NULL;
  467. iUnloadableDll = NULL;
  468. }
  469. //
  470. // Reduce the object count of the handler, refered to by the index, by one.
  471. // If the object count becomes NULL, free up the handler that is ready to be
  472. // freed (refered to by index iUnloadableDll), and then make this handler the
  473. // freeable one.
  474. //
  475. // As you can see we are trying to implement a simple mechanism of caching.
  476. //
  477. void FARINTERNAL DecreaseHandlerObjCount (iTable)
  478. int iTable;
  479. {
  480. if (!iTable)
  481. return;
  482. if (iTable != INVALID_INDEX) {
  483. ASSERT (lpDllTable[iTable].cObj, "Handler Obj count is already NULL");
  484. if (!--lpDllTable[iTable].cObj) {
  485. UnloadDll ();
  486. iUnloadableDll = iTable;
  487. }
  488. }
  489. }
  490. /***************************** Public Function ****************************\
  491. *
  492. * OLESTATUS FARINTERNAL CreatePictFromClip (lpclient, lhclientdoc, lpobjname, lplpoleobject, optRender, cfFormat, lpClass, ctype)
  493. *
  494. * CreatePictFromClip: This function creates the LP to an object
  495. * from the clipboard. It will try to create a static picture object if
  496. * it understands any rendering formats on the clipboard. Currently, it
  497. * understands only bitmaps and metafiles.
  498. *
  499. * Effects:
  500. *
  501. * History:
  502. * Wrote it.
  503. \***************************************************************************/
  504. OLESTATUS FARINTERNAL CreatePictFromClip (lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat, lpClass, objType)
  505. LPOLECLIENT lpclient;
  506. LHCLIENTDOC lhclientdoc;
  507. LPSTR lpobjname;
  508. LPOLEOBJECT FAR * lplpobj;
  509. OLEOPT_RENDER optRender;
  510. OLECLIPFORMAT cfFormat;
  511. LPSTR lpClass;
  512. LONG objType;
  513. {
  514. OLESTATUS retVal = OLE_ERROR_OPTION;
  515. *lplpobj = NULL;
  516. if (optRender == olerender_none)
  517. return OLE_OK;
  518. else if (optRender == olerender_format) {
  519. switch (cfFormat) {
  520. case NULL:
  521. return OLE_ERROR_FORMAT;
  522. case CF_METAFILEPICT:
  523. return MfPaste (lpclient, lhclientdoc, lpobjname,
  524. lplpobj, objType);
  525. case CF_DIB:
  526. return DibPaste (lpclient, lhclientdoc, lpobjname,
  527. lplpobj, objType);
  528. case CF_BITMAP:
  529. return BmPaste (lpclient, lhclientdoc, lpobjname,
  530. lplpobj, objType);
  531. default:
  532. return GenPaste (lpclient, lhclientdoc, lpobjname, lplpobj,
  533. lpClass, cfFormat, objType);
  534. }
  535. }
  536. else if (optRender == olerender_draw) {
  537. cfFormat = EnumClipboardFormats (NULL);
  538. while ((cfFormat) && (retVal > OLE_WAIT_FOR_RELEASE)) {
  539. switch (cfFormat) {
  540. case CF_METAFILEPICT:
  541. retVal = MfPaste (lpclient, lhclientdoc,
  542. lpobjname, lplpobj, objType);
  543. break;
  544. case CF_DIB:
  545. retVal = DibPaste (lpclient, lhclientdoc,
  546. lpobjname, lplpobj, objType);
  547. break;
  548. case CF_BITMAP:
  549. retVal = BmPaste (lpclient, lhclientdoc,
  550. lpobjname, lplpobj, objType);
  551. break;
  552. }
  553. cfFormat = EnumClipboardFormats (cfFormat);
  554. }
  555. }
  556. return retVal;
  557. }
  558. OLESTATUS FARINTERNAL CreatePackageFromClip (lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat, objType)
  559. LPOLECLIENT lpclient;
  560. LHCLIENTDOC lhclientdoc;
  561. LPSTR lpobjname;
  562. LPOLEOBJECT FAR * lplpobj;
  563. OLEOPT_RENDER optRender;
  564. OLECLIPFORMAT cfFormat;
  565. LONG objType;
  566. {
  567. char file[MAX_STR+6];
  568. HANDLE hData;
  569. LPSTR lpFileName;
  570. if (!(hData = GetClipboardData (cfFileName))
  571. || !(lpFileName = GlobalLock (hData)))
  572. return OLE_ERROR_CLIPBOARD;
  573. if (objType == OT_LINK) {
  574. lstrcpy (file, lpFileName);
  575. lstrcat (file, "/Link");
  576. lpFileName = (LPSTR) file;
  577. }
  578. GlobalUnlock (hData);
  579. return CreateEmbLnkFromFile (lpclient, packageClass, lpFileName,
  580. NULL, lhclientdoc, lpobjname, lplpobj,
  581. optRender, cfFormat, OT_EMBEDDED);
  582. }
  583. void FARINTERNAL RemoveLinkStringFromTopic (lpobj)
  584. LPOBJECT_LE lpobj;
  585. {
  586. char buf[MAX_STR+6];
  587. int i = 0;
  588. if (GlobalGetAtomName (lpobj->topic, buf, sizeof(buf))) {
  589. // scan the topic for "/Link"
  590. while (buf[i] != '/') {
  591. if (!buf[i])
  592. return;
  593. i++;
  594. }
  595. buf[i] = '\0';
  596. if (lpobj->topic)
  597. GlobalDeleteAtom (lpobj->topic);
  598. lpobj->topic = GlobalAddAtom (buf);
  599. }
  600. }
  601. void SetMaxPixel ()
  602. {
  603. HDC hdc;
  604. // find out the pixel equivalent of MAX_HIMETRIC in X and Y directions
  605. if (hdc = GetDC (NULL)) {
  606. maxPixelsX = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSX),
  607. 2540);
  608. maxPixelsY = MulDiv (MAX_HIMETRIC, GetDeviceCaps(hdc, LOGPIXELSY),
  609. 2540);
  610. ReleaseDC (NULL, hdc);
  611. }
  612. }