Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2373 lines
75 KiB

  1. /*-----------------------------------------------------------------------------+
  2. | OLE1.C |
  3. | |
  4. | (C) Copyright Microsoft Corporation 1991. All rights reserved. |
  5. | |
  6. | Revision History |
  7. | 02-Jun-94 AndrewBe created, based upon the OLE1 SERVER.C |
  8. | |
  9. +-----------------------------------------------------------------------------*/
  10. #ifdef OLE1_HACK
  11. /* This was originally server.c in the OLE1 Media Player.
  12. * It is here somewhat munged to bolt onto the side of the OLE2 Media Player,
  13. * to get around the fact that OLE1/OLE2 interoperability is broken in Daytona.
  14. *
  15. * The OLE2 interface is Unicode, whereas the OLE1 interface is ANSI.
  16. * This accounts for some, though probably not all, of the horrors that are
  17. * about to unfold before your eyes.
  18. */
  19. #ifndef UNICODE
  20. #error This file assumes that UNICODE is defined.
  21. #endif
  22. #undef UNICODE
  23. #define SERVERONLY
  24. #include <windows.h>
  25. #include <commdlg.h>
  26. #include <mmsystem.h>
  27. #include <port1632.h>
  28. #include <shellapi.h>
  29. #include <string.h>
  30. #include <ole.h>
  31. #include "mplayer.h"
  32. #include "ole1.h"
  33. //////////////////////////////////////////////////////////////////////////
  34. //
  35. // (c) Copyright Microsoft Corp. 1991 - All Rights Reserved
  36. //
  37. /////////////////////////////////////////////////////////////////////////
  38. #include <stdlib.h>
  39. #undef _MAX_PATH // ??? someone hacking?
  40. #undef _MAX_DIR // ??? someone hacking?
  41. #undef _MAX_FNAME // ??? someone hacking?
  42. #undef _MAX_EXT // ??? someone hacking?
  43. #include "toolbar.h"
  44. DWORD gDocVersion = DOC_VERSION_NONE;
  45. extern PSTR gpchFilter;
  46. #define WAITDIFFERENTLY // dont ask....
  47. extern UINT gwPlaybarHeight; // tell playbar how tall to make itself
  48. // so it covers the title
  49. STATICDT BOOL gfMouseUpSeen = FALSE; // OK to close play in place?
  50. STATICDT BOOL gfKeyStateUpSeen = FALSE; // OK to close play in place?
  51. /* Height of picture given to client to be pasted */
  52. STATICDT UINT gwPastedHeight;
  53. /* DELAYED BROKEN LINK */
  54. extern WCHAR gachFile[MAX_PATH];
  55. STATICDT CHAR gachDeviceA[80];
  56. STATICDT WCHAR gachDeviceW[80];
  57. extern BOOL gfBrokenLink;
  58. STATICDT int gerr;
  59. STATICDT HWND ghwndClient = NULL;
  60. STATICDT RECT grcClient;
  61. /* ........................ */
  62. extern HANDLE ghInst;
  63. extern POINT gptBtnSize;
  64. #define abs(x) ((x) < 0 ? -(x) : (x))
  65. /**************************************************************************
  66. ***************************************************************************/
  67. #ifndef GetWS
  68. #define GetWS(hwnd) GetWindowLongPtr(hwnd, GWL_STYLE)
  69. #define PutWS(hwnd, f) SetWindowLongPtr(hwnd, GWL_STYLE, f)
  70. #define TestWS(hwnd,f) (GetWS(hwnd) & f)
  71. #define SetWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) | f)
  72. #define ClrWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) & ~(f))
  73. #endif
  74. /************************************************************************
  75. Important Note:
  76. No method should ever dispatch a DDE message or allow a DDE message to
  77. be dispatched.
  78. Therefore, no method should ever enter a message dispatch loop.
  79. Also, a method should not show a dialog or message box, because the
  80. processing of the dialog box messages will allow DDE messages to be
  81. dispatched.
  82. the hacky way we enforce this is with the global <gfErrorBox>. see
  83. errorbox.c and all the "gfErrorBox++"'s in this file.
  84. Note that we are an exe, not a DLL, so this does not rely on
  85. non-preemptive scheduling. Should be OK on NT too.
  86. ***************************************************************************/
  87. /**************************************************************************
  88. GLOBALS
  89. ***************************************************************************/
  90. STATICDT BOOL gfUnblockServer; //
  91. STATICDT int nBlockCount;
  92. #ifndef _WIN32
  93. HHOOK hHookMouse; // Mouse hook handle.
  94. HOOKPROC fpMouseHook; // Mouse hook proc address.
  95. #else
  96. /*
  97. ** These functions are exported from mciole32.dll.
  98. **
  99. */
  100. typedef BOOL (*LPINSTALLHOOK)( HWND, DWORD );
  101. typedef BOOL (*LPREMOVEHOOK)( VOID );
  102. LPINSTALLHOOK fpInstallHook;
  103. LPREMOVEHOOK fpRemoveHook;
  104. BOOL fHookInstalled = FALSE;
  105. #endif
  106. HWND ghwndFocusSave; // saved focus window
  107. HMODULE hMciOle;
  108. OLECLIPFORMAT cfLink;
  109. OLECLIPFORMAT cfOwnerLink;
  110. OLECLIPFORMAT cfNative;
  111. OLESERVERDOCVTBL docVTbl;
  112. OLEOBJECTVTBL itemVTbl;
  113. OLESERVERVTBL srvrVTbl;
  114. SRVR gSrvr;
  115. OLE1DOC gDoc;
  116. ITEM gItem;
  117. /**************************************************************************
  118. STRINGS
  119. ***************************************************************************/
  120. #ifdef _WIN32
  121. STATICDT ANSI_SZCODE aszInstallHook[] = "InstallHook";
  122. STATICDT ANSI_SZCODE aszRemoveHook[] = "RemoveHook";
  123. #endif
  124. extern ANSI_SZCODE aszAppName[] = "MPlayer";
  125. /* Formatting characters for string macros:
  126. */
  127. STATICDT WCHAR szFormatAnsiToUnicode[] = L"%hs";
  128. STATICDT CHAR szFormatUnicodeToAnsi[] = "%ws";
  129. STATICDT WCHAR szFormatUnicodeToUnicode[] = L"%ws";
  130. /* Unicode - ANSI string-copying macros:
  131. */
  132. #define COPYSTRINGA2W(pTarget, pSource) wsprintfW(pTarget, szFormatAnsiToUnicode, pSource)
  133. #define COPYSTRINGW2A(pTarget, pSource) wsprintfA(pTarget, szFormatUnicodeToAnsi, pSource)
  134. #define COPYSTRINGW2W(pTarget, pSource) wsprintfW(pTarget, szFormatUnicodeToUnicode, pSource)
  135. /**************************************************************************
  136. ***************************************************************************/
  137. void FAR PASCAL Ole1PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc);
  138. void FAR PASCAL Ole1EndPlayInPlace(HWND hwndApp);
  139. OLESTATUS FAR PASCAL ItemSetData1(LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata);
  140. BOOL NEAR PASCAL ScanCmdLine(LPSTR szCmdLine);
  141. STATICFN int NEAR PASCAL Ole1ReallyDoVerb(LPOLEOBJECT lpobj, UINT verb, BOOL fShow, BOOL fActivate);
  142. STATICFN OLESTATUS NEAR PASCAL SetDataPartII(LPWSTR szFile, LPWSTR szDevice);
  143. STATICFN BOOL NetParseFile(LPSTR szFile, LPSTR szPath);
  144. int FAR PASCAL ParseOptions(LPTSTR pOpt);
  145. extern BOOL FindRealFileName(LPTSTR szFile, int iLen);
  146. HWND TopWindow(HWND hwnd);
  147. void PASCAL DinkWithWindowStyles(HWND hwnd, BOOL fRestore);
  148. HANDLE GetLink( VOID );
  149. /*
  150. *
  151. */
  152. VOID SetDocVersion( DWORD DocVersion )
  153. {
  154. #if DBG
  155. if( ( DocVersion != DOC_VERSION_NONE ) && ( gDocVersion != DOC_VERSION_NONE ) )
  156. {
  157. DPF0( "Expected gDocVersion == 0!! It's %u\n", gDocVersion );
  158. }
  159. #endif /* DBG */
  160. gDocVersion = DocVersion;
  161. DPF0( "gDocVersion set to %u\n", DocVersion );
  162. }
  163. /**************************************************************************
  164. * Ole1UpdateObject() - handle the update of the object
  165. *
  166. ***************************************************************************/
  167. void Ole1UpdateObject(void)
  168. {
  169. if (gfEmbeddedObject) {
  170. //
  171. // some client's (ie Excel 3.00 and PowerPoint 1.0) dont
  172. // handle saved notifications, they expect to get a
  173. // OLE_CLOSED message.
  174. //
  175. // we will send a OLE_CLOSED message right before we
  176. // revoke the DOC iff gfDirty == -1, see FileNew()
  177. //
  178. if (SendChangeMsg(OLE_SAVED) == OLE_OK)
  179. CleanObject();
  180. else {
  181. DPF("Unable to update object, setting gfDirty = -1\n");
  182. gfDirty = -1;
  183. }
  184. }
  185. }
  186. /*
  187. *
  188. */
  189. BOOL FAR PASCAL Ole1FixLinkDialog(LPSTR szFile, LPSTR szDevice, int iLen)
  190. {
  191. UINT wDevice;
  192. char achFile[MAX_PATH + 1]; /* file or device name buffer */
  193. char achTitle[80]; /* string holding the title bar name */
  194. HWND hwndFocus;
  195. OPENFILENAME ofn;
  196. BOOL f;
  197. static SZCODE aszDialog[] = "MciOpenDialog"; // in open.c too.
  198. //
  199. // I GIVE UP!!! Put up an open dlg box and let them find it themselves!
  200. //
  201. // If we haven't initialized the device menu yet, do it now.
  202. if (gwNumDevices == 0)
  203. InitDeviceMenu();
  204. // find out the device number for the specifed device
  205. wDevice = gwCurDevice;
  206. LoadString(ghInst, IDS_FINDFILE, achFile, CHAR_COUNT(achFile));
  207. wsprintf(achTitle, achFile, FileName(szFile)); // title bar for locate dlg
  208. /* Start with the bogus file name */
  209. lstrcpy(achFile, FileName(szFile));
  210. /* Set up the ofn struct */
  211. ofn.lStructSize = sizeof(OPENFILENAME);
  212. /* MUST use ActiveWindow to make user deal with us NOW in case of multiple*/
  213. /* broken links */
  214. ofn.hwndOwner = GetActiveWindow();
  215. ofn.hInstance = ghInst;
  216. ofn.lpstrFilter = gpchFilter;
  217. ofn.lpstrCustomFilter = NULL;
  218. ofn.nMaxCustFilter = 0;
  219. if (wDevice == 0)
  220. ofn.nFilterIndex = gwNumDevices+1; // select "All Files"
  221. else
  222. ofn.nFilterIndex = wDevice;
  223. ofn.lpstrFile = achFile;
  224. ofn.nMaxFile = sizeof(achFile);
  225. ofn.lpstrFileTitle = NULL;
  226. ofn.nMaxFileTitle = 0;
  227. ofn.lpstrInitialDir = NULL;
  228. ofn.lpstrTitle = achTitle;
  229. // ofn.Flags = OFN_ENABLETEMPLATE | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
  230. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
  231. OFN_SHAREAWARE | OFN_PATHMUSTEXIST;
  232. ofn.nFileOffset = 0;
  233. ofn.nFileExtension = 0;
  234. ofn.lpstrDefExt = NULL;
  235. ofn.lCustData = 0;
  236. ofn.lpfnHook = NULL;
  237. // ofn.lpTemplateName = aszDialog;
  238. ofn.lpTemplateName = NULL;
  239. // Show the cursor in case PowerPig is hiding it
  240. ShowCursor(TRUE);
  241. hwndFocus = GetFocus();
  242. /* Let the user pick a filename */
  243. BlockServer();
  244. gfErrorBox++;
  245. f = GetOpenFileName(&ofn);
  246. if (f) {
  247. lstrcpyn(szFile, achFile, iLen);
  248. gfDirty = TRUE; // make sure the object is dirty now
  249. }
  250. gfErrorBox--;
  251. UnblockServer();
  252. SetFocus(hwndFocus);
  253. // Put cursor back how it used to be
  254. ShowCursor(FALSE);
  255. return f;
  256. }
  257. /**************************************************************************/
  258. /* We've just gotten our delayed message that we need to bring up an open */
  259. /* dialog to let the user fix the broken link, and then we can finish the */
  260. /* SetData and the DoVerb. */
  261. /**************************************************************************/
  262. void FAR PASCAL DelayedFixLink(UINT verb, BOOL fShow, BOOL fActivate)
  263. {
  264. CHAR achFileA[MAX_PATH];
  265. gfBrokenLink = FALSE;
  266. COPYSTRINGW2A(gachDeviceA, garMciDevices[gwCurDevice].szDevice);
  267. COPYSTRINGW2W(gachDeviceW, garMciDevices[gwCurDevice].szDevice);
  268. COPYSTRINGW2A(achFileA, gachFile);
  269. /* Something goes wrong? Get out of here and give up. */
  270. if (!Ole1FixLinkDialog(achFileA, gachDeviceA, CHAR_COUNT(achFileA)) ||
  271. SetDataPartII(gachFile, gachDeviceW) != OLE_OK)
  272. PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
  273. else
  274. Ole1ReallyDoVerb(NULL, verb, fShow, fActivate);
  275. }
  276. /**************************************************************************
  277. ***************************************************************************/
  278. BOOL FAR PASCAL InitOle1Server(HWND hwnd, HANDLE hInst)
  279. {
  280. long cb;
  281. int err;
  282. char aszPlay[40];
  283. char aszEdit[40];
  284. #ifdef _WIN32
  285. /*
  286. ** On NT we have to install a global mouse HookProc which has to
  287. ** in a DLL. Also we have to tell the DLL which process/thread we are
  288. ** interested in, therefore let the DLL install the HookProc. When the
  289. ** HookProc detects an "interesting" mouse message it stops the
  290. ** device from playing. However, the device "stopping" function is
  291. ** inside mplayer, so we have to export it so that the HookProc can
  292. ** call it.
  293. */
  294. if ( hMciOle ) {
  295. fpInstallHook = (LPINSTALLHOOK)GetProcAddress(hMciOle, aszInstallHook);
  296. fpRemoveHook = (LPREMOVEHOOK)GetProcAddress(hMciOle, aszRemoveHook);
  297. }
  298. else {
  299. fpInstallHook = NULL;
  300. fpRemoveHook = NULL;
  301. }
  302. #endif
  303. cfLink = RegisterClipboardFormat("Link");
  304. cfOwnerLink = RegisterClipboardFormat("OwnerLink");
  305. // The scheme of casting everything to FARPROC relies on then being able
  306. // to do a cast on lvalue later to make it all work. Last time I checked
  307. // that wouldn't wash on MIPS. So we have be a little cleaner.
  308. #define MPI(fn) MakeProcInstance((FARPROC)fn, hInst);
  309. //
  310. // srvr vtable.
  311. //
  312. *(FARPROC*)&srvrVTbl.Open = MPI(SrvrOpen);
  313. *(FARPROC*)&srvrVTbl.Create = MPI(SrvrCreate);
  314. *(FARPROC*)&srvrVTbl.CreateFromTemplate = MPI(SrvrCreateFromTemplate);
  315. *(FARPROC*)&srvrVTbl.Edit = MPI(SrvrEdit);
  316. *(FARPROC*)&srvrVTbl.Exit = MPI(SrvrExit);
  317. *(FARPROC*)&srvrVTbl.Release = MPI(SrvrRelease1);
  318. *(FARPROC*)&srvrVTbl.Execute = MPI(SrvrExecute);
  319. //
  320. // doc table
  321. //
  322. *(FARPROC*)&docVTbl.Save = MPI(DocSave);
  323. *(FARPROC*)&docVTbl.Close = MPI(DocClose);
  324. *(FARPROC*)&docVTbl.GetObject = MPI(DocGetObject);
  325. *(FARPROC*)&docVTbl.Release = MPI(DocRelease);
  326. *(FARPROC*)&docVTbl.SetHostNames = MPI(DocSetHostNames);
  327. *(FARPROC*)&docVTbl.SetDocDimensions = MPI(DocSetDocDimensions);
  328. *(FARPROC*)&docVTbl.SetColorScheme = MPI(DocSetColorScheme);
  329. *(FARPROC*)&docVTbl.Execute = MPI(DocExecute);
  330. //
  331. // item table.
  332. //
  333. *(FARPROC*)&itemVTbl.Show = MPI(ItemOpen);
  334. *(FARPROC*)&itemVTbl.DoVerb = MPI(ItemDoVerb);
  335. *(FARPROC*)&itemVTbl.GetData = MPI(ItemGetData);
  336. *(FARPROC*)&itemVTbl.SetData = MPI(ItemSetData1);
  337. *(FARPROC*)&itemVTbl.Release = MPI(ItemRelease);
  338. *(FARPROC*)&itemVTbl.SetTargetDevice = MPI(ItemSetTargetDevice);
  339. *(FARPROC*)&itemVTbl.EnumFormats = MPI(ItemEnumFormats);
  340. *(FARPROC*)&itemVTbl.SetBounds = MPI(ItemSetBounds);
  341. *(FARPROC*)&itemVTbl.SetColorScheme = MPI(ItemSetColorScheme);
  342. gSrvr.lhsrvr = 0L;
  343. gDoc.lhdoc = 0L;
  344. gItem.lpoleclient = NULL;
  345. gSrvr.olesrvr.lpvtbl = &srvrVTbl;
  346. err = OleRegisterServer(aszAppName, (LPOLESERVER)&gSrvr,
  347. &gSrvr.lhsrvr, hInst, OLE_SERVER_MULTI);
  348. if (err != OLE_OK) {
  349. gSrvr.lhsrvr = 0L;
  350. Error(ghwndApp, IDS_CANTSTARTOLE);
  351. return TRUE;
  352. }
  353. gSrvr.hwnd = hwnd; // corresponding main window
  354. return TRUE;
  355. }
  356. /**************************************************************************
  357. ***************************************************************************/
  358. void FAR PASCAL TermServer(void)
  359. {
  360. if (hMciOle)
  361. FreeLibrary(hMciOle);
  362. }
  363. /**************************************************************************
  364. ***************************************************************************/
  365. void FAR PASCAL NewDoc(BOOL fUntitled)
  366. {
  367. //
  368. // some client's (ie Excel 3.00 and PowerPoint 1.0) dont
  369. // handle saved notifications, they expect to get a
  370. // OLE_CLOSED message.
  371. //
  372. // if the user has chosen to update the object, but the client did
  373. // not then send a OLE_CLOSED message.
  374. //
  375. if (gfEmbeddedObject && IsObjectDirty()) {
  376. UpdateObject();
  377. if (gfDirty == -1)
  378. SendChangeMsg(OLE_CLOSED);
  379. CleanObject();
  380. }
  381. BlockServer();
  382. /* !!! If PlayMCI errors, and we close the client, we get called, but */
  383. /* we can't CloseMCI now or we'll explode. */
  384. if (!gfErrorBox && IsWindowEnabled(ghwndApp))
  385. CloseMCI(TRUE);
  386. // app.c has a better way of not dispatching evil timer messages
  387. #if 0
  388. // A leftover WM_TIMER is UAE'ing Packager going down
  389. if (PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD)) {
  390. DPF("Ack! *** We removed a WM_TIMER msg from someone's queue!\n");
  391. }
  392. #endif
  393. UnblockServer();
  394. RevokeDocument();
  395. //
  396. // register a "untitled" doc?????
  397. //
  398. if (fUntitled) {
  399. LoadStringW(ghInst, IDS_UNTITLED, (LPWSTR)gachFileDevice, 40);
  400. RegisterDocument(0,0);
  401. }
  402. }
  403. /**************************************************************************
  404. ***************************************************************************/
  405. void FAR PASCAL ServerUnblock()
  406. {
  407. if (gfUnblockServer)
  408. {
  409. BOOL fMoreMsgs = TRUE;
  410. while (fMoreMsgs && gSrvr.lhsrvr)
  411. OleUnblockServer (gSrvr.lhsrvr, &fMoreMsgs);
  412. // We have taken care of all the messages in the OLE queue
  413. gfUnblockServer = FALSE;
  414. }
  415. }
  416. /**************************************************************************
  417. ***************************************************************************/
  418. void FAR PASCAL BlockServer()
  419. {
  420. // gfErrorBox++;
  421. if (nBlockCount++ == 0)
  422. OleBlockServer(gSrvr.lhsrvr);
  423. }
  424. /**************************************************************************
  425. ***************************************************************************/
  426. void FAR PASCAL UnblockServer()
  427. {
  428. /* Don't wrap around! */
  429. if (!nBlockCount)
  430. return;
  431. if (--nBlockCount == 0)
  432. gfUnblockServer = TRUE;
  433. // gfErrorBox--;
  434. }
  435. /**************************************************************************
  436. ***************************************************************************/
  437. void FAR PASCAL TerminateServer(void)
  438. {
  439. LHSERVER lhsrvr;
  440. if (gfPlayingInPlace)
  441. Ole1EndPlayInPlace(ghwndApp);
  442. // Is this right?
  443. DPF("IDM_EXIT: Revoking server...\n");
  444. lhsrvr = gSrvr.lhsrvr;
  445. if (lhsrvr) {
  446. ServerUnblock();
  447. gSrvr.lhsrvr = (LHSERVER)0;
  448. ////////ShowWindow(ghwndApp,SW_HIDE); // Insert 2nd obj over 1st in Write bug
  449. // RevokeServer won't Destroy us
  450. OleRevokeServer(lhsrvr);
  451. } else {
  452. /* Probably, there never was a server... */
  453. DPF("Closing application window\n");
  454. // This delete server should release the server immediately
  455. // EndDialog(ghwndApp, TRUE);
  456. // DestroyWindow(ghwndApp);
  457. PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0);
  458. }
  459. }
  460. /**************************************************************************
  461. ***************************************************************************/
  462. OLESTATUS FAR PASCAL SrvrRelease1 (LPOLESERVER lpolesrvr)
  463. {
  464. LHSERVER lhsrvr;
  465. /* If we're visible, but we don't want to be released, then ignore. */
  466. if (gSrvr.lhsrvr && (IsWindowVisible(ghwndApp) || !gfRunWithEmbeddingFlag)) {
  467. DPF("SrvrRelease: Ignoring releases...\n");
  468. return OLE_OK;
  469. }
  470. lhsrvr = gSrvr.lhsrvr;
  471. if (lhsrvr) {
  472. DPF("SrvrRelease: Calling RevokeServer\n");
  473. ServerUnblock();
  474. gSrvr.lhsrvr = 0;
  475. OleRevokeServer(lhsrvr);
  476. } else {
  477. DPF("SrvrRelease: Closing application window\n");
  478. // This delete server should release the server immediately
  479. // EndDialog(ghwndApp, TRUE);
  480. // DestroyWindow(ghwndApp);
  481. PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0);
  482. }
  483. return OLE_OK; // return something
  484. }
  485. /**************************************************************************
  486. ***************************************************************************/
  487. OLESTATUS FAR PASCAL SrvrExecute (LPOLESERVER lpoledoc, HGLOBAL hCommands)
  488. {
  489. return OLE_ERROR_GENERIC;
  490. }
  491. /**************************************************************************
  492. ***************************************************************************/
  493. BOOL FAR PASCAL RegisterDocument(LHSERVERDOC lhdoc, LPOLESERVERDOC FAR *lplpoledoc)
  494. {
  495. /* If we don't have a server, don't even bother. */
  496. if (!gSrvr.lhsrvr)
  497. return TRUE;
  498. gDoc.hwnd = ghwndApp; // corresponding main window
  499. /* should only be one document at a time... */
  500. while (gDoc.lhdoc != (LHSERVERDOC)0 && gDoc.lhdoc != -1)
  501. RevokeDocument();
  502. #ifdef WAITDIFFERENTLY
  503. while (gDoc.lhdoc == -1) {
  504. MSG rMsg; /* variable used for holding a message */
  505. DPF("RegisterDoc: Waiting for document to be released....\n");
  506. /* call the server code and let it unblock the server */
  507. ServerUnblock();
  508. if (!GetMessage(&rMsg, NULL, 0, 0)) {
  509. DPF("VERY BAD: got WM_QUIT while waiting...\n");
  510. }
  511. TranslateMessage(&rMsg);
  512. DispatchMessage(&rMsg);
  513. }
  514. #endif
  515. if (lhdoc == (LHSERVERDOC)0) {
  516. CHAR szAnsi[MAX_PATH];
  517. DPF("Registering document: %ws\n", (LPWSTR)gachFileDevice);
  518. COPYSTRINGW2A(szAnsi, gachFileDevice);
  519. if (OleRegisterServerDoc(gSrvr.lhsrvr, szAnsi, (LPOLESERVERDOC)&gDoc,
  520. (LHSERVERDOC FAR *)&gDoc.lhdoc) != OLE_OK)
  521. return FALSE;
  522. } else {
  523. gDoc.lhdoc = lhdoc;
  524. }
  525. DPF0( "RegisterDocument: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
  526. ////UpdateCaption(); //!!!
  527. ////DPF("Adding document handle: %lx\n",lhdoc);
  528. ////gDoc.aName = GlobalAddAtom(MakeAnsi((LPWSTR)gachFileDevice));
  529. gDoc.oledoc.lpvtbl = &docVTbl;
  530. if (lplpoledoc)
  531. *lplpoledoc = (LPOLESERVERDOC)&gDoc;
  532. SetDocVersion( DOC_VERSION_OLE1 );
  533. return TRUE;
  534. }
  535. /**************************************************************************
  536. ***************************************************************************/
  537. void FAR PASCAL RevokeDocument(void)
  538. {
  539. LHSERVERDOC lhdoc;
  540. if (gDoc.lhdoc == -1) {
  541. DPF("RevokeDocument: Document has been revoked, waiting for release!\n");
  542. return;
  543. }
  544. if (gDoc.lhdoc) {
  545. DPF0( "RevokeDocument: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
  546. DPF("Revoking document: lhdoc=%lx\n",gDoc.lhdoc);
  547. lhdoc = gDoc.lhdoc;
  548. if (lhdoc) {
  549. gDoc.lhdoc = -1;
  550. if (OleRevokeServerDoc(lhdoc) == OLE_WAIT_FOR_RELEASE) {
  551. #ifndef WAITDIFFERENTLY
  552. while (gDoc.lhdoc != 0) {
  553. MSG msg;
  554. DPF("RevokeDocument: waiting for release...\n");
  555. /* call the server code and let it unblock the server */
  556. ServerUnblock();
  557. if (!GetMessage(&msg, NULL, 0, 0)) {
  558. DPF("VERY BAD: got WM_QUIT while waiting...\n");
  559. }
  560. TranslateMessage(&msg);
  561. DispatchMessage(&msg);
  562. }
  563. DPF("RevokeDocument: done waiting for release\n");
  564. #endif
  565. } else {
  566. //!! WinAssert(gDoc.lhdoc == 0);
  567. }
  568. SetDocVersion( DOC_VERSION_NONE );
  569. } else {
  570. DPF0("Document already revoked!");
  571. }
  572. SetEmbeddedObjectFlag(FALSE);
  573. }
  574. }
  575. /**************************************************************************
  576. ***************************************************************************/
  577. OLESTATUS FAR PASCAL SrvrOpen (
  578. LPOLESERVER lpolesrvr,
  579. LHSERVERDOC lhdoc,
  580. OLE_LPCSTR lpdocname,
  581. LPOLESERVERDOC FAR *lplpoledoc)
  582. {
  583. BOOL f;
  584. DPF("SrvrOpen: %s\n",lpdocname);
  585. SetEmbeddedObjectFlag(TRUE);
  586. BlockServer();
  587. f = OpenMciDevice((LPSTR)lpdocname, (LPSTR)NULL);
  588. UnblockServer();
  589. if (!f)
  590. return OLE_ERROR_GENERIC;
  591. SetEmbeddedObjectFlag(FALSE);
  592. RegisterDocument(lhdoc, lplpoledoc);
  593. return OLE_OK;
  594. }
  595. /**************************************************************************
  596. ***************************************************************************/
  597. OLESTATUS FAR PASCAL SrvrCreate (
  598. LPOLESERVER lpolesrvr,
  599. LHSERVERDOC lhdoc,
  600. OLE_LPCSTR lpclassname,
  601. OLE_LPCSTR lpdocname,
  602. LPOLESERVERDOC FAR *lplpoledoc)
  603. {
  604. DPF("SrvrCreate: %s!%s\n",lpdocname,lpclassname);
  605. BlockServer();
  606. CloseMCI(TRUE);
  607. UnblockServer();
  608. /* Set the title of the client document we're imbedded in */
  609. COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocname);
  610. RegisterDocument(lhdoc,lplpoledoc);
  611. /* You are dirty by default according to OLE */
  612. gfDirty = TRUE;
  613. return OLE_OK;
  614. }
  615. /**************************************************************************
  616. ***************************************************************************/
  617. OLESTATUS FAR PASCAL SrvrCreateFromTemplate (
  618. LPOLESERVER lpolesrvr,
  619. LHSERVERDOC lhdoc,
  620. OLE_LPCSTR lpclassname,
  621. OLE_LPCSTR lpdocname,
  622. OLE_LPCSTR lptemplatename,
  623. LPOLESERVERDOC FAR *lplpoledoc)
  624. {
  625. BOOL f;
  626. DPF("SrvrCreateFromTemplate: %s as %s class=%s\n",lptemplatename,lpdocname,lpclassname);
  627. SetEmbeddedObjectFlag(TRUE);
  628. BlockServer();
  629. f = OpenMciDevice((LPSTR)lptemplatename, (LPSTR)NULL);
  630. UnblockServer();
  631. if (!f)
  632. return OLE_ERROR_GENERIC;
  633. RegisterDocument(lhdoc,lplpoledoc);
  634. gfDirty = TRUE;
  635. return OLE_OK;
  636. }
  637. /**************************************************************************
  638. ***************************************************************************/
  639. OLESTATUS FAR PASCAL SrvrEdit (
  640. LPOLESERVER lpolesrvr,
  641. LHSERVERDOC lhdoc,
  642. OLE_LPCSTR lpclassname,
  643. OLE_LPCSTR lpdocname,
  644. LPOLESERVERDOC FAR *lplpoledoc)
  645. {
  646. DPF("SrvrEdit: %s class=%s\n",lpdocname,lpclassname);
  647. BlockServer();
  648. CloseMCI(TRUE);
  649. UnblockServer();
  650. /* Set the title of the client document we're imbedded in */
  651. COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocname);
  652. RegisterDocument(lhdoc,lplpoledoc);
  653. return OLE_OK;
  654. }
  655. /**************************************************************************
  656. ***************************************************************************/
  657. OLESTATUS FAR PASCAL SrvrExit (
  658. LPOLESERVER lpolesrvr)
  659. {
  660. LHSERVER lhsrvr;
  661. // Server lib is calling us to exit.
  662. // Let us hide the main window.
  663. // But let us not delete the window.
  664. DPF("SrvrExit\n");
  665. ShowWindow (ghwndApp, SW_HIDE);
  666. lhsrvr = gSrvr.lhsrvr;
  667. if (lhsrvr) {
  668. gSrvr.lhsrvr = 0;
  669. OleRevokeServer(lhsrvr);
  670. }
  671. return OLE_OK;
  672. // How does the application ever end?
  673. // Application will end when Release is received
  674. }
  675. /**************************************************************************
  676. ***************************************************************************/
  677. OLESTATUS FAR PASCAL DocSave (
  678. LPOLESERVERDOC lpoledoc)
  679. {
  680. DPF("DocSave\n");
  681. ////BlockServer();
  682. ////FileSave(FALSE); // Save should send change message
  683. ////UnblockServer();
  684. return OLE_OK;
  685. }
  686. /**************************************************************************
  687. ***************************************************************************/
  688. OLESTATUS FAR PASCAL DocClose (
  689. LPOLESERVERDOC lpoledoc)
  690. {
  691. DPF("DocClose\n");
  692. BlockServer();
  693. NewDoc(FALSE);
  694. UnblockServer();
  695. DPF("Leaving DocClose\n");
  696. #ifdef WAITDIFFERENTLY
  697. TerminateServer();
  698. #else
  699. PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
  700. #endif
  701. return OLE_OK;
  702. // Should we exit the app here?
  703. }
  704. /**************************************************************************
  705. ***************************************************************************/
  706. OLESTATUS FAR PASCAL DocSetHostNames(
  707. LPOLESERVERDOC lpoledoc,
  708. OLE_LPCSTR lpclientName,
  709. OLE_LPCSTR lpdocName)
  710. {
  711. DPF("DocSetHostNames: %s -- %s\n",lpclientName,lpdocName);
  712. COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocName);
  713. SetEmbeddedObjectFlag(TRUE); // update menu items
  714. gfValidCaption = FALSE;
  715. UpdateDisplay();
  716. return OLE_OK;
  717. }
  718. /**************************************************************************
  719. ***************************************************************************/
  720. OLESTATUS FAR PASCAL DocSetDocDimensions(
  721. LPOLESERVERDOC lpoledoc,
  722. OLE_CONST RECT FAR * lprc)
  723. {
  724. DPF("DocSetDocDimensions [%d,%d,%d,%d]\n", *lprc);
  725. return OLE_OK;
  726. }
  727. /**************************************************************************
  728. ***************************************************************************/
  729. OLESTATUS FAR PASCAL DocRelease (
  730. LPOLESERVERDOC lpoledoc)
  731. {
  732. DPF("DocRelease\n");
  733. // !!! what is this supposed to do?
  734. // Revoke document calls DocRelease.
  735. ////if (gDoc.aName)
  736. ////////GlobalDeleteAtom (gDoc.aName);
  737. /* This marks the document as having been released */
  738. gDoc.lhdoc = 0L;
  739. // Should we kill the application here?
  740. // No, I don't think so.
  741. return OLE_OK; // return something
  742. }
  743. /**************************************************************************
  744. ***************************************************************************/
  745. OLESTATUS FAR PASCAL DocExecute (LPOLESERVERDOC lpoledoc, HANDLE hCommands)
  746. {
  747. return OLE_ERROR_GENERIC;
  748. }
  749. /**************************************************************************
  750. ***************************************************************************/
  751. OLESTATUS FAR PASCAL DocSetColorScheme (LPOLESERVERDOC lpdoc,
  752. OLE_CONST LOGPALETTE FAR* lppalette)
  753. {
  754. return OLE_OK;
  755. }
  756. /**************************************************************************
  757. ***************************************************************************/
  758. OLESTATUS FAR PASCAL DocGetObject (
  759. LPOLESERVERDOC lpoledoc,
  760. OLE_LPCSTR lpitemname,
  761. LPOLEOBJECT FAR * lplpoleobject,
  762. LPOLECLIENT lpoleclient)
  763. {
  764. DPF("DocGetObject: '%s'\n",lpitemname);
  765. gItem.hwnd = ghwndApp;
  766. gItem.oleobject.lpvtbl = &itemVTbl;
  767. // If the item is not null, then do not show the window.
  768. // So do we show the window here, or not?
  769. *lplpoleobject = (LPOLEOBJECT)&gItem;
  770. gItem.lpoleclient = lpoleclient;
  771. /* !!! We have been given OLD options before any updates. We don't need */
  772. /* to parse options here... we'll do it when given our native data in */
  773. /* ItemSetData. */
  774. #if 0
  775. /* Get the options from the item string */
  776. BlockServer();
  777. err = ParseOptions(lpitemname);
  778. UnblockServer();
  779. #endif
  780. return OLE_OK;
  781. }
  782. /**************************************************************************
  783. get the native data that represents the currenly open MCI
  784. file/device. currently this is exactly the same as cfLink data!
  785. ***************************************************************************/
  786. STATICFN HANDLE NEAR PASCAL Ole1GetLink ()
  787. {
  788. HANDLE hUnicode;
  789. DWORD cbUnicode;
  790. LPWSTR pUnicode;
  791. DWORD cbAnsi;
  792. LPSTR pAnsi;
  793. HANDLE hAnsi;
  794. DPF("Ole1GetLink\n");
  795. hUnicode = GetLink();
  796. if( !hUnicode )
  797. return NULL;
  798. cbUnicode = GlobalSize( hUnicode );
  799. if( cbUnicode == 0 )
  800. return NULL;
  801. pUnicode = GlobalLock( hUnicode );
  802. if( !pUnicode )
  803. {
  804. GlobalUnlock( hUnicode );
  805. GlobalFree( hUnicode );
  806. return NULL;
  807. }
  808. cbAnsi = ( cbUnicode * sizeof(CHAR) ) / sizeof(WCHAR);
  809. hAnsi = GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, cbAnsi );
  810. if( !hAnsi )
  811. return NULL;
  812. pAnsi = GlobalLock( hAnsi );
  813. if( !pAnsi )
  814. {
  815. GlobalFree( hAnsi );
  816. return NULL;
  817. }
  818. while( *pUnicode )
  819. {
  820. DWORD Len;
  821. COPYSTRINGW2A( pAnsi, pUnicode );
  822. Len = wcslen( pUnicode );
  823. pAnsi += ( Len + 1 );
  824. pUnicode += ( Len + 1 );
  825. }
  826. GlobalUnlock( hUnicode );
  827. GlobalUnlock( hAnsi );
  828. GlobalFree( hUnicode );
  829. return hAnsi;
  830. }
  831. /**************************************************************************
  832. ***************************************************************************/
  833. STATICFN HBITMAP NEAR PASCAL GetBitmap (PITEM pitem)
  834. {
  835. DPF(" GetBitmap\n");
  836. return BitmapMCI();
  837. }
  838. /**************************************************************************
  839. ***************************************************************************/
  840. STATICFN HANDLE PASCAL NEAR GetPalette(PITEM pitem)
  841. {
  842. extern HPALETTE CopyPalette(HPALETTE); // in MCI.C
  843. DPF(" GetPalette\n");
  844. return CopyPalette(PaletteMCI());
  845. }
  846. /**************************************************************************
  847. ***************************************************************************/
  848. STATICFN HANDLE PASCAL NEAR GetDib(PITEM pitem)
  849. {
  850. HBITMAP hbm;
  851. HPALETTE hpal;
  852. HANDLE hdib;
  853. HDC hdc;
  854. extern HANDLE FAR PASCAL DibFromBitmap(HBITMAP hbm, HPALETTE hpal);
  855. extern void FAR PASCAL DitherMCI(HANDLE hdib, HPALETTE hpal);
  856. DPF(" GetDib\n");
  857. hbm = GetBitmap(pitem);
  858. hpal = PaletteMCI();
  859. hdib = DibFromBitmap(hbm, hpal);
  860. //
  861. // if we are on a palette device. possibly dither to the VGA colors
  862. // for apps that dont deal with palettes!
  863. //
  864. hdc = GetDC(NULL);
  865. if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) &&
  866. (gwOptions & OPT_DITHER)) {
  867. DitherMCI(hdib, hpal);
  868. hpal = NULL; // no longer working with a palette
  869. }
  870. ReleaseDC(NULL, hdc);
  871. DeleteObject(hbm);
  872. return hdib;
  873. }
  874. /**************************************************************************
  875. ***************************************************************************/
  876. STATICFN HANDLE PASCAL NEAR GetPicture (PITEM pitem)
  877. {
  878. HPALETTE hpal;
  879. HANDLE hdib;
  880. HANDLE hmfp;
  881. HDC hdc;
  882. extern HPALETTE CopyPalette(HPALETTE); // in MCI.C
  883. HANDLE FAR PASCAL PictureFromDib(HANDLE hdib, HPALETTE hpal);
  884. DPF(" GetPicture\n");
  885. hdib = GetDib(pitem);
  886. /* If we're dithered, don't use a palette */
  887. hdc = GetDC(NULL);
  888. if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (gwOptions & OPT_DITHER))
  889. hpal = NULL;
  890. else
  891. hpal = PaletteMCI();
  892. if (hpal)
  893. hpal = CopyPalette(hpal);
  894. ReleaseDC(NULL, hdc);
  895. hmfp = PictureFromDib(hdib, hpal);
  896. if (hpal)
  897. DeleteObject(hpal);
  898. GlobalFree(hdib);
  899. return hmfp;
  900. }
  901. /**************************************************************************
  902. ***************************************************************************/
  903. OLESTATUS FAR PASCAL ItemOpen (
  904. LPOLEOBJECT lpoleobject,
  905. BOOL fActivate)
  906. {
  907. /* Start an edit session, and if there is something to play, play it */
  908. /* This is called by Excel to play an object, because it doesn't know */
  909. /* about the PLAY verb. It's also called to Insert a New object into */
  910. /* any client. */
  911. /* All this work is done in our special -1 verb in ReallyDoVerb. */
  912. DPF("ItemOpen\n");
  913. Ole1ReallyDoVerb(lpoleobject, (UINT)(-1), TRUE, fActivate);
  914. return OLE_OK;
  915. }
  916. /**************************************************************************
  917. ***************************************************************************/
  918. /**************************************************************************
  919. * I know this looks odd, but ItemDoVerb is exported so we can't call it*
  920. * internally and sometimes we need to. *
  921. ***************************************************************************/
  922. OLESTATUS FAR PASCAL ItemDoVerb (
  923. LPOLEOBJECT lpobj,
  924. UINT verb,
  925. BOOL fShow,
  926. BOOL fActivate)
  927. {
  928. return Ole1ReallyDoVerb(lpobj, verb, fShow, fActivate);
  929. }
  930. /**************************************************************************
  931. ***************************************************************************/
  932. typedef enum
  933. {
  934. OLE1_OLEOK, /* 0 Function operated correctly */
  935. OLE1_OLEWAIT_FOR_RELEASE, /* 1 Command has been initiated, client */
  936. /* must wait for release. keep dispatching */
  937. /* messages till OLE1_OLERELESE in callback */
  938. OLE1_OLEBUSY, /* 2 Tried to execute a method while another */
  939. /* method is in progress. */
  940. OLE1_OLEERROR_PROTECT_ONLY, /* 3 Ole APIs are called in real mode */
  941. OLE1_OLEERROR_MEMORY, /* 4 Could not alloc or lock memory */
  942. OLE1_OLEERROR_STREAM, /* 5 (OLESTREAM) stream error */
  943. OLE1_OLEERROR_STATIC, /* 6 Non static object expected */
  944. OLE1_OLEERROR_BLANK, /* 7 Critical data missing */
  945. OLE1_OLEERROR_DRAW, /* 8 Error while drawing */
  946. OLE1_OLEERROR_METAFILE, /* 9 Invalid metafile */
  947. OLE1_OLEERROR_ABORT, /* 10 Client chose to abort metafile drawing */
  948. OLE1_OLEERROR_CLIPBOARD, /* 11 Failed to get/set clipboard data */
  949. OLE1_OLEERROR_FORMAT, /* 12 Requested format is not available */
  950. OLE1_OLEERROR_OBJECT, /* 13 Not a valid object */
  951. OLE1_OLEERROR_OPTION, /* 14 Invalid option(link update / render) */
  952. OLE1_OLEERROR_PROTOCOL, /* 15 Invalid protocol */
  953. OLE1_OLEERROR_ADDRESS, /* 16 One of the pointers is invalid */
  954. OLE1_OLEERROR_NOT_EQUAL, /* 17 Objects are not equal */
  955. OLE1_OLEERROR_HANDLE, /* 18 Invalid handle encountered */
  956. OLE1_OLEERROR_GENERIC, /* 19 Some general error */
  957. OLE1_OLEERROR_CLASS, /* 20 Invalid class */
  958. OLE1_OLEERROR_SYNTAX, /* 21 Command syntax is invalid */
  959. OLE1_OLEERROR_DATATYPE, /* 22 Data format is not supported */
  960. OLE1_OLEERROR_PALETTE, /* 23 Invalid color palette */
  961. OLE1_OLEERROR_NOT_LINK, /* 24 Not a linked object */
  962. OLE1_OLEERROR_NOT_EMPTY, /* 25 Client doc contains objects. */
  963. OLE1_OLEERROR_SIZE, /* 26 Incorrect buffer size passed to the api */
  964. /* that places some string in caller's */
  965. /* buffer */
  966. OLE1_OLEERROR_DRIVE, /* 27 Drive letter in doc name is invalid */
  967. OLE1_OLEERROR_NETWORK, /* 28 Failed to establish connection to a */
  968. /* network share on which the document */
  969. /* is located */
  970. OLE1_OLEERROR_NAME, /* 29 Invalid name(doc name, object name), */
  971. /* etc.. passed to the APIs */
  972. OLE1_OLEERROR_TEMPLATE, /* 30 Server failed to load template */
  973. OLE1_OLEERROR_NEW, /* 31 Server failed to create new doc */
  974. OLE1_OLEERROR_EDIT, /* 32 Server failed to create embedded */
  975. /* instance */
  976. OLE1_OLEERROR_OPEN, /* 33 Server failed to open document, */
  977. /* possible invalid link */
  978. OLE1_OLEERROR_NOT_OPEN, /* 34 Object is not open for editing */
  979. OLE1_OLEERROR_LAUNCH, /* 35 Failed to launch server */
  980. OLE1_OLEERROR_COMM, /* 36 Failed to communicate with server */
  981. OLE1_OLEERROR_TERMINATE, /* 37 Error in termination */
  982. OLE1_OLEERROR_COMMAND, /* 38 Error in execute */
  983. OLE1_OLEERROR_SHOW, /* 39 Error in show */
  984. OLE1_OLEERROR_DOVERB, /* 40 Error in sending do verb, or invalid */
  985. /* verb */
  986. OLE1_OLEERROR_ADVISE_NATIVE, /* 41 Item could be missing */
  987. OLE1_OLEERROR_ADVISE_PICT, /* 42 Item could be missing or server doesn't */
  988. /* this format. */
  989. OLE1_OLEERROR_ADVISE_RENAME, /* 43 Server doesn't support rename */
  990. OLE1_OLEERROR_POKE_NATIVE, /* 44 Failure of poking native data to server */
  991. OLE1_OLEERROR_REQUEST_NATIVE, /* 45 Server failed to render native data */
  992. OLE1_OLEERROR_REQUEST_PICT, /* 46 Server failed to render presentation */
  993. /* data */
  994. OLE1_OLEERROR_SERVER_BLOCKED, /* 47 Trying to block a blocked server or */
  995. /* trying to revoke a blocked server */
  996. /* or document */
  997. OLE1_OLEERROR_REGISTRATION, /* 48 Server is not registered in regestation */
  998. /* data base */
  999. OLE1_OLEERROR_ALREADY_REGISTERED,/*49 Trying to register same doc multiple */
  1000. /* times */
  1001. OLE1_OLEERROR_TASK, /* 50 Server or client task is invalid */
  1002. OLE1_OLEERROR_OUTOFDATE, /* 51 Object is out of date */
  1003. OLE1_OLEERROR_CANT_UPDATE_CLIENT,/* 52 Embed doc's client doesn't accept */
  1004. /* updates */
  1005. OLE1_OLEERROR_UPDATE, /* 53 erorr while trying to update */
  1006. OLE1_OLEERROR_SETDATA_FORMAT, /* 54 Server app doesn't understand the */
  1007. /* format given to its SetData method */
  1008. OLE1_OLEERROR_STATIC_FROM_OTHER_OS,/* 55 trying to load a static object created */
  1009. /* on another Operating System */
  1010. /* Following are warnings */
  1011. OLE1_OLEWARN_DELETE_DATA = 1000 /* Caller must delete the data when he is */
  1012. /* done with it. */
  1013. } OLE1_OLESTATUS;
  1014. OLE1_OLESTATUS (FAR PASCAL *OleQueryObjPos)(LPVOID lpobj, HWND FAR* lphwnd, LPRECT lprc, LPRECT lprcWBounds);
  1015. STATICFN int NEAR PASCAL Ole1ReallyDoVerb (
  1016. LPOLEOBJECT lpobj,
  1017. UINT verb,
  1018. BOOL fShow,
  1019. BOOL fActivate)
  1020. {
  1021. BOOL fWindowWasVisible = IsWindowVisible(ghwndApp);
  1022. int dx,dy;
  1023. HWND hwndClient;
  1024. HWND hwndT;
  1025. RECT rcSave;
  1026. RECT rcClient;
  1027. RECT rc;
  1028. UINT err;
  1029. HPALETTE hpal;
  1030. HDC hdc;
  1031. INT xTextExt, yTextExt;
  1032. int yOrig, yNow, xOrig, ytitleNow, xtitleOrig, xNow;
  1033. int xIndent;
  1034. int wWinNow;
  1035. // ACK! We haven't finished doing ItemSetData yet because we have to
  1036. // bring up an open dialog. So we can't do the ItemDoVerb yet. We will
  1037. // Post a message to ourselves that will do both the SetData and DoVerb
  1038. // and we will succeed the DoVerb right now so the client will be happy
  1039. // and start dispatching messages again.
  1040. if (gfBrokenLink) {
  1041. // We need to get client info NOW because our OLE handler can only
  1042. // answer this question now... if we click on two broken links at the
  1043. // same time, it will get confused about which object we want.
  1044. gerr = OleQueryObjPos(lpobj, &ghwndClient, &grcClient, NULL);
  1045. PostMessage(ghwndApp, WM_DO_VERB, verb, MAKELONG(fShow, fActivate));
  1046. return OLE_OK;
  1047. }
  1048. //
  1049. // dont even try to nest things.
  1050. //
  1051. if (gfPlayingInPlace)
  1052. return OLE_OK;
  1053. if (verb == OLEVERB_PRIMARY) {
  1054. DPF("ItemDoVerb: Play\n");
  1055. //
  1056. // if the device can't window and the user does not want a playbar
  1057. // dont play in place - just start the media and run invisible.
  1058. //
  1059. if (!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR)) {
  1060. gwOptions &= ~OPT_PLAY;
  1061. }
  1062. //
  1063. // Select the palette in right now on behalf of the active
  1064. // window, so USER will think it is palette aware.
  1065. //
  1066. // any palette will do we dont even have to realize it!!
  1067. //
  1068. if ((hpal = PaletteMCI()) && (hwndT = GetActiveWindow())) {
  1069. hdc = GetDC(hwndT);
  1070. hpal = SelectPalette(hdc, hpal, FALSE);
  1071. SelectPalette(hdc, hpal, FALSE);
  1072. ReleaseDC(hwndT, hdc);
  1073. }
  1074. if (ghwndClient) {
  1075. hwndClient = ghwndClient;
  1076. err = gerr;
  1077. rcClient = grcClient;
  1078. ghwndClient = NULL;
  1079. } else
  1080. err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
  1081. #ifdef DEBUG
  1082. if (gwOptions & OPT_PLAY)
  1083. {
  1084. DPF("ObjQueryObjPos: hwnd=%04X [%d %d %d %d]\n",hwndClient, rcClient);
  1085. if (err != OLE_OK) {
  1086. DPF("ItemDoVerb: CANT GET OBJECT POSITION!!!\n");
  1087. }
  1088. else {
  1089. if (!(gwDeviceType & DTMCI_CANWINDOW))
  1090. DPF("ItemDoVerb: DEVICE CANT WINDOW\n");
  1091. if (!IsWindow(hwndClient))
  1092. DPF("ItemDoVerb: Invalid Client Window?\n");
  1093. if (!IsWindowVisible(hwndClient))
  1094. DPF("ItemDoVerb: Client window is not visible, playing in a popup\n");
  1095. }
  1096. }
  1097. #endif
  1098. /* We want to play in place and we can. */
  1099. /* If we're a link, not an embedded object, and there was an instance */
  1100. /* of MPlayer up when we said "Play" that was already editing this */
  1101. /* file, we don't want to play in place... we'll just play in that */
  1102. /* instance. We can tell this by the fact that our main MPlayer */
  1103. /* window is already visible. */
  1104. if (err == OLE_OK && (gwOptions & OPT_PLAY) &&
  1105. IsWindow(hwndClient) && IsWindowVisible(hwndClient) &&
  1106. !fWindowWasVisible)
  1107. {
  1108. extern HPALETTE FAR PASCAL CreateSystemPalette(void);
  1109. rc = grcSize; // default playback window size for this movie
  1110. /* If we can't window, or something's wrong, use ICON size */
  1111. if (IsRectEmpty(&rc))
  1112. SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
  1113. GetSystemMetrics(SM_CYICON));
  1114. /* rcSave is the area for the MCI window above the control bar */
  1115. /* (if we have one). */
  1116. /* rcClient is the area of the MCI window (0 based) to play in.*/
  1117. /* Control bar may be longer than picutre, so rcClient may be */
  1118. /* smaller than rcSave. */
  1119. rcSave = rcClient; // remember stretched size
  1120. /* Make rcClient 0 based from rcSave */
  1121. rcClient.left = 0;
  1122. rcClient.right = rcSave.right - rcSave.left;
  1123. rcClient.top = 0;
  1124. rcClient.bottom = rcSave.bottom - rcSave.top;
  1125. /* Assume playbar will be regular height for now */
  1126. if (gwOptions & OPT_BAR)
  1127. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1128. else
  1129. gwPlaybarHeight = 0;
  1130. //
  1131. // munge rectangle to account for a title in the picture
  1132. // and the fact that picture is centred above title.
  1133. // Remember, it's been stretched around.
  1134. //
  1135. if (gwOptions & OPT_TITLE) {
  1136. CHAR szAnsi[MAX_PATH];
  1137. hdc = GetDC(NULL);
  1138. if (ghfontMap)
  1139. SelectObject(hdc, ghfontMap);
  1140. #ifdef _WIN32
  1141. COPYSTRINGW2A(szAnsi, gachCaption);
  1142. MGetTextExtent( hdc, szAnsi, lstrlen(szAnsi),
  1143. &xTextExt, &yTextExt);
  1144. #else
  1145. xTextExt = GetTextExtent(hdc, gachCaption,
  1146. lstrlen(gachCaption));
  1147. #endif
  1148. ReleaseDC(NULL, hdc);
  1149. if (gwPastedHeight)
  1150. yOrig = gwPastedHeight;
  1151. else
  1152. yOrig = rc.bottom - rc.top;
  1153. xOrig = rc.right - rc.left;
  1154. xtitleOrig = max(xTextExt + 4, xOrig);
  1155. yNow = rcClient.bottom - rcClient.top;
  1156. xNow = rcClient.right - rcClient.left;
  1157. ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
  1158. / (yOrig + TITLE_HEIGHT));
  1159. /* for windowed devices, center the playback area above the */
  1160. /* control bar if the control bar is longer. */
  1161. if (gwDeviceType & DTMCI_CANWINDOW) {
  1162. wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
  1163. xIndent = (xNow - wWinNow) / 2;
  1164. rcClient.left += xIndent;
  1165. rcClient.right = rcClient.left + wWinNow;
  1166. }
  1167. // Align top of control bar with the top of the title bar.
  1168. // The control bar (if there) will appear under rcSave.
  1169. rcClient.bottom = rcClient.top + yNow - ytitleNow;
  1170. rcSave.bottom = rcSave.top + yNow - ytitleNow;
  1171. /* When we make the playbar, make it cover the title */
  1172. /* if the caption was stretched taller than ordinary.*/
  1173. if (gwOptions & OPT_BAR)
  1174. gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
  1175. }
  1176. /* Enforce a minimum width for the control bar */
  1177. if ((gwOptions & OPT_BAR) &&
  1178. (rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON))){
  1179. rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
  1180. if (gwDeviceType & DTMCI_CANWINDOW)
  1181. xIndent = TRUE; // force SetWindowMCI to be called to
  1182. // avoid stretching to this new size.
  1183. }
  1184. if (gwDeviceType & DTMCI_CANWINDOW) {
  1185. //
  1186. // If we've only stretched a bit, don't stretch at all.
  1187. // We might be off a bit due to rounding problems.
  1188. //
  1189. dx = (rcClient.right - rcClient.left) - (rc.right - rc.left);
  1190. dy = (rcClient.bottom - rcClient.top) - (rc.bottom - rc.top);
  1191. if (dx && abs(dx) <= 2)
  1192. {
  1193. DPF("Adjusting for x round off\n");
  1194. rcClient.right = rcClient.left + (rc.right - rc.left);
  1195. // Fix Save rect too
  1196. rcSave.right = rcSave.left + (rc.right - rc.left);
  1197. }
  1198. if (dy && abs(dy) <= 2)
  1199. {
  1200. DPF("Adjusting for y round off\n");
  1201. rcClient.bottom = rcClient.top + (rc.bottom - rc.top);
  1202. // Fix Save rect, too.
  1203. rcSave.bottom = rcSave.top + (rc.bottom - rc.top);
  1204. }
  1205. //
  1206. // try to get the right palette from the client, if our
  1207. // pesentation data was dithered or, the user asked us to
  1208. // always use the object palette, then ignore any client
  1209. // palette.
  1210. //
  1211. #ifdef DEBUG
  1212. if (GetProfileInt("options", "UseClientPalette", !(gwOptions & OPT_USEPALETTE)))
  1213. gwOptions &= ~OPT_USEPALETTE;
  1214. else
  1215. gwOptions |= OPT_USEPALETTE;
  1216. #endif
  1217. if (!(gwOptions & OPT_USEPALETTE) &&
  1218. !(gwOptions & OPT_DITHER)) {
  1219. //
  1220. // try to get a OWNDC Palette of the client, PowerPoint
  1221. // uses a PC_RESERVED palette in "SlideShow" mode. so
  1222. // we must use it's exact palette.
  1223. //
  1224. hdc = GetDC(hwndClient);
  1225. hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  1226. SelectPalette(hdc, hpal, FALSE);
  1227. ReleaseDC(hwndClient, hdc);
  1228. if (hpal == NULL || hpal == GetStockObject(DEFAULT_PALETTE)) {
  1229. /* Assume client realized the proper palette for us */
  1230. DPF("Using system palette\n");
  1231. if (ghpalApp)
  1232. DeleteObject(ghpalApp);
  1233. hpal = ghpalApp = CreateSystemPalette();
  1234. }
  1235. else {
  1236. DPF("Using clients OWNDC palette\n");
  1237. }
  1238. if (hpal)
  1239. SetPaletteMCI(hpal);
  1240. }
  1241. else {
  1242. DPF("Using MCI Object's normal palette\n");
  1243. }
  1244. }
  1245. else {
  1246. //
  1247. // for non window devices, just have the playbar show up!
  1248. // so use a zero height MCI Window area.
  1249. //
  1250. rcSave.top = rcSave.bottom;
  1251. }
  1252. //
  1253. // if we are not in small mode, get there now
  1254. //
  1255. if (!gfPlayOnly) {
  1256. ShowWindow(ghwndApp, SW_HIDE);
  1257. gfPlayOnly = TRUE;
  1258. SizeMPlayer();
  1259. }
  1260. ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
  1261. if (gwOptions & OPT_BORDER)
  1262. SetWS(ghwndApp, WS_BORDER);
  1263. /* Set the size of Mplayer to have enough space for the MCI */
  1264. /* playback area and a playbar and the non-client area. */
  1265. rcSave.bottom += gwPlaybarHeight;
  1266. AdjustWindowRect(&rcSave, GetWS(ghwndApp), FALSE);
  1267. Ole1PlayInPlace(ghwndApp, hwndClient, &rcSave);
  1268. fShow = FALSE;
  1269. fActivate = FALSE;
  1270. /* become visible */
  1271. ShowWindow(ghwndApp,SW_SHOWNA);
  1272. /* Remember to play the video in the rcClient area of rcSave */
  1273. if ((gwDeviceType & DTMCI_CANWINDOW) &&
  1274. (gwOptions & OPT_TITLE) && xIndent != 0)
  1275. SetDestRectMCI(&rcClient);
  1276. /* Let keyboard interface work on control bar, and let the */
  1277. /* accelerators go through. */
  1278. toolbarSetFocus(ghwndToolbar, BTN_PLAY);
  1279. SetFocus(ghwndToolbar);
  1280. gfCloseAfterPlaying = TRUE;
  1281. /* We won't play in place - use a popup window or nothing. */
  1282. } else {
  1283. /* If we want a playbar, then use MPlayer reduced mode to play. */
  1284. /* If we don't want one, then don't show mplayer's window - */
  1285. /* we'll just use the default MCI window (for a windowed device)*/
  1286. /* or nothing for a non-windowed device. If we stole an already*/
  1287. /* running instance of mplayer, we must use it and not run */
  1288. /* silently. */
  1289. if ((gwOptions & OPT_BAR) || fWindowWasVisible) {
  1290. DPF("Using Toplevel window for playback\n");
  1291. /* go to our little miniature version */
  1292. if (!gfPlayOnly && !fWindowWasVisible) {
  1293. gwPlaybarHeight = TOOLBAR_HEIGHT;
  1294. gfPlayOnly = TRUE;
  1295. SizeMPlayer();
  1296. }
  1297. fShow = fActivate = TRUE;
  1298. gfCloseAfterPlaying = !fWindowWasVisible;
  1299. } else {
  1300. DPF("Running silently\n");
  1301. if (!fWindowWasVisible)
  1302. SetWindowMCI(NULL); // make sure we're using default MCI win
  1303. fShow = fActivate = FALSE;
  1304. gfCloseAfterPlaying = TRUE; // we're invisible, so close auto.
  1305. }
  1306. }
  1307. Yield(); // If play goes to full screen mode, PowerPig will
  1308. Yield(); // time out and put up errors thinking we didn't play.
  1309. PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
  1310. } else if (verb == 1) {
  1311. DPF("ItemDoVerb: Edit\n");
  1312. if (gfPlayOnly) {
  1313. gfPlayOnly = FALSE;
  1314. SizeMPlayer();
  1315. }
  1316. /* If we come up empty, it's OK to be in OPEN or NOT_READY mode and */
  1317. /* don't try to seek anywhere. */
  1318. if (gwDeviceID) {
  1319. switch (gwStatus) {
  1320. case MCI_MODE_OPEN:
  1321. case MCI_MODE_NOT_READY:
  1322. Error(ghwndApp, IDS_CANTEDIT);
  1323. break;
  1324. default:
  1325. // Seek to the position we were when we copied. Stop first.
  1326. if (StopMCI()) {
  1327. // fix state so Seek recognizes we're stopped
  1328. gwStatus = MCI_MODE_STOP;
  1329. SeekMCI(gdwPosition);
  1330. }
  1331. break;
  1332. }
  1333. }
  1334. /* Let UpdateDisplay set focus properly by saying we're invalid */
  1335. gwStatus = (UINT)(-1);
  1336. /* Our special ItemOpen verb */
  1337. } else if (verb == -1) {
  1338. Ole1ReallyDoVerb(lpobj, 1, fShow, fActivate);
  1339. if (gwDeviceID)
  1340. Ole1ReallyDoVerb(lpobj, OLEVERB_PRIMARY, fShow, fActivate);
  1341. return OLE_OK;
  1342. } else {
  1343. DPF("ItemDoVerb: Unknown verb: %d\n", verb);
  1344. }
  1345. if (fShow) {
  1346. ShowWindow(ghwndApp, SW_SHOW);
  1347. if (IsIconic(ghwndApp))
  1348. SendMessage(ghwndApp, WM_SYSCOMMAND, SC_RESTORE, 0L);
  1349. }
  1350. if (fActivate) {
  1351. BringWindowToTop (ghwndApp); // let WM_ACTIVATE put client
  1352. SetActiveWindow (ghwndApp); // underneath us
  1353. }
  1354. return OLE_OK;
  1355. }
  1356. /**************************************************************************
  1357. ***************************************************************************/
  1358. OLESTATUS FAR PASCAL ItemRelease (
  1359. LPOLEOBJECT lpoleobject)
  1360. {
  1361. DPF("ItemRelease\n");
  1362. gItem.lpoleclient = NULL;
  1363. return OLE_OK;
  1364. }
  1365. /**************************************************************************
  1366. ***************************************************************************/
  1367. OLESTATUS FAR PASCAL ItemGetData ( LPOLEOBJECT lpoleobject,
  1368. OLECLIPFORMAT cfFormat,
  1369. LPHANDLE lphandle)
  1370. {
  1371. PITEM pitem;
  1372. DPF("ItemGetData\n");
  1373. #ifndef _WIN32
  1374. pitem = (PITEM)(WORD)(DWORD)lpoleobject;
  1375. #else
  1376. // LKG: What was that doing? Are they unpacking something subtle?
  1377. pitem = (PITEM)lpoleobject;
  1378. #endif //_WIN32
  1379. if (cfFormat == cfNative) {
  1380. *lphandle = Ole1GetLink ();
  1381. if (!(*lphandle))
  1382. return OLE_ERROR_MEMORY;
  1383. if (gfEmbeddedObject)
  1384. CleanObject();
  1385. return OLE_OK;
  1386. }
  1387. *lphandle = NULL;
  1388. if (cfFormat == CF_METAFILEPICT) {
  1389. *lphandle = GetPicture (pitem);
  1390. }
  1391. else if (cfFormat == CF_PALETTE) {
  1392. *lphandle = GetPalette(pitem);
  1393. }
  1394. else if (cfFormat == CF_DIB) {
  1395. *lphandle = GetDib(pitem);
  1396. }
  1397. else if (cfFormat == cfLink || cfFormat == cfOwnerLink){
  1398. *lphandle = Ole1GetLink ();
  1399. }
  1400. else return OLE_ERROR_MEMORY; // this is actually unknown format.
  1401. if (!(*lphandle))
  1402. return OLE_ERROR_MEMORY; // honestly this time
  1403. return OLE_OK;
  1404. }
  1405. /**************************************************************************
  1406. ***************************************************************************/
  1407. OLESTATUS FAR PASCAL ItemSetTargetDevice (
  1408. LPOLEOBJECT lpoleobject,
  1409. HGLOBAL hdata)
  1410. {
  1411. DPF("ItemSetTargetDevice\n");
  1412. return OLE_OK;
  1413. }
  1414. /**************************************************************************
  1415. ***************************************************************************/
  1416. STATICFN OLESTATUS NEAR PASCAL SetDataPartII(LPWSTR szFile, LPWSTR szDevice)
  1417. {
  1418. int status = OLE_OK;
  1419. LHSERVERDOC lhdocTemp;
  1420. // TERRIBLE HACK! set gfEmbeddedObject so OpenMCI does
  1421. // not re-register this document!!!
  1422. //
  1423. BlockServer();
  1424. lhdocTemp = gDoc.lhdoc;
  1425. gDoc.lhdoc = (LHSERVERDOC)0; /* So it won't be killed by CloseMCI!! */
  1426. gfEmbeddedObject++;
  1427. /* Coming up: Horrible cast to get rid of warning.
  1428. *
  1429. * This file is compiled non-Unicode, in contrast to the rest of MPlayer.
  1430. * This means that LPTSTR in the function prototypes mean different things
  1431. * depending on who included them. OpenMciDevice and other Unicode
  1432. * routines called from this module expect Unicode strings, but the
  1433. * compiler thinks they're ANSI. We can keep the compiler happy by
  1434. * casting them to LPTSTR. Does that make sense?
  1435. *
  1436. * Places where this unspeakable act is perpetrated are indicated thus:
  1437. */
  1438. if (!OpenMciDevice((LPTSTR)szFile, (LPTSTR)szDevice))
  1439. // ^^^^^^^^ ^^^^^^^^
  1440. status = OLE_ERROR_FORMAT;
  1441. gfEmbeddedObject--;
  1442. gDoc.lhdoc = lhdocTemp;
  1443. /* Set the selection to what we parsed in ParseOptions. */
  1444. if (status == OLE_OK) {
  1445. SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
  1446. SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
  1447. }
  1448. UnblockServer();
  1449. return status;
  1450. }
  1451. /**************************************************************************/
  1452. /**************************************************************************/
  1453. OLESTATUS FAR PASCAL ItemSetData1(LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata)
  1454. {
  1455. LPBYTE p, pSave, pT;
  1456. // Why BYTE?? And is this heading
  1457. // for UNICODE trouble?
  1458. LPWSTR pUnicode;
  1459. LPSTR szFile, szDevice;
  1460. char achFile[MAX_PATH];
  1461. char ach[40];
  1462. OLESTATUS status;
  1463. WCHAR FileNameW[MAX_PATH];
  1464. DPF("ItemSetData1\n");
  1465. if (hdata == NULL)
  1466. return OLE_ERROR_MEMORY;
  1467. if (cfFormat != cfNative)
  1468. return OLE_ERROR_FORMAT;
  1469. p = GlobalLock(hdata);
  1470. if (p == NULL)
  1471. return OLE_ERROR_MEMORY;
  1472. szFile = p + lstrlen((LPSTR)p) + 1; // pick off the Filename
  1473. p = szFile + lstrlen(szFile) + 1;
  1474. pSave = p;
  1475. szDevice = ach; // copy over Device name and
  1476. for (pT = ach; *p && *p != ',';) // NULL terminate it (it ends
  1477. *pT++ = *p++; // with a ',' right now).
  1478. *pT = '\0';
  1479. #ifdef DEBUG
  1480. DPF(" %s|%s!%s\n", (LPSTR)p, (LPSTR)szFile, (LPSTR)szDevice);
  1481. #endif
  1482. BlockServer(); // cause CloseMCI can yield
  1483. CloseMCI(TRUE); // nuke old gachCaption
  1484. UnblockServer();
  1485. pUnicode = AllocateUnicodeString(pSave);
  1486. if( !pUnicode )
  1487. return OLE_ERROR_MEMORY;
  1488. ParseOptions((LPTSTR)pUnicode); // this will set new gachCaption
  1489. // YUK ^^^^^^^^ \\
  1490. FreeUnicodeString(pUnicode);
  1491. // If this file doesn't exist, we won't continue setting data, we will
  1492. // succeed and get out, and do it later, because we can't bring up a dialog
  1493. // right now because clients like WinWord won't dispatch any msgs.
  1494. lstrcpyn(achFile, szFile, sizeof(achFile));
  1495. // if the filename we were given is bad, try and find it somewhere
  1496. COPYSTRINGA2W(FileNameW, szFile);
  1497. if (FindRealFileName((LPTSTR)FileNameW, sizeof(achFile))) {
  1498. // YUK ^^^^^^^^ \\
  1499. // We found it on the disk somewhere, so continue with SetData
  1500. WCHAR szDeviceW[80];
  1501. COPYSTRINGA2W(szDeviceW, szDevice);
  1502. status = SetDataPartII(FileNameW, szDeviceW);
  1503. } else {
  1504. // Nowhere to be found. We need to ask the user to find it... LATER!!
  1505. if (gfBrokenLink) {
  1506. DPF("ACK!! Got Second ItemSetData with BrokenLink!!");
  1507. return OLE_ERROR_GENERIC;
  1508. }
  1509. // Succeed to ItemSetData so client will be happy
  1510. lstrcpyn(gachDeviceA, szDevice, sizeof(gachDeviceA));
  1511. COPYSTRINGA2W(gachFile, szFile);
  1512. gfBrokenLink = TRUE;
  1513. status = OLE_OK;
  1514. }
  1515. return status;
  1516. }
  1517. /**************************************************************************
  1518. ***************************************************************************/
  1519. OLESTATUS FAR PASCAL ItemSetColorScheme (LPOLEOBJECT lpobj,
  1520. OLE_CONST LOGPALETTE FAR * lppalette)
  1521. {
  1522. DPF("ItemSetColorScheme\n");
  1523. return OLE_OK;
  1524. }
  1525. /**************************************************************************
  1526. ***************************************************************************/
  1527. OLESTATUS FAR PASCAL ItemSetBounds (LPOLEOBJECT lpobj, OLE_CONST RECT FAR* lprc)
  1528. {
  1529. DPF("ItemSetBounds: [%d,%d,%d,%d]\n", *lprc);
  1530. return OLE_OK;
  1531. }
  1532. /**************************************************************************
  1533. ***************************************************************************/
  1534. OLECLIPFORMAT FAR PASCAL ItemEnumFormats(
  1535. LPOLEOBJECT lpoleobject,
  1536. OLECLIPFORMAT cfFormat)
  1537. {
  1538. ////DPF("ItemEnumFormats: %u\n",cfFormat);
  1539. if (cfFormat == 0)
  1540. return cfLink;
  1541. if (cfFormat == cfLink)
  1542. return cfOwnerLink;
  1543. if (cfFormat == cfOwnerLink)
  1544. return CF_METAFILEPICT;
  1545. if (cfFormat == CF_METAFILEPICT)
  1546. return CF_DIB;
  1547. if (cfFormat == CF_DIB)
  1548. return CF_PALETTE;
  1549. if (cfFormat == CF_PALETTE)
  1550. return cfNative;
  1551. //if (cfFormat == cfNative)
  1552. // return NULL;
  1553. return (OLECLIPFORMAT)0;
  1554. }
  1555. /**************************************************************************
  1556. ***************************************************************************/
  1557. int FAR PASCAL SendChangeMsg (UINT options)
  1558. {
  1559. CHAR szAnsi[MAX_PATH];
  1560. if (gDoc.lhdoc && gDoc.lhdoc != -1) {
  1561. if (options == OLE_SAVED) {
  1562. DPF("SendChangeMsg(OLE_SAVED): Calling OleSavedServerDoc\n");
  1563. DPF0( "SendChangeMsg: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
  1564. return OleSavedServerDoc(gDoc.lhdoc);
  1565. } else if (options == OLE_RENAMED) {
  1566. DPF("SendChangeMsg(OLE_RENAMED): new name is '%ws'.\n", (LPWSTR)gachFileDevice);
  1567. COPYSTRINGW2A(szAnsi, gachFileDevice);
  1568. return OleRenameServerDoc(gDoc.lhdoc, szAnsi);
  1569. } else if (gItem.lpoleclient) {
  1570. DPF("SendChangeMsg(%d) client=%lx\n",options,gItem.lpoleclient);
  1571. return (*gItem.lpoleclient->lpvtbl->CallBack) (gItem.lpoleclient,
  1572. options, (LPOLEOBJECT)&gItem);
  1573. }
  1574. }
  1575. return OLE_OK;
  1576. }
  1577. /**************************************************************************
  1578. ***************************************************************************/
  1579. void FAR PASCAL CopyObject(HWND hwnd)
  1580. {
  1581. PITEM pitem = &gItem;
  1582. //
  1583. // we put two types of OLE objects in the clipboard, the type of
  1584. // OLE object is determined by the *order* of the clipboard data
  1585. //
  1586. // Embedded Object:
  1587. // cfNative
  1588. // OwnerLink
  1589. // Picture
  1590. // ObjectLink
  1591. //
  1592. // Linked Object:
  1593. // OwnerLink
  1594. // Picture
  1595. // ObjectLink
  1596. //
  1597. if (OpenClipboard (hwnd)) {
  1598. // Copying an object can take a long time - especially large AVI frames
  1599. // Tell the user its coffee time.
  1600. HCURSOR hcurPrev = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1601. BlockServer();
  1602. EmptyClipboard();
  1603. SetClipboardData(cfNative, Ole1GetLink());
  1604. /* Don't ask me why we do this even if it is untitled... */
  1605. SetClipboardData (cfOwnerLink, Ole1GetLink());
  1606. CopyMCI(NULL);
  1607. #if 0 // DON'T OFFER LINKS ANYMORE!
  1608. /* Only offer link data if not untitled and not a embedded object */
  1609. if (gwDeviceType & DTMCI_FILEDEV)
  1610. SetClipboardData(cfLink, Ole1GetLink());
  1611. #endif
  1612. UnblockServer();
  1613. CloseClipboard();
  1614. SetCursor(hcurPrev); // We're back!!!
  1615. }
  1616. }
  1617. /**************************************************************************
  1618. ***************************************************************************/
  1619. /**************************************************************************
  1620. STUFF FOR PLAY IN PLACE
  1621. ***************************************************************************/
  1622. #ifndef _WIN32
  1623. /**************************************************************************
  1624. ***************************************************************************/
  1625. LRESULT CALLBACK _EXPORT MouseHook(int hc, WPARAM wParam, LPARAM lParam)
  1626. {
  1627. LPMOUSEHOOKSTRUCT lpmh = (LPVOID)lParam;
  1628. BOOL fDownNow, fDownBefore;
  1629. //
  1630. // NOTE SS != DS
  1631. //
  1632. if (hc == HC_ACTION)
  1633. {
  1634. #ifdef XDEBUG
  1635. char ach[80];
  1636. wsprintf( ach
  1637. , "MouseHook: %c%c pt=[%d,%d] hwnd=%04X ht=%04X\r\n"
  1638. , (GetAsyncKeyState(VK_LBUTTON) < 0 ? 'L' : ' ')
  1639. , (GetAsyncKeyState(VK_RBUTTON) < 0 ? 'R' : ' ')
  1640. , lpmh->pt
  1641. , lpmh->hwnd
  1642. , lpmh->wHitTestCode
  1643. );
  1644. OutputDebugString(ach);
  1645. #endif
  1646. /* If the mouse was DOWN when we started, we wait until it comes up */
  1647. /* before we let mouse downs kill us. If KeyState said it was DOWN */
  1648. /* we wait until it says it is UP before we let DOWN KeyStates kill */
  1649. /* us. */
  1650. /* We're checking Async because we have to... it's the NOW state. */
  1651. /* We're ALSO checking GetKeyState because Faris' machine misses */
  1652. /* some mouse downs unless we call every function possible !!**!!** */
  1653. fDownNow = GetAsyncKeyState(VK_LBUTTON) || GetAsyncKeyState(VK_RBUTTON);
  1654. fDownBefore = GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON);
  1655. if ((fDownNow && gfMouseUpSeen) || (fDownBefore && gfKeyStateUpSeen)) {
  1656. //
  1657. // the user is clicking on the client DOC, allow him/her to
  1658. // only click on the caption (for moving sizing) or we will
  1659. // exit.
  1660. //
  1661. if (lpmh->hwnd != GetDesktopWindow() &&
  1662. lpmh->wHitTestCode != HTCAPTION) {
  1663. // Do this NOW before anybody gets a chance to yield and draw
  1664. // with the wrong styles...
  1665. if (gfPlayingInPlace)
  1666. Ole1EndPlayInPlace(ghwndApp);
  1667. PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
  1668. }
  1669. }
  1670. if (!fDownNow)
  1671. gfMouseUpSeen = TRUE;
  1672. if (!fDownBefore)
  1673. gfKeyStateUpSeen = TRUE;
  1674. }
  1675. return CallNextHookEx(hHookMouse, hc, wParam, lParam);
  1676. }
  1677. #endif
  1678. /**************************************************************************
  1679. ***************************************************************************/
  1680. void FAR PASCAL Ole1PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
  1681. {
  1682. HWND hwndP;
  1683. DPF("Ole1PlayInPlace(%04X, %04X, [%d %d %d %d])\n", hwndApp, hwndClient, *prc);
  1684. if (gfPlayingInPlace) // this is bad
  1685. return;
  1686. #ifdef DEBUG
  1687. if (GetPrivateProfileInt("options", "PopupWindow", FALSE, "mplayer.ini"))
  1688. #else
  1689. if (FALSE)
  1690. #endif
  1691. {
  1692. DPF("Using Popup window for playback\n");
  1693. //
  1694. // this is code for a popup window.
  1695. //
  1696. ClientToScreen(hwndClient, (LPPOINT)prc);
  1697. ClientToScreen(hwndClient, (LPPOINT)prc+1);
  1698. SetWS(hwndApp, WS_POPUP);
  1699. hwndP = TopWindow(hwndClient);
  1700. #ifndef _WIN32
  1701. // I haven't the faintest idea what this is trying to do, but I see it's
  1702. // within the scope of a retail if(FALSE) anyway.
  1703. // If you understand it then either delete the function or replace this comment.
  1704. // Laurie
  1705. SetWindowWord(hwndApp, GWW_HWNDPARENT, (WORD)hwndP); // set owner
  1706. #endif
  1707. gfParentWasEnabled = IsWindowEnabled(hwndP);
  1708. EnableWindow(hwndP, FALSE);
  1709. } else {
  1710. DPF("Using Child window for playback\n");
  1711. SetWS(hwndApp, WS_CHILD);
  1712. SetParent(hwndApp, hwndClient);
  1713. DinkWithWindowStyles(hwndApp, FALSE);
  1714. }
  1715. gfPlayingInPlace = TRUE;
  1716. SetWindowPos(hwndApp, HWND_TOP,
  1717. prc->left,prc->top,
  1718. prc->right - prc->left,
  1719. prc->bottom - prc->top,
  1720. SWP_NOACTIVATE);
  1721. #ifndef _WIN32
  1722. if (fpMouseHook == NULL)
  1723. fpMouseHook = (HOOKPROC)MakeProcInstance((FARPROC)MouseHook, ghInst);
  1724. #endif
  1725. //
  1726. // Is the key down at this INSTANT ??? Then wait until it comes up before
  1727. // we allow GetAsyncKeyState to make us go away
  1728. //
  1729. gfMouseUpSeen = !((GetAsyncKeyState(VK_LBUTTON) & 0x8000) ||
  1730. (GetAsyncKeyState(VK_RBUTTON) & 0x8000));
  1731. //
  1732. // Is GetKeyState saying it's down? If so, wait until GetKeyState returns
  1733. // up before we let GetKeyState kill us.
  1734. //
  1735. gfKeyStateUpSeen= !(GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON));
  1736. #ifdef _WIN32
  1737. /*
  1738. ** Tell mciole32.dll to install its mouse HookProc.
  1739. */
  1740. #ifdef DEBUG
  1741. if ( fHookInstalled ) {
  1742. DPF( "Hook already installed\n" );
  1743. DebugBreak();
  1744. }
  1745. #endif
  1746. if ( fpInstallHook ) {
  1747. DWORD wow_thread_id = 0L;
  1748. /*
  1749. ** This is a HACK. If the client applications is a WOW app the
  1750. ** HIWORD of the window handle will be 0xFFFF.
  1751. */
  1752. if ( HIWORD(hwndClient) == 0xFFFF ) {
  1753. wow_thread_id = GetWindowThreadProcessId( hwndClient, NULL );
  1754. }
  1755. fHookInstalled = (*fpInstallHook)( ghwndApp, wow_thread_id );
  1756. }
  1757. #else /* !_WIN32 */
  1758. hHookMouse = SetWindowsHookEx( WH_MOUSE, fpMouseHook, ghInst,
  1759. GetWindowTask(hwndClient) );
  1760. #endif
  1761. ghwndFocusSave = GetFocus();
  1762. }
  1763. /**************************************************************************
  1764. ***************************************************************************/
  1765. void FAR PASCAL Ole1EndPlayInPlace(HWND hwndApp)
  1766. {
  1767. HWND hwndP;
  1768. HWND hwndT;
  1769. #if 0 // can't do this because SS != DS
  1770. DPF("Ole1EndPlayInPlace()\n");
  1771. #endif
  1772. if (!gfPlayingInPlace || !IsWindow(hwndApp))
  1773. return;
  1774. /* Do this BEFORE hiding our window and BEFORE we do anything that */
  1775. /* might yield so client can't redraw with the wrong styles set. */
  1776. DinkWithWindowStyles(hwndApp, TRUE);
  1777. gfPlayingInPlace = FALSE;
  1778. #ifdef _WIN32
  1779. /*
  1780. ** Tell mciole32.dll to remove its mouse HookProc.
  1781. */
  1782. if ( fpRemoveHook ) {
  1783. fHookInstalled = !(*fpRemoveHook)();
  1784. }
  1785. #else /* !_WIN32 */
  1786. UnhookWindowsHookEx(hHookMouse);
  1787. hHookMouse = NULL;
  1788. #endif
  1789. hwndP = GetParent(hwndApp);
  1790. //
  1791. // If we have the focus, then restore it to who used to have it.
  1792. // ACK!! If the person who used to have it is GONE, we must give it away
  1793. // to somebody (who choose our parent) because our child can't
  1794. // keep the focus without making windows crash hard during the WM_DESTROY
  1795. // (or maybe later whenever it feels like crashing at some random time).
  1796. // See bug #8634.
  1797. //
  1798. if ((hwndT = GetFocus()) && GetWindowTask(hwndT) == MGetCurrentTask) {
  1799. if (IsWindow(ghwndFocusSave))
  1800. SetFocus(ghwndFocusSave);
  1801. else
  1802. SetFocus(hwndP);
  1803. }
  1804. if (!hwndP ||
  1805. (gwOptions & OPT_BAR) ||
  1806. (gwOptions & OPT_BORDER) ||
  1807. (gwOptions & OPT_AUTORWD)) {
  1808. //
  1809. // hide the aplication window
  1810. //
  1811. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  1812. SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|
  1813. SWP_NOACTIVATE);
  1814. }
  1815. else {
  1816. //
  1817. // hide our window, but don't redraw it will look
  1818. // like we are still on the last frame.
  1819. //
  1820. // this is when we are playing in place, and there is
  1821. // no playbar, and no rewind
  1822. //
  1823. // this is for Playing a AVI in a PowerPoint slide
  1824. // without redraw problems.
  1825. //
  1826. SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
  1827. SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
  1828. SWP_HIDEWINDOW|SWP_NOACTIVATE);
  1829. }
  1830. SetParent(hwndApp, NULL);
  1831. ClrWS(hwndApp, WS_CHILD);
  1832. if (hwndP && gfParentWasEnabled)
  1833. EnableWindow(hwndP, TRUE);
  1834. //
  1835. // set either the owner or the WS_CHILD bit so it will
  1836. // not act up because we have the palette bit set and cause the
  1837. // desktop to steal the palette.
  1838. //
  1839. #if 0
  1840. // The folowing was ifdef-ed away before I saw it, but note that it
  1841. // wouldn't work on WIN32 anyway.
  1842. SetWindowWord(hwndApp, GWW_HWNDPARENT, (WORD)GetDesktopWindow());
  1843. #else
  1844. SetWS(hwndApp, WS_CHILD);
  1845. #endif
  1846. }
  1847. #endif /* OLE1_HACK */
  1848.