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.

788 lines
19 KiB

  1. /* (C) Copyright Microsoft Corporation 1991-1994. All Rights Reserved */
  2. //
  3. // FILE: oleglue.c
  4. //
  5. // NOTES: OLE-related outbound references from SoundRecorder
  6. //
  7. #include <windows.h>
  8. #include <windowsx.h>
  9. #include <mmsystem.h>
  10. #include <shellapi.h>
  11. #include <objbase.h>
  12. #define INCLUDE_OLESTUBS
  13. #include "soundrec.h"
  14. #include "srecids.h"
  15. //
  16. // GLOBALS
  17. //
  18. // should unify state variables and put globals into a single location
  19. DWORD dwOleBuildVersion = 0; // OLE library version number
  20. BOOL gfOleInitialized = FALSE; // did OleInitialize succeed?
  21. BOOL gfStandalone = FALSE; // status, are we a non-embedded object
  22. BOOL gfEmbedded = FALSE; // were we invoked with an -Embedding flag?
  23. BOOL gfLinked = FALSE; // are we a linked object?
  24. BOOL gfTerminating = FALSE; // has TerminateServer been called?
  25. BOOL gfHideAfterPlaying = FALSE;
  26. BOOL gfShowWhilePlaying = TRUE;
  27. BOOL gfCloseAtEndOfPlay = FALSE;
  28. TCHAR gachLinkFilename[_MAX_PATH];
  29. BOOL gfClosing = FALSE;
  30. int giExtWidth; // Metafile extent width
  31. int giExtHeight; // Metafile extent height
  32. //
  33. // Utility functions ported from old OLE1 code
  34. //
  35. /*
  36. * DibFromBitmap()
  37. *
  38. * Will create a global memory block in DIB format that represents the DDB
  39. * passed in
  40. *
  41. */
  42. #define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
  43. HANDLE FAR PASCAL DibFromBitmap(HBITMAP hbm, HPALETTE hpal, HANDLE hMem)
  44. {
  45. BITMAP bm;
  46. BITMAPINFOHEADER bi;
  47. BITMAPINFOHEADER FAR *lpbi;
  48. DWORD dw;
  49. HANDLE hdib = NULL;
  50. HDC hdc;
  51. HPALETTE hpalT;
  52. if (!hbm)
  53. return NULL;
  54. GetObject(hbm,sizeof(bm),&bm);
  55. bi.biSize = sizeof(BITMAPINFOHEADER);
  56. bi.biWidth = bm.bmWidth;
  57. bi.biHeight = bm.bmHeight;
  58. bi.biPlanes = 1;
  59. bi.biBitCount = (bm.bmPlanes * bm.bmBitsPixel) > 8 ? 24 : 8;
  60. bi.biCompression = BI_RGB;
  61. bi.biSizeImage = (DWORD)WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight;
  62. bi.biXPelsPerMeter = 0;
  63. bi.biYPelsPerMeter = 0;
  64. bi.biClrUsed = bi.biBitCount == 8 ? 256 : 0;
  65. bi.biClrImportant = 0;
  66. dw = bi.biSize + bi.biClrUsed * sizeof(RGBQUAD) + bi.biSizeImage;
  67. if (hMem && GlobalSize(hMem) != 0)
  68. {
  69. if (GlobalSize(hMem) < dw)
  70. return NULL;
  71. lpbi = GlobalLock(hMem);
  72. }
  73. else
  74. lpbi = GlobalAllocPtr(GHND | GMEM_DDESHARE, dw);
  75. if (!lpbi)
  76. return NULL;
  77. *lpbi = bi;
  78. hdc = CreateCompatibleDC(NULL);
  79. if (hdc)
  80. {
  81. if (hpal)
  82. {
  83. hpalT = SelectPalette(hdc,hpal,FALSE);
  84. RealizePalette(hdc);
  85. }
  86. GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight,
  87. (LPBYTE)lpbi + (int)lpbi->biSize + (int)lpbi->biClrUsed * sizeof(RGBQUAD),
  88. (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
  89. if (hpal)
  90. SelectPalette(hdc,hpalT,FALSE);
  91. DeleteDC(hdc);
  92. }
  93. hdib = GlobalHandle(lpbi);
  94. GlobalUnlock(hdib);
  95. return hdib;
  96. }
  97. HANDLE GetDIB(HANDLE hMem)
  98. {
  99. HPALETTE hpal = GetStockObject(DEFAULT_PALETTE);
  100. HBITMAP hbm = GetBitmap();
  101. HANDLE hDib = NULL;
  102. if (hbm && hpal)
  103. {
  104. hDib = DibFromBitmap(hbm,hpal,hMem);
  105. if (!hDib)
  106. DOUT(TEXT("DibFromBitmap failed!\r\n"));
  107. }
  108. if (hpal)
  109. DeleteObject(hpal);
  110. if (hbm)
  111. DeleteObject(hbm);
  112. return hDib;
  113. }
  114. HBITMAP
  115. GetBitmap(void)
  116. {
  117. HDC hdcmem = NULL;
  118. HDC hdc = NULL;
  119. HBITMAP hbitmap = NULL;
  120. HBITMAP holdbitmap = NULL;
  121. RECT rc;
  122. hdc = GetDC(ghwndApp);
  123. if (hdc)
  124. {
  125. SetRect(&rc, 0, 0,
  126. GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
  127. hdcmem = CreateCompatibleDC(hdc);
  128. if (hdcmem)
  129. {
  130. hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
  131. holdbitmap = (HBITMAP)SelectObject(hdcmem, hbitmap);
  132. // paint directly into the bitmap
  133. PatBlt(hdcmem, 0, 0, rc.right, rc.bottom, WHITENESS);
  134. DrawIcon(hdcmem, 0, 0, ghiconApp);
  135. hbitmap = (HBITMAP)SelectObject(hdcmem, holdbitmap);
  136. DeleteDC(hdcmem);
  137. }
  138. ReleaseDC(ghwndApp, hdc);
  139. }
  140. return hbitmap;
  141. }
  142. #pragma message("this code should extract the picture from the file")
  143. HANDLE
  144. GetPicture(void)
  145. {
  146. HANDLE hpict = NULL;
  147. HMETAFILE hMF = NULL;
  148. LPMETAFILEPICT lppict = NULL;
  149. HBITMAP hbmT = NULL;
  150. HDC hdcmem = NULL;
  151. HDC hdc = NULL;
  152. BITMAP bm;
  153. HBITMAP hbm;
  154. hbm = GetBitmap();
  155. if (hbm == NULL)
  156. return NULL;
  157. GetObject(hbm, sizeof(bm), (LPVOID)&bm);
  158. hdc = GetDC(ghwndApp);
  159. if (hdc)
  160. {
  161. hdcmem = CreateCompatibleDC(hdc);
  162. ReleaseDC(ghwndApp, hdc);
  163. }
  164. if (!hdcmem)
  165. {
  166. DeleteObject(hbm);
  167. return NULL;
  168. }
  169. hdc = CreateMetaFile(NULL);
  170. hbmT = (HBITMAP)SelectObject(hdcmem, hbm);
  171. SetWindowOrgEx(hdc, 0, 0, NULL);
  172. SetWindowExtEx(hdc, bm.bmWidth, bm.bmHeight, NULL);
  173. StretchBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight,
  174. hdcmem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
  175. hMF = CloseMetaFile(hdc);
  176. SelectObject(hdcmem, hbmT);
  177. DeleteObject(hbm);
  178. DeleteDC(hdcmem);
  179. lppict = (LPMETAFILEPICT)GlobalAllocPtr(GHND|GMEM_DDESHARE
  180. , sizeof(METAFILEPICT));
  181. if (!lppict)
  182. {
  183. if (hMF)
  184. DeleteMetaFile(hMF);
  185. return NULL;
  186. }
  187. hdc = GetDC(ghwndApp);
  188. lppict->mm = MM_ANISOTROPIC;
  189. lppict->hMF = hMF;
  190. lppict->xExt = MulDiv(bm.bmWidth, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
  191. lppict->yExt = MulDiv(bm.bmHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSX));
  192. giExtWidth = lppict->xExt;
  193. giExtHeight = lppict->yExt;
  194. ReleaseDC(ghwndApp, hdc);
  195. hpict = GlobalHandle(lppict);
  196. GlobalUnlock(hpict);
  197. return hpict;
  198. }
  199. //
  200. // Code ported from server.c (OLE1) for serialization...
  201. //
  202. HANDLE GetNativeData(void)
  203. {
  204. LPBYTE lplink = NULL;
  205. MMIOINFO mmioinfo;
  206. HMMIO hmmio;
  207. BOOL fOk;
  208. lplink = (LPBYTE)GlobalAllocPtr(GHND | GMEM_SHARE, 4096L);
  209. if (lplink == NULL)
  210. {
  211. #if DBG
  212. OutputDebugString(TEXT("GetNativeData: malloc failed\r\n"));
  213. #endif
  214. return NULL;
  215. }
  216. mmioinfo.fccIOProc = FOURCC_MEM;
  217. mmioinfo.pIOProc = NULL;
  218. mmioinfo.pchBuffer = lplink;
  219. mmioinfo.cchBuffer = 4096L; // initial size
  220. mmioinfo.adwInfo[0] = 4096L; // grow by this much
  221. hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READWRITE);
  222. if (hmmio == NULL)
  223. {
  224. GlobalFreePtr(lplink);
  225. return NULL;
  226. }
  227. fOk = WriteWaveFile(hmmio
  228. , gpWaveFormat
  229. , gcbWaveFormat
  230. , gpWaveSamples
  231. , glWaveSamplesValid);
  232. mmioGetInfo(hmmio, &mmioinfo, 0);
  233. mmioClose(hmmio,0);
  234. if (fOk)
  235. {
  236. //
  237. // Warning, the buffer we allocated may have been realloc'd
  238. //
  239. HANDLE hlink = GlobalHandle(mmioinfo.pchBuffer);
  240. GlobalUnlock(hlink);
  241. return hlink;
  242. }
  243. else
  244. {
  245. gfErrorBox++;
  246. ErrorResBox( ghwndApp
  247. , ghInst
  248. , MB_ICONEXCLAMATION | MB_OK
  249. , IDS_APPTITLE
  250. , IDS_ERROREMBED
  251. );
  252. #if DBG
  253. OutputDebugString(TEXT("Failed to WriteWaveFile\r\n"));
  254. #endif
  255. gfErrorBox--;
  256. //
  257. // Warning, the buffer we allocated may have been realloc'd
  258. //
  259. if (mmioinfo.pchBuffer)
  260. GlobalFreePtr(mmioinfo.pchBuffer);
  261. return NULL;
  262. }
  263. }
  264. /*
  265. * Called from OLE storage code
  266. */
  267. LPBYTE PutNativeData(LPBYTE lpbData, DWORD dwSize)
  268. {
  269. MMIOINFO mmioinfo;
  270. HMMIO hmmio;
  271. MMRESULT mmr;
  272. LPWAVEFORMATEX pwfx;
  273. DWORD cbwfx;
  274. DWORD cbdata;
  275. LPBYTE pdata;
  276. mmioinfo.fccIOProc = FOURCC_MEM;
  277. mmioinfo.pIOProc = NULL;
  278. mmioinfo.pchBuffer = lpbData;
  279. mmioinfo.cchBuffer = dwSize; // initial size
  280. mmioinfo.adwInfo[0] = 0L; // grow by this much
  281. hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READ);
  282. if (hmmio)
  283. {
  284. mmr = ReadWaveFile(hmmio
  285. , &pwfx
  286. , &cbwfx
  287. , &pdata
  288. , &cbdata
  289. , TEXT("NativeData")
  290. , TRUE);
  291. mmioClose(hmmio,0);
  292. if (mmr != MMSYSERR_NOERROR)
  293. return NULL;
  294. if (pwfx == NULL)
  295. return NULL;
  296. DestroyWave();
  297. gpWaveFormat = pwfx;
  298. gcbWaveFormat = cbwfx;
  299. gpWaveSamples = pdata;
  300. glWaveSamples = cbdata;
  301. }
  302. //
  303. // update state variables
  304. //
  305. glWaveSamplesValid = glWaveSamples;
  306. glWavePosition = 0L;
  307. gfDirty = FALSE;
  308. //
  309. // update the display
  310. //
  311. UpdateDisplay(TRUE);
  312. return (LPBYTE)gpWaveSamples;
  313. }
  314. /*
  315. * PERMANENT ENTRY POINTS
  316. */
  317. BOOL ParseCommandLine(LPTSTR lpCommandLine);
  318. /*
  319. * modifies gfEmbedded, initializes gStartParams
  320. */
  321. BOOL InitializeSRS(HINSTANCE hInst)
  322. {
  323. TCHAR * lptCmdLine = GetCommandLine();
  324. BOOL fOLE = FALSE, fServer;
  325. gfUserClose = FALSE;
  326. gachLinkFilename[0] = 0;
  327. fServer = ParseCommandLine(lptCmdLine);
  328. gfEmbedded = fServer; // We are embedded or linked
  329. if (!fServer)
  330. {
  331. if (gStartParams.achOpenFilename[0] != 0)
  332. {
  333. lstrcpy(gachLinkFilename, gStartParams.achOpenFilename);
  334. }
  335. }
  336. //
  337. // Only if we are invoked as an embedded object do we initialize OLE.
  338. // Defer initialization for the standalone object until later.
  339. //
  340. if (gfEmbedded)
  341. fOLE = InitializeOle(hInst);
  342. return fOLE;
  343. }
  344. /* OLE initialization
  345. */
  346. BOOL InitializeOle(HINSTANCE hInst)
  347. {
  348. BOOL fOLE;
  349. DOUT(TEXT("SOUNDREC: Initializing OLE\r\n"));
  350. dwOleBuildVersion = OleBuildVersion();
  351. // Fix bug #33271
  352. // As stated in the docs:
  353. // Typically, the COM library is initialized on an apartment only once.
  354. // Subsequent calls will succeed, as long as they do not attempt to change
  355. // the concurrency model of the apartment, but will return S_FALSE. To close
  356. // the COM library gracefully, each successful call to OleInitialize,
  357. // including those that return S_FALSE, must be balanced by a corresponding
  358. // call to OleUninitialize.
  359. // gfOleInitialized = (OleInitialize(NULL) == NOERROR) ? TRUE : FALSE;
  360. gfOleInitialized = SUCCEEDED(OleInitialize(NULL));
  361. if (gfOleInitialized)
  362. fOLE = CreateSRClassFactory(hInst, gfEmbedded);
  363. else
  364. fOLE = FALSE; // signal a serious problem!
  365. return fOLE;
  366. }
  367. /*
  368. * Initialize the state of the application or
  369. * change state from Embedded to Standalone.
  370. */
  371. void FlagEmbeddedObject(BOOL flag)
  372. {
  373. // Set global state variables. Note, gfEmbedding is untouched.
  374. gfEmbeddedObject = flag;
  375. gfStandalone = !flag;
  376. }
  377. void SetOleCaption(
  378. LPTSTR lpszObj)
  379. {
  380. TCHAR aszFormatString[256];
  381. LPTSTR lpszTitle;
  382. //
  383. // Change title to "Sound Object in XXX"
  384. //
  385. LoadString(ghInst, IDS_OBJECTTITLE, aszFormatString,
  386. SIZEOF(aszFormatString));
  387. lpszTitle = (LPTSTR)GlobalAllocPtr(GHND, (lstrlen(lpszObj) + SIZEOF(aszFormatString))*sizeof(TCHAR));
  388. if (lpszTitle)
  389. {
  390. wsprintf(lpszTitle, aszFormatString, lpszObj);
  391. SetWindowText(ghwndApp, lpszTitle);
  392. GlobalFreePtr(lpszTitle);
  393. }
  394. }
  395. void SetOleMenu(
  396. HMENU hMenu,
  397. LPTSTR lpszObj)
  398. {
  399. TCHAR aszFormatString[256];
  400. LPTSTR lpszMenu;
  401. //
  402. // Change menu to "Exit & Return to XXX"
  403. //
  404. LoadString(ghInst, IDS_EXITANDRETURN, aszFormatString,
  405. SIZEOF(aszFormatString));
  406. lpszMenu = (LPTSTR)GlobalAllocPtr(GHND, (lstrlen(lpszObj) + SIZEOF(aszFormatString))*sizeof(TCHAR));
  407. if (lpszMenu)
  408. {
  409. wsprintf(lpszMenu, aszFormatString, lpszObj);
  410. ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND, IDM_EXIT, lpszMenu);
  411. GlobalFreePtr(lpszMenu);
  412. }
  413. }
  414. /* Adjust menus according to system state.
  415. * */
  416. void FixMenus(void)
  417. {
  418. HMENU hMenu;
  419. hMenu = GetMenu(ghwndApp);
  420. if (!gfLinked && gfEmbeddedObject)
  421. {
  422. // Remove these menu items as they are irrelevant.
  423. DeleteMenu(hMenu, IDM_NEW, MF_BYCOMMAND);
  424. DeleteMenu(hMenu, IDM_SAVE, MF_BYCOMMAND);
  425. DeleteMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND);
  426. DeleteMenu(hMenu, IDM_REVERT, MF_BYCOMMAND);
  427. DeleteMenu(hMenu, IDM_OPEN, MF_BYCOMMAND);
  428. }
  429. else
  430. {
  431. TCHAR ach[40];
  432. // Is this necessary?
  433. LoadString(ghInst, IDS_NONEMBEDDEDSAVE, ach, SIZEOF(ach));
  434. ModifyMenu(hMenu, IDM_SAVE, MF_BYCOMMAND, IDM_SAVE, ach);
  435. }
  436. //
  437. // Update the titlebar and exit menu too.
  438. //
  439. if (!gfLinked && gfEmbeddedObject)
  440. {
  441. LPTSTR lpszObj = NULL;
  442. LPTSTR lpszApp = NULL;
  443. OleObjGetHostNames(&lpszApp,&lpszObj);
  444. if (lpszObj)
  445. lpszObj = (LPTSTR)FileName((LPCTSTR)lpszObj);
  446. if (lpszObj)
  447. {
  448. SetOleCaption(lpszObj);
  449. SetOleMenu(hMenu, lpszObj);
  450. }
  451. }
  452. DrawMenuBar(ghwndApp); /* Can't hurt... */
  453. }
  454. #define WM_USER_DESTROY (WM_USER+10)
  455. //
  456. // Called from WM_CLOSE (from user) or SCtrl::~SCtrl (from container)
  457. //
  458. void TerminateServer(void)
  459. {
  460. DOUT(TEXT("SoundRec: TerminateServer\r\n"));
  461. gfTerminating = TRUE;
  462. if (gfOleInitialized)
  463. {
  464. WriteObjectIfEmpty();
  465. ReleaseSRClassFactory();
  466. FlushOleClipboard();
  467. //
  468. // If, at this time, we haven't closed, we really should.
  469. //
  470. if (!gfClosing)
  471. {
  472. DoOleClose(TRUE);
  473. AdviseClosed();
  474. }
  475. }
  476. //
  477. // only if the user is terminating OR we're embedded
  478. //
  479. if (gfUserClose || !gfStandalone)
  480. PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0);
  481. }
  482. /* start params!
  483. * the app will use these params to determine behaviour once started.
  484. */
  485. StartParams gStartParams = { FALSE,FALSE,FALSE,FALSE,TEXT("") };
  486. BOOL ParseCommandLine(LPTSTR lpCommandLine)
  487. {
  488. #define TEST_STRING_MAX 11 // sizeof szEmbedding
  489. #define NUMOPTIONS 6
  490. static TCHAR szEmbedding[] = TEXT("embedding");
  491. static TCHAR szPlay[] = TEXT("play");
  492. static TCHAR szOpen[] = TEXT("open");
  493. static TCHAR szNew[] = TEXT("new");
  494. static TCHAR szClose[] = TEXT("close");
  495. static struct tagOption {
  496. LPTSTR name;
  497. LPTSTR filename;
  498. int cchfilename;
  499. LPBOOL state;
  500. } options [] = {
  501. { NULL, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fOpen },
  502. { szEmbedding, gStartParams.achOpenFilename, _MAX_PATH, &gfEmbedded },
  503. { szPlay, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fPlay },
  504. { szOpen, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fOpen },
  505. { szNew, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fNew },
  506. { szClose, NULL, 0, &gStartParams.fClose }
  507. };
  508. LPTSTR pchNext;
  509. int iOption = 0,i,cNumOptions = sizeof(options)/sizeof(struct tagOption);
  510. TCHAR szSwitch[TEST_STRING_MAX];
  511. TCHAR ch;
  512. if (lpCommandLine == NULL)
  513. return FALSE;
  514. /* skip argv[0] */
  515. if (*lpCommandLine == TEXT('"'))
  516. {
  517. //
  518. // eat up everything to the next quote
  519. //
  520. lpCommandLine++;
  521. do {
  522. ch = *lpCommandLine++;
  523. }
  524. while (ch != TEXT('"'));
  525. }
  526. else
  527. {
  528. //
  529. // eat up everything to the next whitespace
  530. //
  531. ch = *lpCommandLine;
  532. while (ch != TEXT(' ') && ch != TEXT('\t') && ch != TEXT('\0'))
  533. ch = *++lpCommandLine;
  534. }
  535. pchNext = lpCommandLine;
  536. while ( *pchNext )
  537. {
  538. LPTSTR pchName = options[iOption].filename;
  539. int cchName = options[iOption].cchfilename;
  540. /* whitespace */
  541. switch (*pchNext)
  542. {
  543. case TEXT(' '):
  544. case TEXT('\t'):
  545. pchNext++;
  546. continue;
  547. case TEXT('-'):
  548. case TEXT('/'):
  549. {
  550. lstrcpyn(szSwitch,pchNext+1,TEST_STRING_MAX);
  551. szSwitch[TEST_STRING_MAX-1] = 0;
  552. /* scan to the NULL or ' ' and terminate string */
  553. for (i = 0; i < TEST_STRING_MAX && szSwitch[i] != 0; i++)
  554. if (szSwitch[i] == TEXT(' '))
  555. {
  556. szSwitch[i] = 0;
  557. break;
  558. }
  559. /* now test each option switch for a hit */
  560. for (i = 0; i < cNumOptions; i++)
  561. {
  562. if (options[i].name == NULL)
  563. continue;
  564. if (!lstrcmpi(szSwitch,options[i].name))
  565. {
  566. *(options[i].state) = TRUE;
  567. if (options[i].filename)
  568. /* next non switch string applies to this option */
  569. iOption = i;
  570. break;
  571. }
  572. }
  573. /* seek ahead */
  574. while (*pchNext && *pchNext != TEXT(' '))
  575. pchNext++;
  576. continue;
  577. }
  578. case TEXT('\"'):
  579. /* filename */
  580. /* copy up to next quote */
  581. pchNext++;
  582. while (*pchNext && *pchNext != TEXT('\"'))
  583. {
  584. if (cchName)
  585. {
  586. *pchName++ = *pchNext++;
  587. cchName--;
  588. }
  589. else
  590. break;
  591. }
  592. pchNext++;
  593. continue;
  594. default:
  595. /* filename */
  596. /* copy up to the end */
  597. while (*pchNext && cchName)
  598. {
  599. *pchName++ = *pchNext++;
  600. cchName--;
  601. }
  602. break;
  603. }
  604. }
  605. /* special case.
  606. * we are linked if given a LinkFilename and an embedding flag.
  607. * Does this ever happen or only through IPersistFile?
  608. */
  609. if (gfEmbedded && gStartParams.achOpenFilename[0] != 0)
  610. {
  611. gfLinked = TRUE;
  612. }
  613. return gfEmbedded;
  614. }
  615. void
  616. BuildUniqueLinkName(void)
  617. {
  618. //
  619. //Ensure a unique filename in gachLinkFilename so we can create valid
  620. //FileMonikers...
  621. //
  622. if(gachLinkFilename[0] == 0)
  623. {
  624. TCHAR aszFile[_MAX_PATH];
  625. GetTempFileName(TEXT("."), TEXT("Tmp"), 0, gachLinkFilename);
  626. /* GetTempFileName creates an empty file, delete it.
  627. */
  628. GetFullPathName(gachLinkFilename,SIZEOF(aszFile),aszFile,NULL);
  629. DeleteFile(aszFile);
  630. }
  631. }
  632. void AppPlay(BOOL fClose)
  633. {
  634. if (fClose)
  635. {
  636. //ugh. don't show while playing.
  637. gfShowWhilePlaying = FALSE;
  638. }
  639. if (IsWindow(ghwndApp))
  640. {
  641. gfCloseAtEndOfPlay = fClose;
  642. PostMessage(ghwndApp,WM_COMMAND,ID_PLAYBTN, 0L);
  643. }
  644. }