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.

2188 lines
76 KiB

  1. /*---------------------------------------------------------------------------
  2. | DOVERB.C
  3. | This file is used to be called server.c in the OLE1 versions of MPlayer.
  4. | This file has the ReallyDoVerb function which is called by the the
  5. | OLE DoVerb method. This file also has some functions to do the
  6. | InPlace activation in OLE1 apps.
  7. |
  8. | Modified for OLE2 By: Vij Rajarajan (VijR)
  9. +---------------------------------------------------------------------------*/
  10. #define SERVERONLY
  11. #include <windows.h>
  12. #include <mmsystem.h>
  13. #include <shellapi.h>
  14. #define STRSAFE_NO_DEPRECATE
  15. #include <strsafe.h>
  16. #undef _MAX_PATH // ??? someone hacking?
  17. #undef _MAX_DIR // ??? someone hacking?
  18. #undef _MAX_FNAME // ??? someone hacking?
  19. #undef _MAX_EXT // ??? someone hacking?
  20. #include "ctrls.h"
  21. #include "mpole.h"
  22. #include "mplayer.h"
  23. #include "toolbar.h"
  24. #include "ole2ui.h"
  25. #define OLE_OK S_OK
  26. #define NOVERB 1000
  27. extern HANDLE ghInst;
  28. extern HWND ghwndFocus; // Who had focus when we went inactive
  29. extern HWND ghwndFocusSave; // saved focus window
  30. extern HOOKPROC fpMouseHook; // Mouse hook proc address.
  31. extern UINT gwPlaybarHeight; //tell playbar how tall to make
  32. //itself so it covers the title
  33. DWORD gdwPosition;
  34. LONG glCurrentVerb = NOVERB;
  35. BOOL gfBrokenLink = FALSE;
  36. static BOOL gfMouseUpSeen = FALSE; // OK to close play in place?
  37. static BOOL gfKeyStateUpSeen = FALSE; // OK to close play in place?
  38. extern HMODULE hMciOle;
  39. /*
  40. ** These functions are exported from mciole32.dll.
  41. **
  42. */
  43. typedef BOOL (*LPINSTALLHOOK)( HWND, DWORD );
  44. typedef BOOL (*LPREMOVEHOOK)( VOID );
  45. LPINSTALLHOOK fpInstallHook;
  46. LPREMOVEHOOK fpRemoveHook;
  47. BOOL fHookInstalled = FALSE;
  48. char aszInstallHook[] = "InstallHook";
  49. char aszRemoveHook[] = "RemoveHook";
  50. /* Height of picture given to client to be pasted */
  51. static UINT gwPastedHeight;
  52. static DWORD gwOldOptions;
  53. static DWORD gwOldHeight;
  54. TCHAR gachFile[_MAX_PATH];
  55. static int gerr;
  56. static HWND ghwndClient = NULL;
  57. static RECT grcClient;
  58. BOOL gfOle1Client = FALSE;
  59. WNDPROC gfnMCIWndProc;
  60. HWND ghwndSubclass;
  61. BOOL SkipInPlaceEdit = FALSE; //TRUE if we are just reactivating
  62. BOOL gfSeenPBCloseMsg; //TRUE if the subclasses PlayBack WIndow Proc
  63. //has seen the WM_CLOSE message
  64. HWND ghwndFocusSave; //Who had the focus when we were activated.?
  65. #define abs(x) ((x) < 0 ? -(x) : (x))
  66. #ifndef GetWS
  67. #define GetWS(hwnd) GetWindowLongPtr(hwnd, GWL_STYLE)
  68. #define PutWS(hwnd, f) SetWindowLongPtr(hwnd, GWL_STYLE, f)
  69. #define TestWS(hwnd,f) (GetWS(hwnd) & f)
  70. #define SetWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) | f)
  71. #define ClrWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) & ~(f))
  72. #endif
  73. static SZCODE aszAppName[] = TEXT("MPlayer");
  74. STATICFN BOOL FileExists(LPTSTR szFile, LPTSTR szFullName, int iLen);
  75. STATICFN BOOL NetParseFile(LPTSTR szFile, LPTSTR szDrive, LPTSTR szPath);
  76. HPALETTE FAR PASCAL CreateSystemPalette(void);
  77. void TransferTools(HWND hwndToolWindow);
  78. #ifdef DEBUG
  79. BOOL ShowAppWindow(int nCmdShow)
  80. {
  81. return ShowWindow(ghwndApp, nCmdShow);
  82. }
  83. #define SHOWAPPWINDOW(nCmdShow) ShowAppWindow(nCmdShow)
  84. #else
  85. #define SHOWAPPWINDOW(nCmdShow) ShowWindow(ghwndApp, nCmdShow)
  86. #endif
  87. /*************************************************************************
  88. * DirtyObject(BOOL fDocStgChangeOnly) - mark the "object" dirty,
  89. * ie has been changed.
  90. *
  91. * We set the gfDirty flag to TRUE and iff we are a embedded object tell
  92. * the client we have changed by sending a SendDocMsg(OLE_CHANGED).
  93. * fDocStgChangeOnly is TRUE if the change would affect the Embedding if there
  94. * is one but not appearence of the object i.e. the Metafile.
  95. * OLE_CHANGED message is sent only if fDocStgChangeOnly is FALSE;
  96. ***************************************************************************/
  97. void DirtyObject(BOOL fDocStgChangeOnly)
  98. {
  99. //
  100. // NOTE we want to send OLE_CHANGED even if selection has changed
  101. //
  102. if (gfOle2IPEditing && ((gwOptions & OPT_BAR) != (gwOldOptions &OPT_BAR)) && !fDocStgChangeOnly)
  103. {
  104. RECT rc;
  105. BOOL fCanWindow = gwDeviceType & DTMCI_CANWINDOW;
  106. if (fCanWindow)
  107. {
  108. GetWindowRect(ghwndApp, (LPRECT)&rc);
  109. OffsetRect((LPRECT)&rc, -rc.left, -rc.top);
  110. /* rc contains the coordinates of the current app window.
  111. * If we have a playbar, we must allow space for it:
  112. */
  113. if ((gwOptions & OPT_BAR) && !(gwOldOptions &OPT_BAR))
  114. {
  115. /* Add bar */
  116. Layout();
  117. gwPlaybarHeight = TOOLBAR_HEIGHT;
  118. }
  119. else if(!(gwOptions & OPT_BAR) && (gwOldOptions &OPT_BAR))
  120. {
  121. /* Remove bar */
  122. Layout();
  123. gwPlaybarHeight = 0;
  124. }
  125. }
  126. else
  127. {
  128. HBITMAP hbm;
  129. BITMAP bm;
  130. GetWindowRect(ghwndIPHatch, (LPRECT)&rc);
  131. if (gwOptions & OPT_BAR)
  132. gwPlaybarHeight = TOOLBAR_HEIGHT;
  133. else
  134. gwPlaybarHeight = 0;
  135. hbm = BitmapMCI();
  136. GetObject(hbm,sizeof(bm),&bm);
  137. rc.bottom = rc.top + bm.bmHeight;
  138. rc.right = rc.left + bm.bmWidth;
  139. DeleteObject(hbm);
  140. MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&rc, (UINT)2);
  141. DPF("IOleInPlaceSite::OnPosRectChange %d, %d, %d, %d\n", rc);
  142. if (!gfInPPViewer)
  143. IOleInPlaceSite_OnPosRectChange(docMain.lpIpData->lpSite, &rc);
  144. }
  145. }
  146. if (gwOptions != gwOldOptions)
  147. {
  148. gwOldOptions = gwOptions;
  149. if (gfEmbeddedObject && !fDocStgChangeOnly)
  150. SendDocMsg(&docMain, OLE_CHANGED);
  151. }
  152. if (gfDirty /* IsObjectDirty() */)
  153. return;
  154. fDocChanged=gfDirty = TRUE;
  155. gfValidCaption = FALSE;
  156. }
  157. /**************************************************************************
  158. IsObjectDirty() - Object is dirty if the dirty flag is set or the selection
  159. has changed since we last cleaned or the Metafile has
  160. changed
  161. ***************************************************************************/
  162. BOOL FAR PASCAL IsObjectDirty(void)
  163. {
  164. // don't let anyone insert an empty mplayer into a document
  165. if (gwDeviceID == (UINT)0)
  166. return FALSE;
  167. return (gfDirty
  168. || glSelStart != (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L)
  169. || glSelEnd != (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L)
  170. /// I don't see this. This line results in the Update Object dialog coming
  171. /// up when it shouldn't. What has it got to do with metafiles?
  172. /// ??? || gdwPosition != (DWORD)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L)
  173. );
  174. }
  175. /**************************************************************************
  176. CleanObject() - mark the "object" clean.
  177. ***************************************************************************/
  178. void CleanObject(void)
  179. {
  180. if (!IsObjectDirty())
  181. return;
  182. fDocChanged = gfDirty = FALSE;
  183. /* Reset selection globals so we can see if they changed */
  184. glSelStart = (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L);
  185. glSelEnd = (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L);
  186. gdwPosition = (DWORD)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L);
  187. gfValidCaption = FALSE;
  188. }
  189. /**************************************************************************
  190. //## Just parses the play etc options in the embedded object
  191. //## description string
  192. ***************************************************************************/
  193. SCODE FAR PASCAL ParseOptions(LPSTR pOpt)
  194. {
  195. #ifdef UNICODE
  196. DWORD OptLen;
  197. #endif
  198. PTSTR pT, pSave;
  199. int c;
  200. if (pOpt == NULL || *pOpt == 0)
  201. return OLE_OK;
  202. #ifdef UNICODE
  203. OptLen = ANSI_STRING_BYTE_COUNT( pOpt );
  204. pT = AllocMem( OptLen * sizeof( TCHAR ) );
  205. if (pT == NULL)
  206. return E_OUTOFMEMORY;
  207. MultiByteToWideChar( CP_ACP,
  208. MB_PRECOMPOSED,
  209. pOpt,
  210. OptLen,
  211. pT,
  212. OptLen );
  213. #else
  214. pT = pOpt;
  215. #endif
  216. pSave = pT; // wasn't NULL terminated before
  217. for (c = 0; *pT && c < 5; pT++) // change 1st 5 ','s to '\0'
  218. if (*pT == TEXT(','))
  219. {
  220. c++;
  221. *pT = TEXT('\0');
  222. }
  223. pT = pSave; // restore back to beginning
  224. pT += STRLEN(pT) + 1; // skip over Device Name
  225. gwOptions = ATOI(pT);
  226. gwCurScale = (gwOptions & OPT_SCALE);
  227. /* Can't set selection now because Media isn't initialized (UpdateMCI) */
  228. pT += STRLEN(pT) + 1;
  229. glSelStart = ATOL(pT); // remember start of selection for later
  230. pT += STRLEN(pT) + 1;
  231. glSelEnd = ATOL(pT); // remember end of selection for later
  232. pT += STRLEN(pT) + 1;
  233. // remember position in a global so we can Seek later!!
  234. gdwPosition = ATOL(pT);
  235. /* Maybe there is the original height of the picture given to the client in */
  236. /* here hidden in the Position string after a semicolon. */
  237. /* Old versions of Mplayer didn't have any such thing. */
  238. for (; *pT && *pT != TEXT(';'); pT++);
  239. if (*pT == TEXT(';'))
  240. {
  241. pT++;
  242. gwPastedHeight = (UINT)ATOL(pT);
  243. }
  244. else
  245. gwPastedHeight = 0;
  246. pT += STRLEN(pT) + 1;
  247. StringCchCopy(gachCaption, MAX_PATH, pT);
  248. #ifdef UNICODE
  249. FreeMem( pSave, OptLen * sizeof( TCHAR ) );
  250. #endif
  251. return OLE_OK;
  252. }
  253. /**************************************************************************
  254. //## Used to find the parent window of the window handle passed till the
  255. //## window handle is a top level handle
  256. ***************************************************************************/
  257. HWND TopWindow(HWND hwnd)
  258. {
  259. HWND hwndP;
  260. while ((hwndP = GetParent(hwnd)) != NULL)
  261. hwnd = hwndP;
  262. return hwnd;
  263. }
  264. /**************************************************************************
  265. ***************************************************************************/
  266. void FAR PASCAL SetEmbeddedObjectFlag(BOOL flag)
  267. {
  268. TCHAR ach[60];
  269. TCHAR achText[_MAX_PATH];
  270. gfEmbeddedObject = flag;
  271. srvrMain.fEmbedding = flag;
  272. if (!ghMenu)
  273. return;
  274. /*** First fix the Close/Update menu item ***/
  275. LOADSTRING(flag ? IDS_UPDATE : IDS_CLOSE, ach);
  276. if (flag)
  277. StringCchPrintf(achText, _MAX_PATH, ach, (LPTSTR)FileName(szClientDoc));
  278. else
  279. lstrcpy(achText, ach);
  280. /* Menu option will either say "Close" or "Update" (for embedded obj) */
  281. /* and for update, will have the doc name in the text. */
  282. ModifyMenu(ghMenu, IDM_CLOSE, MF_BYCOMMAND, IDM_CLOSE, achText);
  283. /*** Now fix the Exit menu item ***/
  284. LOADSTRING(flag ? IDS_EXITRETURN : IDS_EXIT, ach);
  285. if (flag)
  286. StringCchPrintf(achText, _MAX_PATH, ach, (LPTSTR)FileName(szClientDoc));
  287. else
  288. lstrcpy(achText, ach);
  289. /* Menu option will either say "Close" or "Update" (for embedded obj) */
  290. /* and for update, will have the doc name in the text. */
  291. ModifyMenu(ghMenu, IDM_EXIT, MF_BYCOMMAND, IDM_EXIT, achText);
  292. DrawMenuBar(ghwndApp); /* Can't hurt... */
  293. }
  294. /**************************************************************************
  295. //## MORE STUFF FOR PLAY IN PLACE, should disappear in OLE2.
  296. //VIJR: Nope. Still needed for playing inplace in OLE1 clients.
  297. ***************************************************************************/
  298. void PASCAL DinkWithWindowStyles(HWND hwnd, BOOL fRestore)
  299. {
  300. #define MAX_DINK 80
  301. static LONG_PTR lStyleSave[MAX_DINK];
  302. static HWND hwndSave[MAX_DINK];
  303. static int nSave;
  304. int i;
  305. HWND hwndT;
  306. RECT rc, rcT;
  307. if (!TestWS(hwnd, WS_CHILD))
  308. return;
  309. if (fRestore)
  310. for (i=0; i<nSave; i++)
  311. {
  312. if(IsWindow(hwndSave[i])) {
  313. ClrWS(hwndSave[i],WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  314. SetWS(hwndSave[i],lStyleSave[i] & (WS_CLIPSIBLINGS|WS_CLIPCHILDREN));
  315. }
  316. }
  317. else
  318. {
  319. //
  320. // walk all the siblings that intersect us and set CLIPSIBLINGS
  321. //
  322. i = 0;
  323. GetWindowRect(hwnd, &rc);
  324. for (hwndT = GetWindow(hwnd, GW_HWNDFIRST);
  325. hwndT;
  326. hwndT = GetWindow(hwndT, GW_HWNDNEXT))
  327. {
  328. GetWindowRect(hwndT, &rcT);
  329. if (IntersectRect(&rcT, &rcT, &rc))
  330. {
  331. lStyleSave[i] = GetWS(hwndT);
  332. hwndSave[i] = hwndT;
  333. SetWS(hwndT,WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  334. if (++i == MAX_DINK-4)
  335. break;
  336. }
  337. }
  338. //
  339. // walk up the window chain, making sure we get clipped from our
  340. // parent(s).
  341. //
  342. for (hwndT = hwnd; hwndT; hwndT = GetParent(hwndT))
  343. {
  344. lStyleSave[i] = GetWS(hwndT);
  345. hwndSave[i] = hwndT;
  346. if(IsWindow(hwndT))
  347. SetWS(hwndT,WS_CLIPSIBLINGS|WS_CLIPCHILDREN);
  348. if (++i == MAX_DINK)
  349. break;
  350. }
  351. nSave = i;
  352. }
  353. }
  354. #define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
  355. /**************************************************************************
  356. FileName - return a pointer to the filename part of szPath
  357. with no preceding path.
  358. ***************************************************************************/
  359. LPTSTR FAR FileName(LPCTSTR lszPath)
  360. {
  361. LPCTSTR lszCur;
  362. for (lszCur = lszPath + STRLEN(lszPath); lszCur > lszPath && !SLASH(*lszCur) && *lszCur != TEXT(':');)
  363. lszCur = CharPrev(lszPath, lszCur);
  364. if (lszCur == lszPath)
  365. return (LPTSTR)lszCur;
  366. else
  367. return (LPTSTR)(lszCur + 1);
  368. }
  369. /**************************************************************************
  370. //## This function should be handled by OLE2
  371. //VIJR: Nope. Still needed for playing inplace in OLE1 clients.
  372. ***************************************************************************/
  373. void FAR PASCAL PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
  374. {
  375. if (gfPlayingInPlace) // this is bad
  376. return;
  377. DPF("Using Child window for playback\n");
  378. SetWS(hwndApp, WS_CHILD);
  379. SetParent(hwndApp, hwndClient);
  380. if(!(gfOle2IPEditing || gfOle2IPPlaying))
  381. DinkWithWindowStyles(hwndApp, FALSE);
  382. if(!gfOle2IPEditing)
  383. gfPlayingInPlace = TRUE;
  384. if(gfOle2IPPlaying)
  385. MapWindowPoints(NULL,hwndClient,(LPPOINT)prc,2);
  386. /* For OLE2, now calls MoveWindow in DoInPlaceEdit (inplace.c).
  387. * This fixes 23429, window positioning in Word.
  388. */
  389. if(!(gfOle2IPEditing || gfOle2IPPlaying))
  390. {
  391. SetWindowPos(hwndApp, HWND_TOP,
  392. prc->left,prc->top,
  393. prc->right - prc->left,
  394. prc->bottom - prc->top,
  395. SWP_NOACTIVATE);
  396. }
  397. if(!gfOle2IPPlaying) // OLE1 Clients
  398. {
  399. /*
  400. ** On NT we have to install a global mouse HookProc which has to
  401. ** in a DLL. Also we have to tell the DLL which process/thread we are
  402. ** interested in, therefore let the DLL install the HookProc. When the
  403. ** HookProc detects an "interesting" mouse message it stops the
  404. ** device from playing. However, the device "stopping" function is
  405. ** inside mplayer, so we have to export it so that the HookProc can
  406. ** call it.
  407. */
  408. if ( hMciOle ) {
  409. fpInstallHook = (LPINSTALLHOOK)GetProcAddress( hMciOle,
  410. aszInstallHook );
  411. fpRemoveHook = (LPREMOVEHOOK)GetProcAddress( hMciOle,
  412. aszRemoveHook );
  413. }
  414. else {
  415. fpInstallHook = NULL;
  416. fpRemoveHook = NULL;
  417. }
  418. // Is the key down at this INSTANT ??? Then wait until it comes up before
  419. // we allow GetAsyncKeyState to make us go away
  420. gfMouseUpSeen = !((GetAsyncKeyState(VK_LBUTTON) & 0x8000) ||
  421. (GetAsyncKeyState(VK_RBUTTON) & 0x8000));
  422. // Is GetKeyState saying it's down? If so, wait until GetKeyState returns
  423. // up before we let GetKeyState kill us.
  424. gfKeyStateUpSeen= !(GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON));
  425. #ifdef DEBUG
  426. if ( fHookInstalled ) {
  427. DPF( "Hook already installed\n" );
  428. //DebugBreak();
  429. }
  430. #endif
  431. if ( fpInstallHook ) {
  432. DWORD wow_thread_id = 0L;
  433. /*
  434. ** This is a HACK. If the client applications is a WOW app the
  435. ** HIWORD of the window handle will be 0x0000 or 0xFFFF.
  436. ** Chandan tells me that on Daytona the HIWORD could be
  437. ** either of the above.
  438. */
  439. if ( HIWORD(hwndClient) == 0x0000 || HIWORD(hwndClient) == 0xFFFF) {
  440. wow_thread_id = GetWindowThreadProcessId( hwndClient, NULL );
  441. }
  442. fHookInstalled = (*fpInstallHook)( ghwndApp, wow_thread_id );
  443. }
  444. }
  445. ghwndFocusSave = GetFocus();
  446. }
  447. //This function is new for OLE2. It sets the container window as
  448. //our window's (actually the hatch window's) parent and positions the window
  449. void FAR PASCAL EditInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
  450. {
  451. RECT rc;
  452. rc = *prc;
  453. SetWS(hwndApp, WS_CHILD);
  454. SetParent(hwndApp, hwndClient);
  455. ScreenToClient(hwndClient,(LPPOINT)&rc);
  456. ScreenToClient(hwndClient,(LPPOINT)&rc+1);
  457. if(gwDeviceType & DTMCI_CANWINDOW)
  458. {
  459. /* Sometimes the position (though not the size) of this rectangle
  460. * gets messed up (most reliably in PowerPoint 7).
  461. * I can't figure out why this is happening (see the nightmarish
  462. * code in ReallyDoVerb() to get a flavour of what happens).
  463. * But it turns out that this call is unnecessary in any case,
  464. * since the window has already been positioned properly in
  465. * IPObjSetObjectRects().
  466. * I suspect there's a lot of surplus window-positioning code,
  467. * but now isn't the time to start making major changes.
  468. * This is the minimal change that makes things work.
  469. */
  470. //This fixes NTRaid bug #236641 in Excel. AND bug #247393 in Word
  471. //Sometimes there is confusion between who the parent is. mplay32 sets the document
  472. //window as the parent and the rectangle sent in SetObjectRects might not be with respect to
  473. //the document window (this might happen when the document window is not in the maximized state).
  474. //In this function we know the parent and the rectangle in that parent. Setting
  475. //the position here places our OLE object as the client requires. This change is even safe in
  476. //terms of introducing regressions.
  477. SetWindowPos(hwndApp, HWND_TOP,
  478. rc.left, rc.top,
  479. rc.right - rc.left,
  480. rc.bottom - rc.top,
  481. SWP_NOACTIVATE | SWP_FRAMECHANGED);
  482. }
  483. else if(gwDeviceID)
  484. SetWindowPos(hwndApp, HWND_TOP,
  485. rc.left,rc.top,
  486. rc.right - rc.left,
  487. rc.bottom - rc.top,
  488. SWP_SHOWWINDOW);
  489. else
  490. SetWindowPos(hwndApp, HWND_TOP,
  491. rc.left,rc.top,
  492. rc.right - rc.left,
  493. rc.bottom - rc.top,
  494. SWP_HIDEWINDOW);
  495. ghwndFocusSave = GetFocus();
  496. //Set the focus for the parent.
  497. if((gwDeviceID == (UINT)0) && IsWindow(hwndClient))
  498. {
  499. SetFocus(hwndClient);
  500. }
  501. }
  502. /**************************************************************************
  503. //## This is called to end PlayInPlace and make sure that the window goes
  504. //## away and the also to manage the palette stuff (May go away in OLE2)
  505. //## This function should be handled by OLE2
  506. ***************************************************************************/
  507. void FAR PASCAL EndPlayInPlace(HWND hwndApp)
  508. {
  509. HWND hwndP;
  510. HWND hwndT;
  511. if (!gfPlayingInPlace || !IsWindow(hwndApp))
  512. return;
  513. /* Do this BEFORE hiding our window and BEFORE we do anything that */
  514. /* might yield so client can't redraw with the wrong styles set. */
  515. if (!(gfOle2IPEditing || gfOle2IPPlaying))
  516. DinkWithWindowStyles(hwndApp, TRUE);
  517. gfPlayingInPlace = FALSE;
  518. /*
  519. ** Tell mciole32.dll to remove its mouse HookProc.
  520. */
  521. if ( fHookInstalled && fpRemoveHook ) {
  522. fHookInstalled = !(*fpRemoveHook)();
  523. }
  524. if (gfOle2IPPlaying)
  525. hwndP = ghwndCntr;
  526. else
  527. hwndP = GetParent(hwndApp);
  528. //
  529. // If we have the focus, then restore it to who used to have it.
  530. // ACK!! If the person who used to have it is GONE, we must give it away
  531. // to somebody (who choose our parent) because our child can't
  532. // keep the focus without making windows crash hard during the WM_DESTROY
  533. // (or maybe later whenever it feels like crashing at some random time).
  534. // See bug #8634.
  535. //
  536. if (((hwndT = GetFocus()) != NULL) && GetWindowTask(hwndT) == MGetCurrentTask) {
  537. if (IsWindow(ghwndFocusSave))
  538. SetFocus(ghwndFocusSave);
  539. else
  540. SetFocus(hwndP);
  541. }
  542. if (!hwndP ||
  543. (gwOptions & OPT_BAR) ||
  544. (gwOptions & OPT_BORDER) ||
  545. (gwOptions & OPT_AUTORWD))
  546. {
  547. // hide the aplication window
  548. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  549. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  550. }
  551. else
  552. {
  553. //
  554. // hide our window, but don't redraw it will look
  555. // like we are still on the last frame.
  556. //
  557. // this is when we are playing in place, and there is
  558. // no playbar, and no rewind
  559. //
  560. // this is for Playing a AVI in a PowerPoint slide
  561. // without redraw problems.
  562. //
  563. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  564. SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
  565. SWP_HIDEWINDOW|SWP_NOACTIVATE);
  566. }
  567. SetParent(hwndApp, NULL);
  568. ClrWS(hwndApp, WS_CHILD);
  569. if (hwndP && gfParentWasEnabled)
  570. EnableWindow(hwndP, TRUE);
  571. //
  572. // set either the owner or the WS_CHILD bit so it will
  573. // not act up because we have the palette bit set and cause the
  574. // desktop to steal the palette.
  575. //
  576. SetWS(hwndApp, WS_CHILD);
  577. }
  578. //If we were InPlace editing restore the windows state.
  579. void FAR PASCAL EndEditInPlace(HWND hwndApp)
  580. {
  581. HWND hwndP;
  582. HWND hwndT;
  583. if (!gfOle2IPEditing || !IsWindow(hwndApp))
  584. return;
  585. /* Do this BEFORE hiding our window and BEFORE we do anything that */
  586. /* might yield so client can't redraw with the wrong styles set. */
  587. DinkWithWindowStyles(hwndApp, TRUE);
  588. gfOle2IPEditing = FALSE;
  589. if (gfOle2IPPlaying)
  590. hwndP = ghwndCntr;
  591. else
  592. hwndP = GetParent(hwndApp);
  593. //
  594. // If we have the focus, then restore it to who used to have it.
  595. // ACK!! If the person who used to have it is GONE, we must give it away
  596. // to somebody (who choose our parent) because our child can't
  597. // keep the focus without making windows crash hard during the WM_DESTROY
  598. // (or maybe later whenever it feels like crashing at some random time).
  599. // See bug #8634.
  600. //
  601. if (((hwndT = GetFocus()) != NULL) && GetWindowTask(hwndT) == MGetCurrentTask) {
  602. if (IsWindow(ghwndFocusSave))
  603. SetFocus(ghwndFocusSave);
  604. else
  605. if (IsWindow(hwndP))
  606. SetFocus(hwndP);
  607. }
  608. if (!IsWindow(hwndP) ||
  609. (gwOptions & OPT_BAR) ||
  610. (gwOptions & OPT_BORDER) ||
  611. (gwOptions & OPT_AUTORWD))
  612. {
  613. // hide the aplication window
  614. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  615. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  616. }
  617. else
  618. {
  619. //
  620. // hide our window, but don't redraw it will look
  621. // like we are still on the last frame.
  622. //
  623. // this is when we are playing in place, and there is
  624. // no playbar, and no rewind
  625. //
  626. // this is for Playing a AVI in a PowerPoint slide
  627. // without redraw problems.
  628. //
  629. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  630. SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
  631. SWP_HIDEWINDOW|SWP_NOACTIVATE);
  632. }
  633. SetParent(hwndApp, NULL);
  634. ClrWS(hwndApp, WS_CHILD);
  635. if (IsWindow(hwndP) && gfParentWasEnabled)
  636. EnableWindow(hwndP, TRUE);
  637. //
  638. // set either the owner or the WS_CHILD bit so it will
  639. // not act up because we have the palette bit set and cause the
  640. // desktop to steal the palette.
  641. //
  642. SetWS(hwndApp, WS_CHILD);
  643. }
  644. /* Tell the user that something's amiss with a network call.
  645. * For network-specific errors, call WNetGetLastError,
  646. * otherwise see if it's a system error.
  647. */
  648. void DisplayNetError(DWORD Error)
  649. {
  650. DWORD ErrorCode; // address of error code
  651. TCHAR szDescription[512]; // address of string describing error
  652. TCHAR szProviderName[64]; // address of buffer for network provider name
  653. if (Error == ERROR_EXTENDED_ERROR)
  654. {
  655. if (WNetGetLastError(&ErrorCode, szDescription, CHAR_COUNT(szDescription),
  656. szProviderName, CHAR_COUNT(szProviderName)) == NO_ERROR)
  657. {
  658. Error1(ghwndApp, IDS_NETWORKERROR, szDescription);
  659. return;
  660. }
  661. }
  662. else
  663. {
  664. if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, Error, 0,
  665. szDescription, CHAR_COUNT(szDescription), NULL) > 0)
  666. {
  667. Error1(ghwndApp, IDS_NETWORKERROR, szDescription);
  668. return;
  669. }
  670. }
  671. /* If all else fails:
  672. */
  673. Error(ghwndApp, IDS_UNKNOWNNETWORKERROR);
  674. }
  675. /**************************************************************************
  676. convert a file name to a fully qualifed path name, if the file
  677. exists on a net drive the UNC name is returned.
  678. ***************************************************************************/
  679. STATICFN BOOL NetParseFile(LPTSTR szFile, LPTSTR szDrive, LPTSTR szPath)
  680. {
  681. TCHAR szTemp[MAX_PATH];
  682. BYTE UNBuffer[(MAX_PATH * sizeof(TCHAR)) + sizeof(UNIVERSAL_NAME_INFO)];
  683. DWORD UNBufferSize = sizeof UNBuffer;
  684. DWORD_PTR Error;
  685. LPTSTR pUniversalName;
  686. //
  687. // Turn into a fully qualified path name
  688. //
  689. if (!FileExists(szFile, szPath, MAX_PATH))
  690. return FALSE;
  691. //
  692. // if the file is not drive based (probably UNC)
  693. //
  694. if (szPath[1] != TEXT(':'))
  695. return TRUE;
  696. Error = WNetGetUniversalName(szDrive, UNIVERSAL_NAME_INFO_LEVEL,
  697. UNBuffer, &UNBufferSize);
  698. if (Error == ERROR_NOT_SUPPORTED)
  699. {
  700. /* This means that the network provider doesn't support
  701. * UNC conventions. Give WNetGetConnection a try.
  702. * Note: dynalink.h assumes that WNetGetUniversalName
  703. * will always be called before WNetGetConnection.
  704. */
  705. UNBufferSize = CHAR_COUNT(UNBuffer);
  706. Error = WNetGetConnection(szDrive, (LPTSTR)UNBuffer, &UNBufferSize);
  707. if (Error == NO_ERROR)
  708. {
  709. /* What does the following mean? It was in the original code.
  710. */
  711. if (!SLASH(UNBuffer[0]) || !SLASH(UNBuffer[1]))
  712. return TRUE;
  713. StringCchCat((LPTSTR)UNBuffer, UNBufferSize, szPath+2);
  714. StringCchCopy(szPath, MAX_PATH, (LPTSTR)UNBuffer);
  715. return TRUE;
  716. }
  717. }
  718. if (Error != NO_ERROR)
  719. {
  720. DisplayNetError((DWORD)Error);
  721. return FALSE;
  722. }
  723. pUniversalName = ((LPUNIVERSAL_NAME_INFO)UNBuffer)->lpUniversalName;
  724. StringCchCopy(szTemp, MAX_PATH, pUniversalName);
  725. StringCchCat(szTemp, MAX_PATH, szPath+2);
  726. StringCchCopy(szPath, MAX_PATH, szTemp);
  727. return TRUE;
  728. }
  729. /**************************************************************************
  730. Get the data that represents the currently open MCI file/device. as
  731. a link. MPlayer links look like this:
  732. MPLAYER|<filename>!<MCIDevice> [selection]
  733. //## This is the opposite of parse options and sets the data string to be
  734. //## embedded in the OLE object.
  735. Note we store the data in an ANSI string, regardless of whether we're
  736. compiled as a Unicode app, for Daytona/Chicago/OLE1/OLE2 compatibility.
  737. ***************************************************************************/
  738. HANDLE GetLink( VOID )
  739. {
  740. TCHAR szFileName[MAX_PATH];
  741. TCHAR szFullName[MAX_PATH];
  742. TCHAR szDevice[MAX_DEVICE];
  743. TCHAR szDrive[4];
  744. HANDLE h;
  745. LPSTR p; /* NOT LPTSTR */
  746. int len;
  747. int lenAppName;
  748. int lenFullName;
  749. StringCchCopy(szFileName, MAX_PATH, gachFileDevice);
  750. StringCchCopy(szFullName, MAX_PATH, gachFileDevice);
  751. //
  752. // convert the filename into a UNC file name, if it exists on the net
  753. //
  754. if (gwDeviceType & DTMCI_FILEDEV)
  755. {
  756. if (szFileName[1] == TEXT(':'))
  757. {
  758. /* This is a file name with a drive letter.
  759. * Find out if it's redirected:
  760. */
  761. szDrive[0] = szFileName[0];
  762. szDrive[1] = szFileName[1];
  763. szDrive[2] = TEXT('\\'); // GetDriveType requires the root.
  764. szDrive[3] = TEXT('\0'); // Null-terminate.
  765. if ((szDrive[1] == TEXT(':')) && GetDriveType(szDrive) == DRIVE_REMOTE)
  766. {
  767. szDrive[2] = TEXT('\0'); // Zap backslash.
  768. if (!NetParseFile(szFileName, szDrive, szFullName))
  769. return NULL;
  770. }
  771. }
  772. }
  773. else if (gwDeviceType & DTMCI_SIMPLEDEV)
  774. {
  775. szFullName[0] = 0;
  776. }
  777. if (gwCurDevice == 0)
  778. GetDeviceNameMCI(szDevice, BYTE_COUNT(szDevice));
  779. else
  780. StringCchCopy(szDevice, MAX_DEVICE, garMciDevices[gwCurDevice].szDevice);
  781. #ifdef UNICODE
  782. // length of the string in bytes != length of the string in characters
  783. lenAppName = WideCharToMultiByte(CP_ACP, 0, aszAppName, -1, NULL, 0, NULL, NULL) - 1;
  784. lenFullName = WideCharToMultiByte(CP_ACP, 0, szFullName, -1, NULL, 0, NULL, NULL) - 1;
  785. #else
  786. lenAppName = STRLEN(aszAppName);
  787. lenFullName = STRLEN(szFullName);
  788. #endif
  789. /* How much data will we be writing? */
  790. #ifdef UNICODE
  791. // length of the string in bytes != length of the string in characters
  792. len = 9 + // all the delimeters
  793. lenAppName +
  794. lenFullName +
  795. WideCharToMultiByte(CP_ACP, 0, szDevice, -1, NULL, 0, NULL, NULL)-1 +
  796. 5 + 10 + 10 + 10 + // max length of int and long strings
  797. WideCharToMultiByte(CP_ACP, 0, gachCaption, -1, NULL, 0, NULL, NULL)-1;
  798. #else
  799. len = 9 + // all the delimeters
  800. lenAppName +
  801. lenFullName +
  802. STRLEN(szDevice) +
  803. 5 + 10 + 10 + 10 + // max length of int and long strings
  804. STRLEN(gachCaption);
  805. #endif
  806. h = GlobalAlloc(GMEM_DDESHARE|GMEM_ZEROINIT, len * sizeof(CHAR));
  807. if (!h)
  808. return NULL;
  809. p = GLOBALLOCK(h);
  810. /* This string must have two terminating null characters.
  811. * The GlobalAlloc GMEM_ZEROINIT flag should ensure this.
  812. */
  813. #ifdef UNICODE
  814. wsprintfA(p, "%ws%c%ws%c%ws%c%d%c%d%c%d%c%d%c%d%c%ws",
  815. #else
  816. wsprintfA(p, "%s%c%s%c%s%c%d%c%d%c%d%c%d%c%d%c%s",
  817. #endif
  818. aszAppName,
  819. '*', // placeholder
  820. szFullName,
  821. '*', // placeholder
  822. szDevice, ',',
  823. (gwOptions & ~OPT_SCALE) | gwCurScale, ',',
  824. (long)SendMessage(ghwndTrackbar, TBM_GETSELSTART, 0, 0L), ',',
  825. (long)SendMessage(ghwndTrackbar, TBM_GETSELEND, 0, 0L), ',',
  826. (long)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L), ';',
  827. // new parameter snuck in since initial version
  828. // Height of picture we're giving the client - w/o caption
  829. grcSize.bottom - grcSize.top, ',',
  830. gachCaption);
  831. /* Replace *'s with NULL characters (wsprintf doesn't accept
  832. * 0 as a replacement parameter for %c):
  833. */
  834. p[lenAppName] = '\0';
  835. p[lenAppName + 1 + lenFullName] = '\0';
  836. DPF("Native data %hs has been created\n", p);
  837. GLOBALUNLOCK(h);
  838. return h;
  839. }
  840. /****************************************************************************
  841. DOS share has a bug. If the file we're testing for existence is open
  842. already by someone else, we have to give it the same flag for SHARE as
  843. the other person is using. So we have to try both on and off. Only one
  844. of these will return TRUE but if one of them does, the file exists. Also
  845. we have to try with SHARE first, because the test without share might
  846. give a system modal error box!!!
  847. //## Check to see if DOS 7 has this bug or is it fixed
  848. Parameter iLen is the number of characters in the szFullName buffer
  849. ****************************************************************************/
  850. STATICFN BOOL FileExists(LPTSTR szFile, LPTSTR szFullName, int iLen)
  851. {
  852. DWORD rc;
  853. LPTSTR pFilePart;
  854. rc = SearchPath(NULL, /* Default path search order */
  855. szFile,
  856. NULL, /* szFile includes extension */
  857. (DWORD)iLen,
  858. szFullName,
  859. &pFilePart);
  860. if(rc > (DWORD)iLen)
  861. {
  862. DPF0("Buffer passed to FileExists is of insufficient length\n");
  863. }
  864. return (BOOL)rc;
  865. }
  866. /****************************************************************************
  867. FindRealFileName - If szFile isn't valid, try searching
  868. client directory for it, or anywhere on
  869. the path, or bringing up a locate dlg.
  870. Set szFile to the valid path name.
  871. //## This function is used to repair broken links
  872. Parameter iLen is the number of characters in the szFile buffer
  873. ****************************************************************************/
  874. BOOL FindRealFileName(LPTSTR szFile, int iLen)
  875. {
  876. TCHAR achFile[_MAX_PATH + 1]; /* file or device name buffer */
  877. int iFileSize = _MAX_PATH + 1;
  878. /* This isn't a file device, so don't do anything */
  879. if (!szFile || *szFile == 0)
  880. return TRUE;
  881. /* The file name we've been given is valid, so do nothing. */
  882. //!!! what about share
  883. if (FileExists(szFile, achFile, iLen))
  884. {
  885. StringCchCopy(szFile, iLen, achFile);
  886. return TRUE;
  887. }
  888. DPF("FindRealFileName: Can't find file '%"DTS"'\n", szFile);
  889. DPF("FindRealFileName: ...Looking on the $PATH\n");
  890. /* Look for the file anywhere */
  891. StringCchCopy(achFile, iFileSize, FileName(szFile));
  892. if (FileExists(achFile, szFile, iLen))
  893. return TRUE;
  894. return FALSE;
  895. }
  896. /**************************************************************************
  897. * SubClassedMCIWndProc:
  898. * This the WndProc function used to sub-class the Play Back window.
  899. * This function is used to trap the drag-drops and also
  900. * to route the WM_CLOSE to the IDM_CLOSE of Mplayer.
  901. **************************************************************************/
  902. LONG_PTR FAR PASCAL SubClassedMCIWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
  903. {
  904. static BOOL fDragCapture = FALSE;
  905. static RECT rcWin;
  906. POINT pt;
  907. LONG_PTR lRc;
  908. switch(wMsg)
  909. {
  910. case WM_LBUTTONDOWN:
  911. // break; // Disable drag from MPlayer! It's broken.
  912. if (!gfOle2IPEditing)
  913. {
  914. fDragCapture = TRUE;
  915. SetCapture(hwnd);
  916. GetClientRect(hwnd, (LPRECT)&rcWin);
  917. MapWindowPoints(hwnd, NULL, (LPPOINT)&rcWin, 2);
  918. }
  919. break;
  920. case WM_LBUTTONUP:
  921. if (!fDragCapture)
  922. break;
  923. fDragCapture = FALSE;
  924. ReleaseCapture();
  925. break;
  926. case WM_MOUSEMOVE:
  927. if (!fDragCapture)
  928. break;
  929. LONG2POINT(lParam, pt);
  930. MapWindowPoints(hwnd, NULL, &pt, 1);
  931. if (!PtInRect((LPRECT)&rcWin, pt))
  932. {
  933. ReleaseCapture();
  934. DoDrag();
  935. fDragCapture = FALSE;
  936. }
  937. SetCursor(LoadCursor(ghInst,MAKEINTRESOURCE(IDC_DRAG)));
  938. break;
  939. case WM_CLOSE:
  940. if (gfSeenPBCloseMsg || gfOle2IPEditing || gfOle2IPPlaying) {
  941. lRc = CallWindowProc(gfnMCIWndProc, hwnd, wMsg, wParam, lParam);
  942. } else {
  943. gfSeenPBCloseMsg = TRUE;
  944. PostMessage(ghwndApp,WM_COMMAND,IDM_CLOSE,0L);
  945. lRc = 0L;
  946. }
  947. CleanUpDrag();
  948. return lRc;
  949. case WM_DESTROY:
  950. ghwndSubclass = NULL;
  951. CleanUpDrag();
  952. break;
  953. case WM_ACTIVATE:
  954. /* Get the app's main window somewhere it can be seen
  955. * if the MCI window gets activated:
  956. */
  957. if (((WORD)wParam != 0) && !IsIconic(ghwndApp))
  958. {
  959. SetWindowPos(ghwndApp, hwnd, 0, 0, 0, 0,
  960. SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
  961. }
  962. break;
  963. }
  964. return CallWindowProc(gfnMCIWndProc, hwnd, wMsg, wParam, lParam);
  965. }
  966. /**************************************************************************
  967. * SubClassMCIWindow:
  968. * This function sub-classes the Play Back window by hooking in
  969. * SubClassedMCIWndProc function.
  970. **************************************************************************/
  971. void SubClassMCIWindow(void)
  972. {
  973. HWND hwndMCI;
  974. hwndMCI = GetWindowMCI();
  975. if(!IsWindow(hwndMCI))
  976. return;
  977. if (gfnMCIWndProc != NULL && IsWindow(ghwndSubclass)) {
  978. SetWindowLongPtr(ghwndSubclass, GWLP_WNDPROC, (LONG_PTR)gfnMCIWndProc);
  979. }
  980. gfnMCIWndProc = (WNDPROC)GetWindowLongPtr(hwndMCI, GWLP_WNDPROC);
  981. if (hwndMCI)
  982. SetWindowLongPtr(hwndMCI, GWLP_WNDPROC, (LONG_PTR)SubClassedMCIWndProc);
  983. ghwndSubclass = hwndMCI;
  984. gfSeenPBCloseMsg = FALSE;
  985. #ifdef CHICAGO_PRODUCT
  986. SendMessage(hwndMCI, WM_SETICON, FALSE,
  987. (LPARAM)GetIconForCurrentDevice(GI_SMALL, IDI_DDEFAULT));
  988. SetWindowText(hwndMCI, gachCaption);
  989. #endif
  990. }
  991. INT_PTR FAR PASCAL FixLinkDialog(LPTSTR szFile, LPTSTR szDevice, int iLen);
  992. /* ANSI-to-Unicode version of lstrcpyn:
  993. *
  994. * Zero terminates the buffer in case it isn't long enough,
  995. * then maps as many characters as will fit into the Unicode buffer.
  996. *
  997. */
  998. #define LSTRCPYNA2W(strW, strA, buflen) \
  999. strW[buflen-1] = L'\0', \
  1000. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, \
  1001. (strA), min( strlen( strA )+1, (buflen)-1 ), \
  1002. (strW), ((buflen)-1) )
  1003. /**************************************************************************
  1004. * ItemSetData(LPBYTE p): This function is left over from OLE1 days, but is
  1005. * very important because the embedded data is still the same. This function
  1006. * parses the embedded data and opens the appropriate device/file and sets
  1007. * everything in motion. "p" is the pointer memory block having the embedded
  1008. * data.
  1009. * Note we store the data in an ANSI string, regardless of whether we're
  1010. * compiled as a Unicode app, for Daytona/Chicago/OLE1/OLE2 compatibility.
  1011. **************************************************************************/
  1012. SCODE ItemSetData(LPBYTE p)
  1013. {
  1014. LPSTR pSave, pT;
  1015. LPSTR szFile, szDevice;
  1016. CHAR ach[40];
  1017. TCHAR achFile[_MAX_PATH];
  1018. TCHAR achCaption[_MAX_PATH];
  1019. LPTSTR pDevice = NULL;
  1020. SCODE scode = E_FAIL;
  1021. int iCnt = 0;
  1022. if (p && *p != 0)
  1023. {
  1024. szFile = p + strlen(p) + 1; // pick off the Filename
  1025. p = szFile + strlen(szFile) + 1;
  1026. pSave = p;
  1027. szDevice = ach; // copy over Device name and
  1028. for (pT = ach; *p && *p != ',' && iCnt < 39;) // NULL terminate it (it ends
  1029. { // with a ',' right now).
  1030. iCnt++;
  1031. *pT++ = *p++;
  1032. }
  1033. *pT = '\0';
  1034. /* It is OK for szFile and szDevice to be empty, since we may have
  1035. * a Media Clip object with no device or file selected
  1036. */
  1037. DPF("%hs|%hs!%hs\n", p, szFile, szDevice);
  1038. CloseMCI(TRUE); // nuke old gachCaption
  1039. scode = ParseOptions(pSave); // this will set new gachCaption
  1040. if (scode != S_OK)
  1041. return scode;
  1042. // If this file doesn't exist, we won't continue setting data, we
  1043. // will succeed and get out, and do it later, because we can't
  1044. // bring up a dialog right now because clients like WinWord
  1045. // won't dispatch any msgs.
  1046. #ifdef UNICODE
  1047. LSTRCPYNA2W(achFile, szFile, CHAR_COUNT(achFile));
  1048. #else
  1049. lstrcpyn(achFile, szFile, CHAR_COUNT(achFile));
  1050. #endif
  1051. // Check for file existence. if the filename we were given is bad,
  1052. // try and find it somewhere on the disk
  1053. #ifdef UNICODE
  1054. pDevice = AllocateUnicodeString(szDevice);
  1055. if (!pDevice)
  1056. return E_OUTOFMEMORY;
  1057. #else
  1058. pDevice = szDevice;
  1059. #endif
  1060. if (FindRealFileName(achFile, CHAR_COUNT(achFile)))
  1061. {
  1062. lstrcpy(achCaption, gachCaption); //Save caption.
  1063. if (OpenMciDevice(achFile, pDevice))
  1064. {
  1065. /* Set the selection to what we parsed in ParseOptions. */
  1066. SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
  1067. SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
  1068. }
  1069. lstrcpy(gachCaption, achCaption); //Restore Caption
  1070. }
  1071. else if (FixLinkDialog(achFile, pDevice, sizeof(achFile)) )
  1072. {
  1073. if (OpenMciDevice(achFile, pDevice))
  1074. {
  1075. /* Set the selection to what we parsed in ParseOptions. */
  1076. SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
  1077. SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
  1078. gfBrokenLink = TRUE;
  1079. }
  1080. }
  1081. else
  1082. scode = E_FAIL;
  1083. }
  1084. #ifdef UNICODE
  1085. FreeUnicodeString(pDevice);
  1086. #endif
  1087. return scode;
  1088. }
  1089. /**************************************************************************
  1090. * UpdateObject() - handle the update of the object
  1091. * If the object has changed in content or appearance a message is
  1092. * sent to the container.
  1093. ***************************************************************************/
  1094. void UpdateObject(void)
  1095. {
  1096. LONG lPos;
  1097. if((gfOle2IPPlaying || gfPlayingInPlace) && !fDocChanged)
  1098. return;
  1099. if (IsWindow(ghwndTrackbar))
  1100. lPos = (LONG)SendMessage(ghwndTrackbar, TBM_GETPOS, 0, 0L);
  1101. else
  1102. lPos = -1;
  1103. if (gfEmbeddedObject &&
  1104. (fDocChanged || ((lPos >= 0) && (lPos != (LONG)gdwPosition)
  1105. && (gwDeviceType & DTMCI_CANWINDOW))))
  1106. {
  1107. //
  1108. // Some clients (e.g. Excel 3.00 and PowerPoint 1.0) don't
  1109. // handle saved notifications; they expect to get an
  1110. // OLE_CLOSED message.
  1111. //
  1112. // We will send an OLE_CLOSED message right before we
  1113. // revoke the DOC iff gfDirty == -1 (see FileNew()).
  1114. //
  1115. if ((lPos >= 0) && (lPos != (LONG)gdwPosition) && (gwDeviceType & DTMCI_CANWINDOW))
  1116. {
  1117. gdwPosition = (DWORD)lPos;
  1118. SendDocMsg((LPDOC)&docMain,OLE_CHANGED);
  1119. }
  1120. if (fDocChanged)
  1121. SendDocMsg(&docMain, OLE_SAVEOBJ);
  1122. }
  1123. }
  1124. /**************************************************************************
  1125. * int FAR PASCAL ReallyDoVerb: This is the main function in the server stuff.
  1126. * This function used to implement the PlayInPlace in OLE1. Most of the code
  1127. * has not been changed and has been used to munge the MPlayer for EditInPlace
  1128. * in OLE2. For OLE2 this function calls DoInPlaceEdit to get the containers
  1129. * hwnd and Object rectangle. For OLE1 clients the rectangle is still got
  1130. * from the OleQueryObjPos funtion in mciole.dll. A new twist in the PlayVerb
  1131. * is that if we are just hidden in a deactivated state we just reappear
  1132. * and play instead of PlayingInPlace without the toolbars etc. This function
  1133. * is also called when reactivating, deactivating etc. The BOOL SkipInPlaceEdit
  1134. * is used to avoid redoing all the stuff if we are just reactivating.
  1135. ***************************************************************************/
  1136. int FAR PASCAL ReallyDoVerb (
  1137. LPDOC lpobj,
  1138. LONG verb,
  1139. LPMSG lpmsg,
  1140. LPOLECLIENTSITE lpActiveSite,
  1141. BOOL fShow,
  1142. BOOL fActivate)
  1143. {
  1144. BOOL fWindowWasVisible = IsWindowVisible(ghwndApp);
  1145. int dx,dy;
  1146. HWND hwndClient;
  1147. HWND hwndT;
  1148. RECT rcSave;
  1149. RECT rcClient;
  1150. RECT rc;
  1151. LONG err;
  1152. SCODE sc;
  1153. HPALETTE hpal;
  1154. HDC hdc;
  1155. INT xTextExt;
  1156. int yOrig, yNow, xOrig, ytitleNow, xtitleOrig, xNow;
  1157. int xIndent = 0; // Avoid warning C4701: local variable 'xIndent'
  1158. // may be used without having been initialized
  1159. int wWinNow;
  1160. HWND hwndMCI;
  1161. int Result = S_OK;
  1162. DPFI("VERB = %d\n", verb);
  1163. /* MSProject assumes that our primary verb is Edit; in fact it's Play.
  1164. * So when we're called with the default verb, make sure we've loaded
  1165. * something from storage and, if not, do the Edit thing.
  1166. *
  1167. * Nope, that doesn't work, because if you insert an object, deactivate
  1168. * it and then play it, PSLoad hasn't been called. A better bet is
  1169. * to check whether we have a current device.
  1170. */
  1171. if (gfRunWithEmbeddingFlag && gwDeviceType == 0)
  1172. {
  1173. if (verb == OLEIVERB_PRIMARY)
  1174. {
  1175. DPF("Primary Verb called without current device -- changing verb to Edit...\n");
  1176. verb = verbEdit;
  1177. }
  1178. }
  1179. /* If a Media Clip is currently open, the user can give the focus back
  1180. * to the container and issue another verb or double-click the object.
  1181. * If this happens, set the focus back to the open object.
  1182. *
  1183. * We don't need to worry about resetting fObjectOpen, since the server
  1184. * shuts down when the user exits and returns to the container.
  1185. */
  1186. if (gfOle2Open)
  1187. {
  1188. SetFocus(ghwndApp);
  1189. return S_OK;
  1190. }
  1191. // This is the first verb we are seeing. So the container must
  1192. // have the focus. Save it so that we can return it later.
  1193. if (glCurrentVerb == NOVERB)
  1194. ghwndFocusSave = GetFocus();
  1195. if (verb == OLEIVERB_PRIMARY && !gfOle2IPEditing && (glCurrentVerb != verbEdit))
  1196. {
  1197. EnableMenuItem((HMENU)GetMenu(ghwndApp), IDM_CLOSE, MF_GRAYED);
  1198. }
  1199. glCurrentVerb = verb;
  1200. //
  1201. // dont even try to nest things.
  1202. //
  1203. if (gfPlayingInPlace && verb != OLEIVERB_HIDE)
  1204. return OLE_OK;
  1205. if (gfBrokenLink)
  1206. {
  1207. PostMessage(ghwndApp, WM_SEND_OLE_CHANGE, 0, 0L);
  1208. gfBrokenLink = FALSE;
  1209. }
  1210. //We are just reactivating. Don't do through all the steps again.
  1211. if (gfOle2IPEditing)
  1212. SkipInPlaceEdit = TRUE;
  1213. // Make sure the timer's doing the right thing:
  1214. gfAppActive = ( verb != OLEIVERB_HIDE );
  1215. // NTVDM can get into a spin if we have too meany TIMER messages,
  1216. // so make sure we don't have any if there's no device.
  1217. if (gwDeviceID)
  1218. EnableTimer( gfAppActive );
  1219. else
  1220. EnableTimer( FALSE );
  1221. if (verb == OLEIVERB_PRIMARY)
  1222. {
  1223. gfOle1Client = FALSE;
  1224. //We are already up but deactivated. Just come up and play.
  1225. if (gfOle2IPEditing)
  1226. {
  1227. if (!(gwDeviceType & DTMCI_CANWINDOW))
  1228. {
  1229. Result = ReallyDoVerb(lpobj, verbEdit, lpmsg, lpActiveSite, fShow, fActivate);
  1230. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1231. }
  1232. else
  1233. {
  1234. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1235. err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verbEdit, &hwndClient,
  1236. &rcClient));
  1237. if (err)
  1238. {
  1239. SHOWAPPWINDOW(SW_HIDE);
  1240. PostMessage(ghwndApp,WM_CLOSE,0,0);
  1241. return((int)err);
  1242. }
  1243. gfInPlaceResize = TRUE;
  1244. rcClient = gInPlacePosRect;
  1245. MapWindowPoints(NULL,ghwndCntr,(LPPOINT)&rcClient,2);
  1246. DPF("IOleInPlaceSite::OnPosRectChange %d, %d, %d, %d\n", rcClient);
  1247. if (!gfInPPViewer)
  1248. IOleInPlaceSite_OnPosRectChange(docMain.lpIpData->lpSite, &rcClient);
  1249. toolbarSetFocus(ghwndToolbar, BTN_PLAY);
  1250. SetFocus(ghwndToolbar);
  1251. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1252. }
  1253. }
  1254. else
  1255. {
  1256. if(gwDeviceID == (UINT)0) //Play without a device !?!!!
  1257. {
  1258. PostMessage(ghwndApp, WM_CLOSE, 0, 0L);
  1259. sc = E_FAIL;
  1260. return (int)sc;
  1261. }
  1262. // if the device can't window and the user does not want a playbar
  1263. // dont play in place - just start the media and run invisible.
  1264. //
  1265. if (!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1266. gwOptions &= ~OPT_PLAY;
  1267. // Select the palette in right now on behalf of the active
  1268. // window, so USER will think it is palette aware.
  1269. //
  1270. // any palette will do we dont even have to realize it!!
  1271. //
  1272. if (((hpal = PaletteMCI()) != NULL) && ((hwndT = GetActiveWindow()) != NULL))
  1273. {
  1274. hdc = GetDC(hwndT);
  1275. hpal = SelectPalette(hdc, hpal, FALSE);
  1276. SelectPalette(hdc, hpal, FALSE);
  1277. ReleaseDC(hwndT, hdc);
  1278. }
  1279. if (ghwndClient)
  1280. {
  1281. hwndClient = ghwndClient;
  1282. err = gerr;
  1283. rcClient = grcClient;
  1284. ghwndClient = NULL;
  1285. }
  1286. else
  1287. {
  1288. err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verb, &hwndClient,
  1289. &rcClient));
  1290. if (err != S_OK)
  1291. {
  1292. err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
  1293. if (err == S_OK)
  1294. {
  1295. gfOle1Client = TRUE;
  1296. ghwndCntr = hwndClient;
  1297. }
  1298. }
  1299. else
  1300. {
  1301. if (gwOptions & OPT_TITLE)
  1302. gwOptions |= OPT_BAR;
  1303. else
  1304. gwOptions &= ~OPT_BAR;
  1305. }
  1306. }
  1307. /* We want to play in place and we can. */
  1308. /* If we're a link, not an embedded object, and there was an instance*/
  1309. /* of MPlayer up when we said "Play" that was already editing this */
  1310. /* file, we don't want to play in place... we'll just play in that */
  1311. /* instance. We can tell this by the fact that our main MPlayer */
  1312. /* window is already visible. */
  1313. if ((err == S_OK)
  1314. && (!gfOle1Client
  1315. || (gwOptions & OPT_PLAY)) /* Ignore Play in client doc for OLE2 clients */
  1316. && (gfOle2IPPlaying
  1317. || (IsWindow(hwndClient)
  1318. && IsWindowVisible(hwndClient)
  1319. && !fWindowWasVisible)))
  1320. {
  1321. rc = grcSize; // default playback window size for this movie
  1322. /* If we can't window, or something's wrong, use ICON size */
  1323. if (IsRectEmpty(&rc))
  1324. SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
  1325. GetSystemMetrics(SM_CYICON));
  1326. /* rcSave is the area for the MCI window above the control bar */
  1327. /* (if we have one). */
  1328. /* rcClient is the area of the MCI window (0 based) to play in.*/
  1329. /* Control bar may be longer than picture, so rcClient may be */
  1330. /* smaller than rcSave. */
  1331. rcSave = rcClient; // remember stretched size
  1332. /* Make rcClient 0 based from rcSave */
  1333. rcClient.left = 0;
  1334. rcClient.right = rcSave.right - rcSave.left;
  1335. rcClient.top = 0;
  1336. rcClient.bottom = rcSave.bottom - rcSave.top;
  1337. /* Assume playbar will be regular height for now */
  1338. if (gwOptions & OPT_BAR)
  1339. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1340. else
  1341. gwPlaybarHeight = 0;
  1342. //
  1343. // munge rectangle to account for a title in the picture
  1344. // and the fact that picture is centred above title.
  1345. // Remember, it's been stretched around.
  1346. //
  1347. if (gwOptions & OPT_TITLE)
  1348. {
  1349. SIZE Size;
  1350. hdc = GetDC(NULL);
  1351. if (ghfontMap)
  1352. SelectObject(hdc, ghfontMap);
  1353. GetTextExtentPoint32(hdc, gachCaption,
  1354. STRLEN(gachCaption), &Size);
  1355. xTextExt = Size.cx;
  1356. ReleaseDC(NULL, hdc);
  1357. yOrig = rc.bottom - rc.top;
  1358. xOrig = rc.right - rc.left;
  1359. xtitleOrig = max(xTextExt + 4, xOrig);
  1360. yNow = rcClient.bottom - rcClient.top;
  1361. xNow = rcClient.right - rcClient.left;
  1362. ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
  1363. / (yOrig + TITLE_HEIGHT));
  1364. /* for windowed devices, center the playback area above the */
  1365. /* control bar if the control bar is longer. */
  1366. if (gwDeviceType & DTMCI_CANWINDOW)
  1367. {
  1368. wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
  1369. xIndent = (xNow - wWinNow) / 2;
  1370. rcClient.left += xIndent;
  1371. rcClient.right = rcClient.left + wWinNow;
  1372. }
  1373. // Align top of control bar with the top of the title bar.
  1374. // The control bar (if there) will appear under rcSave.
  1375. rcClient.bottom = rcClient.top + yNow - ytitleNow;
  1376. rcSave.bottom = rcSave.top + yNow - ytitleNow;
  1377. /* When we make the playbar, make it cover the title */
  1378. /* if the caption was stretched taller than ordinary.*/
  1379. if (gwOptions & OPT_BAR)
  1380. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1381. }
  1382. /* Enforce a minimum width for the control bar */
  1383. if ((gwOptions & OPT_BAR) &&
  1384. (rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON)))
  1385. {
  1386. rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
  1387. if (gwDeviceType & DTMCI_CANWINDOW)
  1388. xIndent = TRUE; // force SetWindowMCI to be called to
  1389. // avoid stretching to this new size.
  1390. }
  1391. if (gwDeviceType & DTMCI_CANWINDOW)
  1392. {
  1393. // THIS CODE IS USED TO AVOID SLOW PLAYBACK
  1394. // If we've only stretched a bit, don't stretch at all.
  1395. // We might be off a bit due to rounding problems.
  1396. //
  1397. dx = (rcClient.right - rcClient.left) - (rc.right - rc.left);
  1398. dy = (rcClient.bottom - rcClient.top) - (rc.bottom - rc.top);
  1399. if (dx && abs(dx) <= 2)
  1400. {
  1401. rcClient.right = rcClient.left + (rc.right - rc.left);
  1402. // Fix Save rect too
  1403. rcSave.right = rcSave.left + (rc.right - rc.left);
  1404. }
  1405. if (dy && abs(dy) <= 2)
  1406. {
  1407. rcClient.bottom = rcClient.top + (rc.bottom - rc.top);
  1408. // Fix Save rect, too.
  1409. rcSave.bottom = rcSave.top + (rc.bottom - rc.top);
  1410. }
  1411. //
  1412. // Try to get the right palette from the client. If our
  1413. // presentation data was dithered, or the user asked us to
  1414. // always use the object palette, then ignore any client
  1415. // palette.
  1416. //
  1417. #ifdef DEBUG
  1418. if (GetProfileInt(TEXT("options"), TEXT("UseClientPalette"),
  1419. !(gwOptions & OPT_USEPALETTE)))
  1420. gwOptions &= ~OPT_USEPALETTE;
  1421. else
  1422. gwOptions |= OPT_USEPALETTE;
  1423. #endif
  1424. if (!(gwOptions & OPT_USEPALETTE)&& !(gwOptions & OPT_DITHER))
  1425. {
  1426. //
  1427. // Try to get a OWNDC Palette of the client. PowerPoint
  1428. // uses a PC_RESERVED palette in "SlideShow" mode, so
  1429. // we must use its exact palette.
  1430. //
  1431. hdc = GetDC(ghwndCntr);
  1432. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  1433. SelectPalette(hdc, hpal, FALSE);
  1434. ReleaseDC(ghwndCntr, hdc);
  1435. if (hpal == NULL || hpal==GetStockObject(DEFAULT_PALETTE))
  1436. {
  1437. /* Assume client realized the proper palette for us */
  1438. if (ghpalApp)
  1439. DeleteObject(ghpalApp);
  1440. hpal = ghpalApp = CreateSystemPalette();
  1441. }
  1442. else
  1443. DPF("Using clients OWNDC palette\n");
  1444. if (hpal)
  1445. SetPaletteMCI(hpal);
  1446. }
  1447. else
  1448. DPF("Using MCI Object's normal palette\n");
  1449. }
  1450. else
  1451. {
  1452. //
  1453. // for non window devices, just have the playbar show up!
  1454. // so use a zero height MCI Window area.
  1455. //
  1456. rcSave.top = rcSave.bottom;
  1457. }
  1458. //
  1459. // if we are not in small mode, get there now
  1460. //
  1461. if (!gfPlayOnly)
  1462. {
  1463. SHOWAPPWINDOW(SW_HIDE);
  1464. gfPlayOnly = TRUE;
  1465. SizeMPlayer();
  1466. }
  1467. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1468. if (gwOptions & OPT_BORDER)
  1469. SetWS(ghwndApp, WS_BORDER);
  1470. /* Set the size of Mplayer to have enough space for the MCI */
  1471. /* playback area and a playbar and the non-client area. */
  1472. rcSave.bottom += gwPlaybarHeight;
  1473. AdjustWindowRect(&rcSave, (DWORD)GetWS(ghwndApp), FALSE);
  1474. if (!(gwDeviceType & DTMCI_CANWINDOW))
  1475. {
  1476. rcSave.left += 2*GetSystemMetrics(SM_CXBORDER);
  1477. rcSave.right -= 2*GetSystemMetrics(SM_CXBORDER);
  1478. }
  1479. PlayInPlace(ghwndApp, hwndClient, &rcSave);
  1480. if (!gfOle2IPEditing)
  1481. gfCloseAfterPlaying = TRUE;
  1482. fShow = FALSE;
  1483. fActivate = FALSE;
  1484. /* become visible */
  1485. SHOWAPPWINDOW(SW_SHOW);
  1486. /* Remember to play the video in the rcClient area of rcSave */
  1487. if ((gwDeviceType & DTMCI_CANWINDOW) &&
  1488. (gwOptions & OPT_TITLE) && xIndent != 0)
  1489. SetDestRectMCI(&rcClient);
  1490. /* Let keyboard interface work on control bar, and let the */
  1491. /* accelerators go through. */
  1492. toolbarSetFocus(ghwndToolbar, BTN_PLAY);
  1493. SetFocus(ghwndToolbar);
  1494. /* We won't play in place - use a popup window or nothing. */
  1495. }
  1496. else
  1497. {
  1498. /* If we want a playbar, then use MPlayer reduced mode to play. */
  1499. /* If we don't want one, then don't show mplayer's window - */
  1500. /* we'll just use the default MCI window (for a windowed device)*/
  1501. /* or nothing for a non-windowed device. If we stole an already*/
  1502. /* running instance of mplayer, we must use it and not run */
  1503. /* silently. */
  1504. DPF("DoVerb: Not is play in place stuff ");
  1505. if ((gwOptions & OPT_BAR) || fWindowWasVisible)
  1506. {
  1507. DPF("Using Toplevel window for playback\n");
  1508. /* go to our little miniature version */
  1509. if (!gfPlayOnly && !fWindowWasVisible)
  1510. {
  1511. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1512. gfPlayOnly = TRUE;
  1513. SizeMPlayer();
  1514. }
  1515. fShow = fActivate = TRUE;
  1516. gfCloseAfterPlaying = !fWindowWasVisible;
  1517. }
  1518. else
  1519. {
  1520. DPF("Running silently\n");
  1521. if (!fWindowWasVisible)
  1522. SetWindowMCI(NULL);
  1523. // make sure we're using default MCI win
  1524. fShow = fActivate = FALSE;
  1525. // DIE when you are done playing
  1526. gfCloseAfterPlaying = TRUE; // we're invisible, so close auto.
  1527. }
  1528. }
  1529. Yield(); // If play goes to full screen mode, PowerPig will
  1530. Yield(); // time out and put up errors thinking we didn't play.
  1531. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1532. }
  1533. }
  1534. else if (verb == verbEdit ||
  1535. verb == verbOpen ||
  1536. verb == OLEIVERB_OPEN ||
  1537. verb == OLEIVERB_SHOW ||
  1538. verb == OLEIVERB_INPLACEACTIVATE ||
  1539. verb == OLEIVERB_UIACTIVATE)
  1540. {
  1541. gfOle1Client = FALSE;
  1542. #ifdef DEBUG
  1543. switch(verb)
  1544. {
  1545. case verbEdit: DPFI("VERBEDIT\r\n");break;
  1546. case OLEIVERB_SHOW: DPFI("OLEIVERB_SHOW\r\n");break;
  1547. case OLEIVERB_INPLACEACTIVATE: DPFI("OLEIVERB_IPACTIVATE\r\n");break;
  1548. case OLEIVERB_UIACTIVATE: DPFI("OLEIVERB_UIACTIVATE\r\n");break;
  1549. }
  1550. #endif
  1551. // If we are already playing inside an Icon, then restore..
  1552. hwndMCI = GetWindowMCI();
  1553. if (IsWindow(hwndMCI) && IsIconic(hwndMCI))
  1554. SendMessage(hwndMCI, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1555. // If we come up empty, it's OK to be in OPEN or NOT_READY mode
  1556. // and don't try to seek anywhere.
  1557. if (gwDeviceID)
  1558. {
  1559. switch (gwStatus)
  1560. {
  1561. case MCI_MODE_OPEN:
  1562. case MCI_MODE_NOT_READY:
  1563. Error(ghwndApp, IDS_CANTPLAY);
  1564. break;
  1565. default:
  1566. // Seek to the position we were when we copied.
  1567. // Stop first.
  1568. if (StopMCI())
  1569. {
  1570. // fix state so Seek recognizes we're stopped
  1571. gwStatus = MCI_MODE_STOP;
  1572. SeekMCI(gdwPosition);
  1573. }
  1574. break;
  1575. }
  1576. }
  1577. // Let UpdateDisplay set focus properly by saying we're invalid
  1578. // FORCES UPDATE
  1579. gwStatus = (UINT)(-1);
  1580. if (((hpal = PaletteMCI()) != NULL) && ((hwndT = GetActiveWindow()) != NULL))
  1581. {
  1582. hdc = GetDC(hwndT);
  1583. hpal = SelectPalette(hdc, hpal, FALSE);
  1584. SelectPalette(hdc, hpal, FALSE);
  1585. ReleaseDC(hwndT, hdc);
  1586. }
  1587. if (verb == verbOpen || verb == OLEIVERB_OPEN)
  1588. {
  1589. DoInPlaceDeactivate(lpobj);
  1590. gfOle2IPEditing = FALSE;
  1591. gfPlayOnly = FALSE;
  1592. SetWindowPos(ghwndApp, NULL, 0, 0, 0, 0,
  1593. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|SWP_NOACTIVATE);
  1594. SetParent(ghwndApp, NULL);
  1595. PutWS(ghwndApp, WS_THICKFRAME | WS_OVERLAPPED | WS_CAPTION |
  1596. WS_CLIPCHILDREN | WS_SYSMENU | WS_MINIMIZEBOX);
  1597. TransferTools(ghwndApp);
  1598. if (lpobj->lpoleclient) /* This is NULL if it's the first verb issued to a link */
  1599. IOleClientSite_OnShowWindow(lpobj->lpoleclient, TRUE);
  1600. SendMessage(ghwndTrackbar, TBM_SHOWTICS, TRUE, FALSE);
  1601. gfOle2Open = TRUE; /* This global is referenced in SizeMPlayer */
  1602. SizeMPlayer();
  1603. SHOWAPPWINDOW(SW_SHOW);
  1604. }
  1605. else if((err = GetScode(DoInPlaceEdit(lpobj, lpmsg, lpActiveSite, verb, &hwndClient,
  1606. &rcClient))) !=S_OK)
  1607. {
  1608. err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
  1609. if (err == S_OK)
  1610. {
  1611. gfOle1Client = TRUE;
  1612. }
  1613. gfOle2IPEditing = FALSE;
  1614. if (gfPlayOnly)
  1615. {
  1616. gfPlayOnly = FALSE;
  1617. SizeMPlayer();
  1618. }
  1619. }
  1620. else
  1621. {
  1622. if (gwOptions & OPT_TITLE)
  1623. gwOptions |= OPT_BAR;
  1624. else
  1625. gwOptions &= ~OPT_BAR;
  1626. }
  1627. if (gfOle2IPEditing && SkipInPlaceEdit)
  1628. {
  1629. gfInPlaceResize = TRUE;
  1630. if(!(gwDeviceType & DTMCI_CANWINDOW) && (gwOptions & OPT_BAR))
  1631. {
  1632. yNow = rcClient.bottom - rcClient.top;
  1633. if (gwOldHeight)
  1634. {
  1635. ytitleNow = (int)((long)yNow * gwPlaybarHeight/gwOldHeight);
  1636. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1637. gwOldHeight = yNow;
  1638. rcClient.top = rcClient.bottom - gwPlaybarHeight;
  1639. }
  1640. else
  1641. {
  1642. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1643. rcClient.top = rcClient.bottom - gwPlaybarHeight;
  1644. ytitleNow = rcClient.bottom - rcClient.top;
  1645. gwOldHeight = yNow;
  1646. }
  1647. }
  1648. if(!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1649. rcClient.bottom = rcClient.top = rcClient.left = rcClient.right = 0;
  1650. EditInPlace(ghwndApp, hwndClient, &rcClient);
  1651. Layout();
  1652. }
  1653. else
  1654. if (gfOle2IPEditing && gwDeviceID == (UINT)0 && IsWindow(ghwndFrame))
  1655. EditInPlace(ghwndApp, hwndClient, &rcClient);
  1656. if(gfOle2IPEditing && gwDeviceID != (UINT)0 && !SkipInPlaceEdit)
  1657. {
  1658. gwOldOptions = gwOptions;
  1659. rc = grcSize; // default playback window size for this movie
  1660. /* If we can't window, or something's wrong, use ICON size */
  1661. if (IsRectEmpty(&rc))
  1662. SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
  1663. GetSystemMetrics(SM_CYICON));
  1664. /* rcSave is the area for the MCI window above the control bar */
  1665. /* (if we have one). */
  1666. /* rcClient is the area of the MCI window (0 based) to play in.*/
  1667. /* Control bar may be longer than picutre, so rcClient may be */
  1668. /* smaller than rcSave. */
  1669. rcSave = rcClient; // remember stretched size
  1670. /* Make rcClient 0 based from rcSave */
  1671. rcClient.left = 0;
  1672. rcClient.right = rcSave.right - rcSave.left;
  1673. rcClient.top = 0;
  1674. rcClient.bottom = rcSave.bottom - rcSave.top;
  1675. /* Assume playbar will be regular height for now */
  1676. if (gwOptions & OPT_BAR)
  1677. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1678. else
  1679. gwPlaybarHeight = 0;
  1680. //
  1681. // munge rectangle to account for a title in the picture
  1682. // and the fact that picture is centred above title.
  1683. // Remember, it's been stretched around.
  1684. //
  1685. if (gwOptions & OPT_TITLE)
  1686. {
  1687. SIZE Size;
  1688. hdc = GetDC(NULL);
  1689. if (ghfontMap)
  1690. SelectObject(hdc, ghfontMap);
  1691. GetTextExtentPoint32(hdc, gachCaption,
  1692. STRLEN(gachCaption), &Size);
  1693. xTextExt = Size.cx;
  1694. ReleaseDC(NULL, hdc);
  1695. if (gwPastedHeight && !(gwDeviceType & DTMCI_CANWINDOW) )
  1696. yOrig = gwPastedHeight;
  1697. else
  1698. yOrig = rc.bottom - rc.top;
  1699. xOrig = rc.right - rc.left;
  1700. xtitleOrig = max(xTextExt + 4, xOrig);
  1701. yNow = rcClient.bottom - rcClient.top;
  1702. xNow = rcClient.right - rcClient.left;
  1703. if (gwDeviceType & DTMCI_CANWINDOW)
  1704. ytitleNow = TITLE_HEIGHT;
  1705. else
  1706. {
  1707. ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
  1708. / (yOrig + TITLE_HEIGHT));
  1709. gwOldHeight = yNow;
  1710. }
  1711. /* for windowed devices, center the playback area above the */
  1712. /* control bar if the control bar is longer. */
  1713. if (gwDeviceType & DTMCI_CANWINDOW)
  1714. {
  1715. wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
  1716. xIndent = (xNow - wWinNow) / 2;
  1717. rcClient.left += xIndent;
  1718. rcClient.right = rcClient.left + wWinNow;
  1719. }
  1720. // Align top of control bar with the top of the title bar.
  1721. // The control bar (if there) will appear under rcSave.
  1722. rcClient.bottom = rcClient.top + yNow - ytitleNow;
  1723. rcSave.bottom = rcSave.top + yNow - ytitleNow;
  1724. /* When we make the playbar, make it cover the title */
  1725. /* if the caption was stretched taller than ordinary.*/
  1726. if (gwOptions & OPT_BAR)
  1727. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1728. }
  1729. /* Enforce a minimum width for the control bar */
  1730. #if 0
  1731. /* No, don't, because this screws up PowerPoint, which is usually
  1732. * scaled. If anything, it would be better to hide the control bar
  1733. * under these circumstances.
  1734. */
  1735. if ((gwOptions & OPT_BAR) &&
  1736. (rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON)))
  1737. {
  1738. rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
  1739. if (gwDeviceType & DTMCI_CANWINDOW)
  1740. xIndent = TRUE; // force SetWindowMCI to be called to
  1741. // avoid stretching to this new size.
  1742. }
  1743. #endif
  1744. if (!(gwOptions & OPT_USEPALETTE)&& !(gwOptions & OPT_DITHER))
  1745. {
  1746. //
  1747. // try to get a OWNDC Palette of the client, PowerPoint
  1748. // uses a PC_RESERVED palette in "SlideShow" mode. so
  1749. // we must use it's exact palette.
  1750. //
  1751. hdc = GetDC(ghwndCntr);
  1752. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE),
  1753. FALSE);
  1754. SelectPalette(hdc, hpal, FALSE);
  1755. ReleaseDC(ghwndCntr, hdc);
  1756. if (hpal == NULL || hpal==GetStockObject(DEFAULT_PALETTE))
  1757. {
  1758. /* Assume client realized the proper palette for us */
  1759. if (ghpalApp)
  1760. DeleteObject(ghpalApp);
  1761. hpal = ghpalApp = CreateSystemPalette();
  1762. }
  1763. else
  1764. DPF("Using clients OWNDC palette\n");
  1765. if (hpal)
  1766. SetPaletteMCI(hpal);
  1767. }
  1768. else
  1769. DPF("Using MCI Object's normal palette\n");
  1770. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1771. if (gwOptions & OPT_BORDER)
  1772. SetWS(ghwndApp, WS_BORDER);
  1773. /* Set the size of Mplayer to have enough space for the MCI */
  1774. /* playback area and a playbar and the non-client area. */
  1775. rcSave.bottom += gwPlaybarHeight;
  1776. if(!(gwDeviceType & DTMCI_CANWINDOW) && (gwOptions & OPT_BAR))
  1777. rcSave.top = rcSave.bottom - gwPlaybarHeight;
  1778. AdjustWindowRect(&rcSave, (DWORD)GetWS(ghwndApp), FALSE);
  1779. if(!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR))
  1780. rcSave.bottom = rcSave.top = rcSave.left = rcSave.right = 0;
  1781. EditInPlace(ghwndApp, hwndClient, &rcSave);
  1782. /* become visible */
  1783. SHOWAPPWINDOW(SW_SHOW);
  1784. /* Remember to play the video in the rcClient area of rcSave */
  1785. if ((gwDeviceType & DTMCI_CANWINDOW) &&
  1786. (gwOptions & OPT_TITLE) && xIndent != 0)
  1787. SetDestRectMCI(&rcClient);
  1788. }
  1789. }
  1790. else
  1791. if (verb == verbOpen || verb == OLEIVERB_OPEN)
  1792. {
  1793. DPFI("\n*verbopen");
  1794. DoInPlaceDeactivate(lpobj);
  1795. if (gwDeviceID)
  1796. return ReallyDoVerb(lpobj, verbEdit, lpmsg, lpActiveSite, fShow, fActivate);
  1797. }
  1798. else
  1799. if (verb == OLEIVERB_HIDE)
  1800. {
  1801. DPFI("\n*^*^* OLEVERB_HIDE *^*^");
  1802. DoInPlaceDeactivate(lpobj);
  1803. return S_OK;
  1804. }
  1805. else
  1806. if (verb > 0)
  1807. {
  1808. Result = ReallyDoVerb(lpobj, OLEIVERB_PRIMARY, lpmsg, lpActiveSite, fShow, fActivate);
  1809. }
  1810. else
  1811. return E_NOTIMPL;
  1812. if (fShow )
  1813. {
  1814. if (ghwndMCI || !gfOle2IPEditing)
  1815. SHOWAPPWINDOW(SW_SHOW);
  1816. /* MUST BE A POST or palette realization will not happen properly */
  1817. if (IsIconic(ghwndApp))
  1818. SendMessage(ghwndApp, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1819. }
  1820. if (fActivate )
  1821. {
  1822. BringWindowToTop (ghwndApp); // let WM_ACTIVATE put client
  1823. SetActiveWindow (ghwndApp); // underneath us
  1824. }
  1825. return Result;
  1826. }