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.

1072 lines
25 KiB

  1. /* embed.c - Contains the routines for pseudo-embedding objects.
  2. *
  3. * Copyright (c) Microsoft Corporation, 1991-
  4. *
  5. * Why is it called pseudo-embedding? Because it is not embedding
  6. * the object in the OLE sense; rather, it just pulls the entire
  7. * file into memory.
  8. */
  9. #define _SECOND ((ULONGLONG) 10000000)
  10. #define _MINUTE (60 * _SECOND)
  11. #define _HOUR (60 * _MINUTE)
  12. #include "packager.h"
  13. #include <shellapi.h>
  14. #include "dialogs.h"
  15. #include <wininet.h>
  16. // #include <shell.h> // For RealShellExecute() call.
  17. #define OLEVERB_EDIT 1
  18. static CHAR szDefTempFile[] = "PKG";
  19. static OLECLIENTVTBL embClivtbl;
  20. static BOOL bOleReleaseError = OLE_OK;
  21. static HWND hTaskWnd;
  22. static INT cEmbWait = 0;
  23. DWORD MainWaitOnChild(LPVOID lpv);
  24. static VOID ReplaceExtension(LPSTR lpstrTempFile, LPSTR lpstrOrigFile);
  25. static DWORD GetFileLength(INT fh);
  26. BOOL CALLBACK GetTaskWndProc(HWND hwnd, LPARAM lParam);
  27. static BOOL EmbError(OLESTATUS retval);
  28. BOOL _EmbExecute(LPCSTR pszFile, LPEMBED lpembed)
  29. {
  30. DWORD err = NO_ERROR;
  31. SHELLEXECUTEINFO sei = {0};
  32. sei.cbSize = sizeof(sei);
  33. sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
  34. sei.lpFile = pszFile;
  35. sei.nShow = SW_SHOWNORMAL;
  36. if (ShellExecuteEx(&sei))
  37. {
  38. if (lpembed->hContents)
  39. {
  40. GlobalFree(lpembed->hContents);
  41. lpembed->aTempName = AddAtom(pszFile);
  42. lpembed->dwSize = 0;
  43. lpembed->hContents = NULL;
  44. }
  45. if (sei.hProcess)
  46. {
  47. // Start a thread to wait on the app and close packager once it has ended
  48. DWORD id;
  49. HANDLE hThd = CreateThread(NULL, 0, MainWaitOnChild, sei.hProcess, 0, &id );
  50. if (hThd)
  51. {
  52. CloseHandle(hThd);
  53. }
  54. else
  55. {
  56. CloseHandle(sei.hProcess);
  57. err = GetLastError();
  58. }
  59. }
  60. else
  61. {
  62. if (gfInvisible)
  63. PostMessage(ghwndFrame, WM_SYSCOMMAND, SC_CLOSE, 0L);
  64. }
  65. }
  66. else
  67. {
  68. err = GetLastError();
  69. }
  70. if (err != NO_ERROR)
  71. {
  72. ErrorMessage((err == ERROR_NO_ASSOCIATION) ? E_FAILED_TO_FIND_ASSOCIATION : E_FAILED_TO_EXECUTE_COMMAND);
  73. }
  74. return (err == NO_ERROR);
  75. }
  76. // Taken from shell code but slightly modified to eliminate problesm with finding ":" in the url
  77. STDAPI_(LPTSTR) PathFindExtension(LPCTSTR pszPath)
  78. {
  79. LPCTSTR pszDot = NULL;
  80. if (pszPath)
  81. {
  82. for (; *pszPath; pszPath = CharNext(pszPath))
  83. {
  84. switch (*pszPath)
  85. {
  86. case TEXT('.'):
  87. pszDot = pszPath; // remember the last dot
  88. break;
  89. case '\\':
  90. case TEXT(' '): // extensions can't have spaces
  91. pszDot = NULL; // forget last dot, it was in a directory
  92. break;
  93. }
  94. }
  95. }
  96. // if we found the extension, return ptr to the dot, else
  97. // ptr to end of the string (NULL extension) (cast->non const)
  98. return pszDot ? (LPTSTR)pszDot : (LPTSTR)pszPath;
  99. }
  100. /* EmbActivate() - Performs activation of a pseudo-embedded file.
  101. *
  102. * Notes: Assumes that lpstrFile is in the OEM character set.
  103. */
  104. BOOL EmbActivate(LPEMBED lpembed, UINT wVerb)
  105. {
  106. LPSTR lpFileData = NULL;
  107. CHAR szFileName[CBPATHMAX];
  108. CHAR szDefPath[CBPATHMAX];
  109. CHAR szTemp[CBPATHMAX];
  110. INT fh;
  111. BOOL fError = TRUE;
  112. LPSTR pExt = NULL;
  113. CHAR szCacheName[MAX_PATH];
  114. CHAR szUrlName[MAX_PATH + 20];
  115. FILETIME ftNow = {0};
  116. FILETIME ft = {0};
  117. SYSTEMTIME sysTime;
  118. ULONGLONG qwResult;
  119. //
  120. // If no hContents, we launched the server at some point...
  121. // so use the same temporary file name.
  122. //
  123. if (!lpembed->hContents)
  124. {
  125. if (lpembed->bOleSvrFile)
  126. return EmbDoVerb(lpembed, wVerb);
  127. if (lpembed->hTask)
  128. {
  129. hTaskWnd = NULL;
  130. EnumTaskWindows(lpembed->hTask, GetTaskWndProc, 0);
  131. if (hTaskWnd)
  132. BringWindowToTop(hTaskWnd);
  133. return TRUE;
  134. }
  135. if (!GetAtomName(lpembed->aTempName, szCacheName, ARRAYSIZE(szCacheName)))
  136. goto errRtn;
  137. }
  138. else
  139. {
  140. if (!GetAtomName(lpembed->aFileName, szFileName, ARRAYSIZE(szFileName))
  141. || !(lpFileData = GlobalLock(lpembed->hContents)))
  142. goto errRtn;
  143. GlobalUnlock(lpembed->hContents);
  144. // Find the extension -- we need it for the urlcache funcion
  145. pExt = PathFindExtension(szFileName);
  146. if('.' == *pExt) // not expecting the '.'
  147. pExt++;
  148. GetSystemTime(&sysTime);
  149. SystemTimeToFileTime(&sysTime, &ft);
  150. // Create a fake URL in the format expected -- While not totally unique, close enough for our purposes (4 billion)
  151. StringCchPrintf(szUrlName, ARRAYSIZE(szUrlName), TEXT("Packager%u:%s"), ft.dwLowDateTime, szFileName);
  152. // So, now I'm pointing at the ext, and I have a fake url name, so
  153. if(!CreateUrlCacheEntry(szUrlName, ARRAYSIZE(szCacheName), pExt, szCacheName, 0))
  154. goto errRtn;
  155. if ((fh = _lcreat(szCacheName, 0)) < 0)
  156. goto errRtn;
  157. if (_lwrite(fh, lpFileData, lpembed->dwSize) < lpembed->dwSize)
  158. {
  159. _lclose(fh);
  160. DeleteFile(szCacheName);
  161. goto errRtn;
  162. }
  163. _lclose(fh);
  164. // exire this in 12 hours (arbitrarily longer than a work day) since we can't always clean it up ourselves.
  165. // Normally we'd only care about it for a very short time, and it probably
  166. // wouldn't hurt to have it cleaned up if it was open anyway.
  167. SystemTimeToFileTime(&sysTime, &ftNow);
  168. // Copy the time into a quadword.
  169. qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
  170. qwResult += (12 * _HOUR);
  171. // Copy the result back into the FILETIME structure.
  172. ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
  173. ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
  174. if(!CommitUrlCacheEntry(
  175. szUrlName,
  176. szCacheName,
  177. ft,
  178. ftNow,
  179. 0,
  180. NULL,
  181. 0,
  182. pExt,
  183. szUrlName))
  184. {
  185. goto errRtn;
  186. }
  187. }
  188. if (lpembed->bOleSvrFile)
  189. {
  190. fError = !EmbActivateThroughOle(lpembed, szCacheName, wVerb);
  191. if (!fError)
  192. {
  193. GlobalFree(lpembed->hContents);
  194. lpembed->aTempName = AddAtom(szCacheName);
  195. lpembed->dwSize = 0;
  196. lpembed->hContents = NULL;
  197. }
  198. goto errRtn;
  199. }
  200. // Try to execute the file
  201. lpembed->hTask = NULL;
  202. fError = !_EmbExecute(szCacheName, lpembed);
  203. if (fError)
  204. {
  205. DeleteFile(szCacheName);
  206. }
  207. errRtn:
  208. if (fError)
  209. {
  210. if (gfInvisible)
  211. PostMessage(ghwndFrame, WM_SYSCOMMAND, SC_CLOSE, 0L);
  212. }
  213. else
  214. {
  215. Dirty();
  216. }
  217. return !fError;
  218. }
  219. /*****************************************************************************\
  220. * MainWaitOnChild
  221. *
  222. * Waits for the specified child process to exit, then posts a message
  223. * back to the main window.
  224. *
  225. * Arguments:
  226. *
  227. * LPVOID lpv - Handle to the child process to wait on.
  228. *
  229. * Returns:
  230. * 0
  231. *
  232. \*****************************************************************************/
  233. DWORD
  234. MainWaitOnChild(
  235. LPVOID lpv
  236. )
  237. {
  238. if (WaitForSingleObject((HANDLE)lpv, INFINITE) == 0)
  239. {
  240. PostMessage(ghwndFrame, WM_READEMBEDDED, 0, 0);
  241. }
  242. CloseHandle((HANDLE)lpv);
  243. GetLastError(); //This seems ominous
  244. return 0;
  245. }
  246. /* EmbCreate() - Performs the pseudo-embedding of a file.
  247. *
  248. * Notes: Assumes that lpstrFile is in the OEM character set.
  249. *
  250. * This function is used by File Import..., is called
  251. * when the Embed modifier is used on Drag&Drop, and
  252. * is also used when Paste-ing a File manager file.
  253. */
  254. LPEMBED
  255. EmbCreate(
  256. LPSTR lpstrFile
  257. )
  258. {
  259. ATOM aFileName = 0;
  260. BOOL fError = TRUE;
  261. DWORD dwSize = 0;
  262. HANDLE hdata = NULL;
  263. HANDLE hFileData = NULL;
  264. LPEMBED lpembed = NULL;
  265. LPSTR lpFileData = NULL;
  266. INT fh = 0;
  267. if (lpstrFile)
  268. {
  269. if ((fh = _lopen(lpstrFile, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR)
  270. {
  271. ErrorMessage(IDS_ACCESSDENIED);
  272. goto errRtn;
  273. }
  274. // Seek to EOF, then to the top of the file.
  275. dwSize = GetFileLength(fh);
  276. if (0 == dwSize)
  277. {
  278. ErrorMessage(IDS_NOZEROSIZEFILES);
  279. goto errRtn;
  280. }
  281. if (!(aFileName = AddAtom(lpstrFile))
  282. || !(hFileData = GlobalAlloc(GMEM_MOVEABLE, dwSize))
  283. || !(lpFileData = GlobalLock(hFileData)))
  284. {
  285. ErrorMessage(IDS_LOWMEM);
  286. goto errRtn;
  287. }
  288. if (_lread(fh, lpFileData, dwSize) != dwSize)
  289. {
  290. ErrorMessage(E_FAILED_TO_READ_FILE);
  291. goto errRtn;
  292. }
  293. }
  294. if (!(hdata = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(EMBED)))
  295. || !(lpembed = (LPEMBED)GlobalLock(hdata)))
  296. {
  297. ErrorMessage(IDS_LOWMEM);
  298. goto errRtn;
  299. }
  300. lpembed->aFileName = aFileName;
  301. lpembed->dwSize = dwSize;
  302. lpembed->hContents = hFileData;
  303. lpembed->hdata = hdata;
  304. lpembed->bOleSvrFile = IsOleServerDoc(lpstrFile);
  305. fError = FALSE;
  306. errRtn:
  307. if (fh)
  308. _lclose(fh);
  309. if (lpFileData)
  310. GlobalUnlock(hFileData);
  311. if (fError)
  312. {
  313. if (hdata)
  314. GlobalFree(hdata);
  315. if (aFileName)
  316. DeleteAtom(aFileName);
  317. if (hFileData)
  318. GlobalFree(hFileData);
  319. }
  320. return lpembed;
  321. }
  322. /* EmbDelete() - Deallocate the pseudo-embedded file.
  323. */
  324. VOID
  325. EmbDelete(
  326. LPEMBED lpembed
  327. )
  328. {
  329. HANDLE hdata;
  330. if (!lpembed)
  331. return;
  332. if (lpembed->lpLinkObj)
  333. {
  334. EmbRead(glpobj[CONTENT]);
  335. EmbDeleteLinkObject(lpembed);
  336. }
  337. else {
  338. /* If the task is active, there's nothing we can do */
  339. #if 0
  340. if (lpembed->hSvrInst)
  341. TermToolHelp(lpembed);
  342. #endif //FEATURE: Does anything need to be done for this case? Like terminating the waiting thread, perhaps?
  343. }
  344. if (lpembed->aFileName)
  345. {
  346. DeleteAtom(lpembed->aFileName);
  347. lpembed->aFileName = 0;
  348. }
  349. if (lpembed->aTempName)
  350. {
  351. DeleteAtom(lpembed->aTempName);
  352. lpembed->aTempName = 0;
  353. }
  354. if (lpembed->hContents)
  355. {
  356. GlobalFree(lpembed->hContents);
  357. lpembed->dwSize = 0;
  358. lpembed->hContents = NULL;
  359. }
  360. GlobalUnlock(hdata = lpembed->hdata);
  361. GlobalFree(hdata);
  362. }
  363. /* EmbDraw() - Draw the pseudo-embedded object.
  364. *
  365. * Note: This drawing is DESCRIPTION-ONLY.
  366. */
  367. VOID
  368. EmbDraw(
  369. LPEMBED lpembed,
  370. HDC hdc,
  371. LPRECT lprc,
  372. BOOL fFocus
  373. )
  374. {
  375. RECT rcFocus;
  376. CHAR szEmbedFile[CBMESSAGEMAX];
  377. CHAR szFileName[CBPATHMAX];
  378. CHAR szMessage[CBMESSAGEMAX + CBPATHMAX];
  379. if (GetAtomName(lpembed->aFileName, szFileName, CBPATHMAX)
  380. && LoadString(ghInst, IDS_EMBEDFILE, szEmbedFile, CBMESSAGEMAX))
  381. {
  382. Normalize(szFileName);
  383. StringCchPrintf(szMessage, ARRAYSIZE(szMessage), szEmbedFile, (LPSTR)szFileName);
  384. DrawText(hdc, szMessage, -1, lprc,
  385. DT_NOPREFIX | DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  386. if (fFocus)
  387. {
  388. rcFocus = *lprc;
  389. DrawText(hdc, szMessage, -1, &rcFocus, DT_CALCRECT | DT_NOPREFIX |
  390. DT_LEFT | DT_TOP | DT_SINGLELINE);
  391. OffsetRect(&rcFocus, (lprc->left + lprc->right - rcFocus.right) /
  392. 2, (lprc->top + lprc->bottom - rcFocus.bottom) / 2);
  393. DrawFocusRect(hdc, &rcFocus);
  394. }
  395. }
  396. }
  397. /* EmbReadFromNative() - Reads a pseudo-embedded object from memory.
  398. *
  399. * Notes: This function is called by GetNative().
  400. */
  401. LPEMBED
  402. EmbReadFromNative(
  403. LPSTR *lplpstr
  404. )
  405. {
  406. BOOL fError = TRUE;
  407. DWORD dwSize;
  408. HANDLE hData = NULL;
  409. LPEMBED lpembed = NULL;
  410. LPSTR lpData = NULL;
  411. CHAR szFileName[CBPATHMAX];
  412. MemRead(lplpstr, (LPSTR)&dwSize, sizeof(dwSize));
  413. MemRead(lplpstr, (LPSTR)szFileName, dwSize);
  414. MemRead(lplpstr, (LPSTR)&dwSize, sizeof(dwSize));
  415. if (!(lpembed = EmbCreate(NULL))
  416. || !(hData = GlobalAlloc(GMEM_MOVEABLE, dwSize))
  417. || !(lpData = GlobalLock(hData)))
  418. goto errRtn;
  419. MemRead(lplpstr, (LPSTR)lpData, dwSize);
  420. lpembed->aFileName = AddAtom(szFileName);
  421. lpembed->dwSize = dwSize;
  422. lpembed->hContents = hData;
  423. lpembed->bOleSvrFile = IsOleServerDoc(szFileName);
  424. fError = FALSE;
  425. errRtn:
  426. if (lpData)
  427. GlobalUnlock(hData);
  428. if (fError)
  429. {
  430. if (hData)
  431. GlobalFree(hData);
  432. if (lpembed)
  433. {
  434. EmbDelete(lpembed);
  435. lpembed = NULL;
  436. }
  437. }
  438. return lpembed;
  439. }
  440. /* EmbWriteToNative() - Used to save pseudo-embed to memory.
  441. *
  442. * Note: This function is called by GetNative().
  443. */
  444. DWORD
  445. EmbWriteToNative(
  446. LPEMBED lpembed,
  447. LPSTR *lplpstr
  448. )
  449. {
  450. BOOL fError = TRUE;
  451. DWORD cBytes = 0;
  452. DWORD dwSize;
  453. HANDLE hData = NULL;
  454. LPSTR lpData = NULL;
  455. LPSTR lpFileData = NULL;
  456. CHAR szFileName[CBPATHMAX];
  457. INT fhTemp = -1;
  458. CHAR * hplpstr;
  459. if (!GetAtomName(lpembed->aFileName, szFileName, CBPATHMAX))
  460. goto errRtn;
  461. if (!lplpstr)
  462. {
  463. cBytes = lstrlen(szFileName) + 1 + sizeof(dwSize);
  464. }
  465. else
  466. {
  467. dwSize = lstrlen(szFileName) + 1;
  468. MemWrite(lplpstr, (LPSTR)&dwSize, sizeof(dwSize));
  469. MemWrite(lplpstr, (LPSTR)szFileName, dwSize);
  470. }
  471. // Read from memory if it's there; otherwise, it's executing
  472. if (lpembed->hContents)
  473. {
  474. cBytes += sizeof(lpembed->dwSize) + lpembed->dwSize;
  475. if (lplpstr)
  476. {
  477. if (!(lpFileData = GlobalLock(lpembed->hContents)))
  478. goto errRtn;
  479. MemWrite(lplpstr, (LPSTR)&(lpembed->dwSize), sizeof(lpembed->dwSize));
  480. MemWrite(lplpstr, (LPSTR)lpFileData, lpembed->dwSize);
  481. }
  482. } else {
  483. int i;
  484. if (!GetAtomName(lpembed->aTempName, szFileName, CBPATHMAX))
  485. goto errRtn;
  486. for (i = 0; i < 5; i++ ) {
  487. int j;
  488. fhTemp = _lopen(szFileName, OF_READ | OF_SHARE_DENY_WRITE);
  489. if (fhTemp != HFILE_ERROR) {
  490. break;
  491. }
  492. /*
  493. * We could not open the file. It is probably still open by the
  494. * server. Wait 5 seconds for the server to finish closing the
  495. * file and then try again.
  496. */
  497. for (j=0; j<25; j++) {
  498. MSG msg;
  499. PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
  500. Sleep(200);
  501. }
  502. }
  503. /*
  504. * If after 25 seconds we still could not open the file, then it
  505. * must be screwed
  506. */
  507. if (fhTemp == HFILE_ERROR)
  508. goto errRtn;
  509. dwSize = GetFileLength(fhTemp);
  510. if (!lplpstr)
  511. cBytes += sizeof(dwSize) + dwSize;
  512. else
  513. {
  514. MemWrite(lplpstr, (LPSTR)&dwSize, sizeof(dwSize));
  515. _lread(fhTemp, *lplpstr, dwSize);
  516. // Increment the pointer being read into
  517. hplpstr = *lplpstr;
  518. hplpstr += dwSize;
  519. *lplpstr = hplpstr;
  520. }
  521. }
  522. fError = FALSE;
  523. errRtn:
  524. if (fhTemp >= 0)
  525. {
  526. _lclose(fhTemp);
  527. if (!fError && lplpstr && !(lpembed->hTask || lpembed->lpLinkObj))
  528. DeleteFile(szFileName);
  529. }
  530. if (lpData)
  531. GlobalUnlock(hData);
  532. if (hData)
  533. GlobalFree(hData);
  534. if (lpFileData)
  535. GlobalUnlock(lpembed->hContents);
  536. return (fError ? ((DWORD)(-1L)) : cBytes);
  537. }
  538. /* EmbWriteToFile() - Used to save pseudo-embed to a file.
  539. *
  540. * Note: This function is called by File Export...
  541. */
  542. VOID
  543. EmbWriteToFile(
  544. LPEMBED lpembed,
  545. INT fh
  546. )
  547. {
  548. BOOL fError = TRUE;
  549. DWORD dwSize;
  550. HANDLE hData = NULL;
  551. LPSTR lpData = NULL;
  552. LPSTR lpFileData = NULL;
  553. CHAR szTempName[CBPATHMAX];
  554. INT fhTemp = -1;
  555. CHAR szMessage[CBMESSAGEMAX];
  556. // Read from memory if it's there
  557. if (lpembed->hContents)
  558. {
  559. if (!(lpFileData = GlobalLock(lpembed->hContents)))
  560. goto errRtn;
  561. if (_lwrite(fh, lpFileData, lpembed->dwSize) != lpembed->dwSize)
  562. goto errRtn;
  563. }
  564. else
  565. {
  566. // otherwise, it is/was executing
  567. if (lpembed->hTask && !gfInvisible)
  568. {
  569. // Object being edited, snapshot current contents?
  570. LoadString(ghInst, IDS_ASKCLOSETASK, szMessage, CBMESSAGEMAX);
  571. BringWindowToTop(ghwndFrame);
  572. switch (MessageBoxAfterBlock(ghwndError, szMessage, szAppName,
  573. MB_OKCANCEL))
  574. {
  575. case IDOK:
  576. break;
  577. case IDCANCEL:
  578. return;
  579. }
  580. }
  581. if (!GetAtomName(lpembed->aTempName, szTempName, CBPATHMAX)
  582. || (fhTemp = _lopen(szTempName, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR)
  583. goto errRtn;
  584. dwSize = GetFileLength(fhTemp);
  585. while (dwSize && !(hData = GlobalAlloc(GMEM_MOVEABLE, dwSize)))
  586. dwSize = dwSize >> 1;
  587. if (!dwSize || !(lpData = GlobalLock(hData)))
  588. goto errRtn;
  589. while (dwSize)
  590. {
  591. dwSize = _lread(fhTemp, lpData, dwSize);
  592. if (dwSize)
  593. _lwrite(fh, lpData, dwSize);
  594. }
  595. }
  596. fError = FALSE;
  597. errRtn:
  598. if (fhTemp >= 0)
  599. {
  600. _lclose(fhTemp);
  601. if (!fError && !lpembed->hTask)
  602. DeleteFile(gszFileName);
  603. }
  604. if (lpData)
  605. GlobalUnlock(hData);
  606. if (hData)
  607. GlobalFree(hData);
  608. if (lpFileData)
  609. GlobalUnlock(lpembed->hContents);
  610. }
  611. /* ReplaceExtension() - Replaces the extension of the temp file.
  612. *
  613. * This routine ensures that the temp file has the same extension as the
  614. * original file, so that the ShellExecute() will load the same file.
  615. */
  616. static VOID
  617. ReplaceExtension(
  618. LPSTR lpstrTempFile,
  619. LPSTR lpstrOrigFile
  620. )
  621. {
  622. LPSTR lpstrBack = NULL;
  623. // Get temp file extension
  624. while (*lpstrTempFile)
  625. {
  626. if (*lpstrTempFile == '\\')
  627. lpstrBack = lpstrTempFile;
  628. if (gbDBCS)
  629. {
  630. lpstrTempFile = CharNext(lpstrTempFile);
  631. }
  632. else
  633. {
  634. lpstrTempFile++;
  635. }
  636. }
  637. while (lpstrBack && *lpstrBack && *lpstrBack != '.')
  638. lpstrBack++;
  639. if (lpstrBack && *lpstrBack)
  640. lpstrTempFile = lpstrBack + 1;
  641. // Get original file extension
  642. while (*lpstrOrigFile)
  643. {
  644. if (*lpstrOrigFile == '\\')
  645. lpstrBack = lpstrOrigFile;
  646. if (gbDBCS)
  647. {
  648. lpstrOrigFile = CharNext(lpstrOrigFile);
  649. }
  650. else
  651. {
  652. lpstrOrigFile++;
  653. }
  654. }
  655. while (lpstrBack && *lpstrBack && *lpstrBack != '.')
  656. lpstrBack++;
  657. if (lpstrBack && *lpstrBack)
  658. {
  659. lpstrOrigFile = lpstrBack + 1;
  660. // Move the extension on over
  661. lstrcpy(lpstrTempFile, lpstrOrigFile);
  662. }
  663. else
  664. {
  665. /* Wipe out the extension altogether */
  666. *lpstrTempFile = 0;
  667. }
  668. }
  669. /* GetFileLength() - Obtain the size of the temporary file used.
  670. *
  671. * Returns: The length of the file in bytes.
  672. * Side effects: Resets fh to the beginning of the file.
  673. */
  674. static DWORD
  675. GetFileLength(
  676. INT fh
  677. )
  678. {
  679. DWORD dwSize;
  680. dwSize = _llseek(fh, 0L, 2);
  681. _llseek(fh, 0L, 0);
  682. return dwSize;
  683. }
  684. /* EmbRead() - Reads the contents back when the task has terminated.
  685. */
  686. VOID
  687. EmbRead(
  688. LPEMBED lpembed
  689. )
  690. {
  691. BOOL fError = TRUE;
  692. DWORD dwSize;
  693. HANDLE hFileData = NULL;
  694. LPSTR lpFileData = NULL;
  695. CHAR szTempFileName[CBPATHMAX];
  696. INT fhTemp = -1;
  697. if (!lpembed || !lpembed->aTempName)
  698. return;
  699. if (!GetAtomName(lpembed->aTempName, szTempFileName, CBPATHMAX))
  700. return;
  701. if ((fhTemp = _lopen(szTempFileName, OF_READ | OF_SHARE_DENY_WRITE)) == HFILE_ERROR)
  702. goto errRtn;
  703. dwSize = GetFileLength(fhTemp);
  704. if (!(hFileData = GlobalAlloc(GMEM_MOVEABLE, dwSize))
  705. || !(lpFileData = GlobalLock(hFileData))
  706. || (_lread(fhTemp, lpFileData, dwSize) != dwSize))
  707. goto errRtn;
  708. DeleteAtom(lpembed->aTempName);
  709. lpembed->aTempName = 0;
  710. lpembed->dwSize = dwSize;
  711. lpembed->hContents = hFileData;
  712. lpembed->hTask = NULL;
  713. fError = FALSE;
  714. errRtn:
  715. if (fhTemp >= 0)
  716. {
  717. _lclose(fhTemp);
  718. if (!fError)
  719. DeleteFile(szTempFileName);
  720. }
  721. if (lpFileData)
  722. GlobalUnlock(hFileData);
  723. if (fError && hFileData)
  724. GlobalFree(hFileData);
  725. }
  726. BOOL CALLBACK
  727. GetTaskWndProc(
  728. HWND hwnd,
  729. LPARAM lParam
  730. )
  731. {
  732. if (IsWindowVisible(hwnd))
  733. {
  734. hTaskWnd = hwnd;
  735. return FALSE;
  736. }
  737. return TRUE;
  738. }
  739. BOOL
  740. EmbDoVerb(
  741. LPEMBED lpembed,
  742. UINT wVerb
  743. )
  744. {
  745. if (wVerb == IDD_PLAY)
  746. {
  747. if (EmbError(OleActivate(lpembed->lpLinkObj, OLEVERB_PRIMARY, TRUE,
  748. TRUE, NULL, NULL)))
  749. return FALSE;
  750. }
  751. else
  752. {
  753. // it must be verb IDD_EDIT
  754. if (EmbError(OleActivate(lpembed->lpLinkObj, OLEVERB_EDIT, TRUE,
  755. TRUE, NULL, NULL)))
  756. return FALSE;
  757. }
  758. WaitForObject(lpembed->lpLinkObj);
  759. if (bOleReleaseError != OLE_OK)
  760. {
  761. bOleReleaseError = OLE_OK;
  762. return FALSE;
  763. }
  764. // if the verb is IDD_PLAY then we need not do any more
  765. if (wVerb == IDD_PLAY)
  766. return TRUE;
  767. // If the verb is IDD_EDIT, then we must show the server, and we will do
  768. // that by calling server's show method
  769. if (EmbError((*(lpembed->lpLinkObj)->lpvtbl->Show)(lpembed->lpLinkObj,
  770. TRUE)))
  771. return FALSE;
  772. WaitForObject(lpembed->lpLinkObj);
  773. if (bOleReleaseError != OLE_OK)
  774. {
  775. bOleReleaseError = OLE_OK;
  776. return FALSE;
  777. }
  778. return TRUE;
  779. }
  780. BOOL
  781. EmbActivateThroughOle(
  782. LPEMBED lpembed,
  783. LPSTR lpdocname,
  784. UINT wVerb
  785. )
  786. {
  787. bOleReleaseError = OLE_OK;
  788. if (!(lpembed->lpclient = PicCreateClient(&EmbCallBack, &embClivtbl)))
  789. return FALSE;
  790. if (EmbError(OleCreateLinkFromFile(gszProtocol, lpembed->lpclient, NULL,
  791. lpdocname, NULL, glhcdoc, gszCaption[CONTENT], &lpembed->lpLinkObj,
  792. olerender_none, 0)))
  793. return FALSE;
  794. WaitForObject(lpembed->lpLinkObj);
  795. if (bOleReleaseError == OLE_OK)
  796. {
  797. if (gfEmbObjectOpen = EmbDoVerb(lpembed, wVerb))
  798. return TRUE;
  799. }
  800. EmbDeleteLinkObject(lpembed);
  801. return FALSE;
  802. }
  803. /* EmbCallBack() - Routine that OLE client DLL calls when events occur.
  804. */
  805. INT CALLBACK
  806. EmbCallBack(
  807. LPOLECLIENT lpclient,
  808. OLE_NOTIFICATION flags,
  809. LPOLEOBJECT lpObject
  810. )
  811. {
  812. switch (flags)
  813. {
  814. case OLE_CLOSED:
  815. case OLE_SAVED:
  816. case OLE_CHANGED:
  817. break;
  818. case OLE_RELEASE:
  819. if (cEmbWait)
  820. --cEmbWait;
  821. bOleReleaseError = OleQueryReleaseError(lpObject);
  822. break;
  823. default:
  824. break;
  825. }
  826. return 0;
  827. }
  828. VOID
  829. EmbDeleteLinkObject(
  830. LPEMBED lpembed
  831. )
  832. {
  833. HGLOBAL hg;
  834. bOleReleaseError = OLE_OK;
  835. if (!lpembed->lpLinkObj)
  836. return;
  837. WaitForObject(lpembed->lpLinkObj);
  838. if (!EmbError(OleDelete(lpembed->lpLinkObj)))
  839. WaitForObject (lpembed->lpLinkObj);
  840. lpembed->lpLinkObj = NULL;
  841. if (lpembed->lpclient)
  842. {
  843. if (hg = GlobalHandle(lpembed->lpclient))
  844. {
  845. GlobalUnlock(hg);
  846. GlobalFree(hg);
  847. }
  848. lpembed->lpclient = NULL;
  849. }
  850. gfEmbObjectOpen = FALSE;
  851. bOleReleaseError = OLE_OK;
  852. }
  853. static BOOL
  854. EmbError(
  855. OLESTATUS retval
  856. )
  857. {
  858. switch (retval)
  859. {
  860. case OLE_WAIT_FOR_RELEASE:
  861. cEmbWait++;
  862. return FALSE;
  863. case OLE_OK:
  864. return FALSE;
  865. default:
  866. return TRUE;
  867. }
  868. }