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.

2121 lines
60 KiB

  1. /* Copyright (c) 1992-1999 Microsoft Corporation */
  2. /*****************************************************************************\
  3. *
  4. * MCIOLE.C
  5. *
  6. * Modified 19-Oct-1992 by Mike Tricker [MikeTri] Ported to Win32
  7. *
  8. \*****************************************************************************/
  9. // #define USE_MOUSE_HOOK
  10. #ifdef WIN32
  11. #if DBG
  12. #define DEBUG
  13. #endif
  14. #endif
  15. //
  16. // MCIOLE - OLE handler DLL for MCI objects
  17. //
  18. //
  19. // NOTES:
  20. // The whole reason for this handler DLL is to supply the function
  21. //
  22. // OleQueryObjPos()
  23. //
  24. // this function gives information to the server application on the
  25. // location (in the client document) of the activated OLE object.
  26. // the server can use this information to play the object in place
  27. // or position the server window correctly
  28. //
  29. // IMPLEMENTION:
  30. //
  31. // in theory all this DLL (handler) has to do is save the information
  32. // passed to OleActivate(). But in reality no app correctly calls
  33. // OleActivate(). They either pass no information or the wrong
  34. // information.
  35. //
  36. // this DLL is a OLE handler, because of global data (vtblDef!) it
  37. // can only be a handler for one class at a time.
  38. //
  39. // the handler intercepts the OleDraw, OleActivate, and all the
  40. // creation/destuction OLE APIs. for each OLE object a info
  41. // structure is maintained (a OBJINFO structure) when ever the
  42. // client draws (using OleDraw...) the drawing position, and the
  43. // window drawn to is remembered.
  44. //
  45. // when the client calls OleActivate, the saved draw location is
  46. // recalled, or if the app never called OleDraw() (plays
  47. // the meta-file itself) then the rectangle passed to OleActivate()
  48. // is used. (if one is supplied)
  49. //
  50. // there are many classes of apps:
  51. //
  52. // calls OleActivate() with correct info
  53. // calls OleActivate() with incorrect info
  54. // calls OleActivate() with no info
  55. //
  56. // calls OleDraw()
  57. // does not call OleDraw()
  58. //
  59. // here is a table of known OLE Clients....
  60. //
  61. // OleDraw OleActivate()
  62. // App Y or N Y, N, X
  63. // (X = wrong info)
  64. // ------------- ---------- ------------
  65. // Write Y N
  66. // CardFile Y N
  67. // Packager Y N
  68. //
  69. // Excel N N (uses DDE)
  70. // Excel 4.0 N N (uses DDE)
  71. // PowerPnt 2.0 N N (uses DDE)
  72. //
  73. // WinWord N N
  74. // WinWorks Y X
  75. // PowerPnt 3.0 N Y
  76. // MsPublisher N X
  77. // ClTest Y N
  78. // Cirus Y X
  79. // WinProj ? ?
  80. //
  81. // AmiPro Y ?
  82. //
  83. #include <windows.h>
  84. #include <ole.h>
  85. #include <port1632.h>
  86. #include <stdio.h>
  87. #include "mciole.h"
  88. #ifdef WIN32
  89. #include <stdlib.h>
  90. #else
  91. #include <shellapi.h>
  92. #endif
  93. HANDLE ghInstance; // Module handle
  94. BOOL fRunningInWOW; // Dll attached to the WOW process
  95. OLEOBJECTVTBL vtblDll; // these are our functions.
  96. OLEOBJECTVTBL vtblDef; // these are the default functions.
  97. HBITMAP hbmStock;
  98. /******************************************************************************\
  99. **
  100. ** The mciole32 shared memory.
  101. **
  102. ** This is only used when mplay32 is serving a WOW client. The memory
  103. ** always gets mapped into the WOW process. It only gets mapped into
  104. ** the mplay32.exe server process if mplay32.exe detects that it is serving
  105. ** a WOW client app. Therefore the global variable lpvMem is NULL in all
  106. ** other processes.
  107. **
  108. ** The memory gets mapped into the mplay32.exe server when it sets the
  109. ** the global hook. We can detect that mplay32.exe is serving a WOW client
  110. ** because the clients window handle will have 0xFFFF in its HIWORD.
  111. ** Of course this is a real hack.
  112. **
  113. ** Inside the hook proc we look at lpvMem. If it is NULL we ignore it because
  114. ** current process is not WOW or mplay32.exe serving a WOW client.
  115. ** We then check to see if the client process id matches the current process
  116. ** id. If this is the case we look for interesting mouse message and stop
  117. ** the playing in place if we find any.
  118. **
  119. ** If lpvMem is not NULL the current process must either by WOW or mplay32.exe
  120. ** serving a WOW client, in which case the global fRunningInWOW will be FALSE.
  121. **
  122. **
  123. **
  124. **
  125. \******************************************************************************/
  126. typedef struct {
  127. HWND hwndServer;
  128. DWORD wow_app_thread_id;
  129. } MCIOLE32_SHARED_MEMORY;
  130. MCIOLE32_SHARED_MEMORY *lpvMem;
  131. HANDLE hMapObject = NULL; /* handle to file mapping */
  132. #ifdef DEBUG
  133. RECT rcNull = {0,0,0,0};
  134. UINT oleDebugLevel = 0;
  135. #define PUSHRC(prc) *((prc) ? (prc) : &rcNull)
  136. #define CARETPOS() // {POINT pt; GetCaretPos(&pt); DPRINTF(("CaretPos: [%d, %d]", pt.x, pt.y));}
  137. #endif
  138. /****************************************************************************
  139. ****************************************************************************/
  140. void ReplaceFunctions(LPOLEOBJECT);
  141. BOOL CanReplace(LPOLEOBJECT);
  142. #ifndef WIN32
  143. /****************************************************************************
  144. FUNCTION: LibMain(HANDLE hInstance)
  145. ****************************************************************************/
  146. BOOL NEAR PASCAL LibMain (HANDLE hInstance)
  147. {
  148. HDC hdc;
  149. HBITMAP hbm;
  150. ghInstance = (HANDLE)hInstance;
  151. //
  152. // get the stock 1x1 mono bitmap.
  153. //
  154. hbm = CreateBitmap(1,1,1,1,NULL);
  155. hdc = CreateCompatibleDC(NULL);
  156. hbmStock = SelectObject(hdc, hbm);
  157. SelectObject(hdc, hbmStock);
  158. DeleteDC(hdc);
  159. DeleteObject(hbm);
  160. // // register clipboard formats.
  161. // cfObjectLink = RegisterClipboardFormat("ObjectLink");
  162. // cfOwnerLink = RegisterClipboardFormat("OwnerLink");
  163. // cfNative = RegisterClipboardFormat("Native");
  164. return TRUE;
  165. }
  166. #else
  167. /****************************************************************************
  168. FUNCTION: DllEntryPoint(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved)
  169. This function is called whenever a process attaches or detaches to/from
  170. the DLL.
  171. ****************************************************************************/
  172. BOOL
  173. DllEntryPoint(
  174. HINSTANCE hinstDLL, /* DLL module handle */
  175. DWORD fdwReason, /* reason called */
  176. LPVOID lpvReserved) /* reserved */
  177. {
  178. BOOL fIgnore;
  179. HDC hdc;
  180. HBITMAP hbm;
  181. # define SHMEMSIZE (sizeof(MCIOLE32_SHARED_MEMORY))
  182. switch (fdwReason) {
  183. /*
  184. ** DLL is attaching to a process, due to process
  185. ** initialization or a call to LoadLibrary.
  186. */
  187. case DLL_PROCESS_ATTACH:
  188. ghInstance = (HANDLE)hinstDLL;
  189. //
  190. // get the stock 1x1 mono bitmap. why ??
  191. //
  192. hbm = CreateBitmap(1,1,1,1,NULL);
  193. if (NULL != hbm)
  194. {
  195. hdc = CreateCompatibleDC(NULL);
  196. if (NULL != hdc)
  197. {
  198. hbmStock = SelectObject(hdc, hbm);
  199. if (NULL != hbmStock)
  200. SelectObject(hdc, hbmStock);
  201. DeleteDC(hdc);
  202. }
  203. DeleteObject(hbm);
  204. }
  205. #ifdef DEBUG
  206. oleDebugLevel = GetProfileInt("Debug", "MCIOLE32", 0);
  207. #endif
  208. /*
  209. **
  210. **
  211. **
  212. ** create named file mapping object
  213. */
  214. hMapObject = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file
  215. NULL, // no security attr.
  216. PAGE_READWRITE, // read/write access
  217. 0, // size: high 32-bits
  218. SHMEMSIZE, // size: low 32-bits
  219. "mciole32shrmem"); // name of map object
  220. if (hMapObject == NULL) {
  221. return FALSE;
  222. }
  223. /*
  224. ** The first process to attach initializes memory.
  225. **
  226. ** fInit = (GetLastError() != ERROR_ALREADY_EXISTS);
  227. **
  228. */
  229. /*
  230. ** Are we attaching to the WOW process ?
  231. ** If so the we map the shared memory into the process.
  232. */
  233. fRunningInWOW = (GetModuleHandle( "WOW32.DLL" ) != NULL);
  234. if ( fRunningInWOW ) {
  235. DPRINTF(( "Attaching shared memory to WOW process" ));
  236. /*
  237. ** Get a pointer to file mapped shared memory.
  238. */
  239. lpvMem = MapViewOfFile( hMapObject, FILE_MAP_WRITE, 0, 0, 0 );
  240. if (lpvMem == NULL) {
  241. fIgnore = CloseHandle(hMapObject);
  242. return FALSE;
  243. }
  244. }
  245. break;
  246. case DLL_THREAD_ATTACH:
  247. /*
  248. ** The attached process creates a new thread.
  249. */
  250. break;
  251. case DLL_THREAD_DETACH:
  252. /*
  253. ** The thread of the attached process terminates.
  254. */
  255. break;
  256. case DLL_PROCESS_DETACH:
  257. /*
  258. ** The DLL is detaching from a process, due to
  259. ** process termination or a call to FreeLibrary.
  260. **
  261. ** Unmap shared memory from process' address space. But only
  262. ** if it was mapped.
  263. */
  264. if ( lpvMem ) {
  265. #ifdef DEBUG
  266. if ( fRunningInWOW ) {
  267. DPRINTF(( "Unmapping shared memory from WOW process" ));
  268. }
  269. #endif
  270. fIgnore = UnmapViewOfFile(lpvMem);
  271. }
  272. /*
  273. ** Close the process' handle to the file-mapping object.
  274. */
  275. fIgnore = CloseHandle(hMapObject);
  276. break;
  277. default:
  278. break;
  279. }
  280. return TRUE;
  281. }
  282. #endif
  283. #ifndef WIN32
  284. /****************************************************************************
  285. FUNCTION: WEP(int)
  286. PURPOSE: Standard exit routine for the DLL
  287. ****************************************************************************/
  288. int FAR PASCAL _LOADDS WEP(nParameter)
  289. int nParameter;
  290. {
  291. return 1;
  292. }
  293. /****************************************************************************
  294. ****************************************************************************/
  295. BOOL NEAR PASCAL IsApp(LPSTR szApp)
  296. {
  297. char ach[80];
  298. int i;
  299. WORD wStack;
  300. _asm mov wStack,ss
  301. GetModuleFileName((HINSTANCE)wStack, ach, sizeof(ach));
  302. for (i = lstrlen(ach);
  303. i > 0 && ach[i-1] != '\\' && ach[i-1] != '/' && ach[i] != ':';
  304. i--)
  305. ;
  306. return lstrcmpi(ach + i, szApp) == 0;
  307. }
  308. #endif //!WIN32
  309. /****************************************************************************
  310. ****************************************************************************/
  311. BOOL NEAR PASCAL IsDcMemory(HDC hdc)
  312. {
  313. HBITMAP hbmT;
  314. if (hbmT = SelectObject(hdc, hbmStock))
  315. SelectObject(hdc, hbmT);
  316. return hbmT != NULL;
  317. }
  318. /****************************************************************************
  319. ****************************************************************************/
  320. typedef struct _OBJINFO {
  321. struct _OBJINFO*poiNext;
  322. LPOLEOBJECT lpobj; // client side LPOLEOBJECT
  323. HWND hwnd; // client window (passed to OleActivate)
  324. RECT rcActivate; // activation rectangle (passed to OleActivate)
  325. HWND hwndDraw; // active window at time of OleDraw
  326. RECT rcDraw; // rectangle of draw
  327. } OBJINFO;
  328. BOOL RegSetGetData(OBJINFO *poi, BOOL Write)
  329. {
  330. LONG Length;
  331. static CHAR szKey[] = "PlayData";
  332. static CHAR szFormat[] = "%ld %ld %d %d %d %d %d %d %d %d";
  333. if (Write) {
  334. LONG Rc;
  335. CHAR Data[100];
  336. //
  337. // Store hwnd, hwnddraw, rcDraw, rcActivate
  338. //
  339. #ifdef WIN32
  340. wsprintf(Data, szFormat,
  341. (LONG_PTR)poi->hwnd,
  342. (LONG_PTR)poi->hwndDraw,
  343. poi->rcDraw.left,
  344. poi->rcDraw.right,
  345. poi->rcDraw.top,
  346. poi->rcDraw.bottom,
  347. poi->rcActivate.left,
  348. poi->rcActivate.right,
  349. poi->rcActivate.top,
  350. poi->rcActivate.bottom);
  351. #else
  352. wsprintf(Data, szFormat,
  353. (LONG)(poi->hwnd == NULL ? (LONG)0 : MAKELONG(poi->hwnd, 0xFFFF)),
  354. (LONG)(poi->hwndDraw == NULL ? (LONG)0 : MAKELONG(poi->hwndDraw, 0xFFFF)),
  355. poi->rcDraw.left,
  356. poi->rcDraw.right,
  357. poi->rcDraw.top,
  358. poi->rcDraw.bottom,
  359. poi->rcActivate.left,
  360. poi->rcActivate.right,
  361. poi->rcActivate.top,
  362. poi->rcActivate.bottom);
  363. #endif
  364. Rc = RegSetValue(HKEY_CLASSES_ROOT,
  365. szKey,
  366. REG_SZ,
  367. Data,
  368. lstrlen(Data));
  369. return Rc == ERROR_SUCCESS;
  370. } else {
  371. #ifdef WIN32
  372. LONG Rc;
  373. CHAR Data[100];
  374. Length = sizeof(Data);
  375. Rc = RegQueryValue(HKEY_CLASSES_ROOT, szKey,
  376. Data, &Length);
  377. RegSetValue(HKEY_CLASSES_ROOT, szKey, REG_SZ, "", 0);
  378. //
  379. // Extract our data - sscanf doesn't work yet!!!
  380. //
  381. if (Rc == ERROR_SUCCESS) {
  382. LONG OurData[10];
  383. int i;
  384. LPTSTR lpData;
  385. for (i = 0, lpData = Data; i < 10; i++) {
  386. OurData[i] = atol(lpData);
  387. while (*lpData != ' ' && *lpData != '\0') {
  388. lpData++;
  389. }
  390. if (*lpData == ' ') {
  391. lpData++;
  392. }
  393. }
  394. poi->hwnd = (HWND)(UINT_PTR)OurData[0];
  395. poi->hwndDraw = (HWND)(UINT_PTR)OurData[1];
  396. poi->rcDraw.left = OurData[2];
  397. poi->rcDraw.right = OurData[3];
  398. poi->rcDraw.top = OurData[4];
  399. poi->rcDraw.bottom = OurData[5];
  400. poi->rcActivate.left = OurData[6];
  401. poi->rcActivate.right = OurData[7];
  402. poi->rcActivate.top = OurData[8];
  403. poi->rcActivate.bottom = OurData[9];
  404. }
  405. return Rc == ERROR_SUCCESS && Length != 0;
  406. #else
  407. return FALSE;
  408. #endif
  409. }
  410. }
  411. #ifdef DEBUG
  412. int nObjects = 0;
  413. #endif
  414. OBJINFO *poiFirst = NULL;
  415. OBJINFO *FindObj(LPOLEOBJECT lpobj)
  416. {
  417. OBJINFO *poi;
  418. for (poi=poiFirst; poi; poi=poi->poiNext)
  419. if (poi->lpobj == lpobj)
  420. return poi;
  421. DPRINTF(("FindObj: Unable to find object %lx", lpobj));
  422. return NULL;
  423. }
  424. void DelObj(LPOLEOBJECT lpobj)
  425. {
  426. OBJINFO *poi;
  427. OBJINFO *poiT;
  428. for (poiT=NULL,poi=poiFirst; poi; poiT=poi,poi=poi->poiNext)
  429. {
  430. if (poi->lpobj == lpobj)
  431. {
  432. if (poiT)
  433. poiT->poiNext = poi->poiNext;
  434. else
  435. poiFirst = poi->poiNext;
  436. poi->lpobj = NULL;
  437. LocalFree((HLOCAL)poi);
  438. DPRINTF(("DelObj(%lx): %d objects", lpobj, --nObjects));
  439. return;
  440. }
  441. }
  442. DPRINTF(("DelObj(%lx): Cant find object to delete.", lpobj));
  443. }
  444. //
  445. // for some reason we dont get all the OleDelete() calls that we should
  446. // so lets try to "weed out the bad apples" so we dont choke.
  447. //
  448. void CleanObjects()
  449. {
  450. OBJINFO *poi;
  451. again:
  452. for (poi=poiFirst; poi; poi=poi->poiNext)
  453. {
  454. if (IsBadReadPtr(poi->lpobj, 0))
  455. {
  456. DPRINTF(("Freeing bad object %lx", poi->lpobj));
  457. DelObj(poi->lpobj);
  458. goto again;
  459. }
  460. }
  461. }
  462. OBJINFO *NewObj(LPOLEOBJECT lpobj)
  463. {
  464. OBJINFO *poi;
  465. CleanObjects();
  466. if (poi = FindObj(lpobj))
  467. {
  468. DPRINTF(("NewObj(%lx): Trying to add object twice!", lpobj));
  469. return poi;
  470. }
  471. if (poi = (OBJINFO*)LocalAlloc(LPTR, sizeof(OBJINFO)))
  472. {
  473. poi->lpobj = lpobj;
  474. poi->hwnd = NULL;
  475. poi->hwndDraw = NULL;
  476. SetRectEmpty(&poi->rcDraw);
  477. SetRectEmpty(&poi->rcActivate);
  478. poi->poiNext = poiFirst;
  479. poiFirst = poi;
  480. DPRINTF(("NewObj(%lx): %d objects", lpobj, ++nObjects));
  481. }
  482. else
  483. {
  484. DPRINTF(("NewObj(%lx): Out of room in the object table", lpobj));
  485. }
  486. return poi;
  487. }
  488. /****************************************************************************
  489. ****************************************************************************/
  490. #ifndef WIN32
  491. HWND LookForDC(HWND hwndP, HDC hdc)
  492. {
  493. RECT rc;
  494. DWORD dw;
  495. HWND hwnd;
  496. if (hwndP == NULL)
  497. return NULL;
  498. dw = GetDCOrg(hdc);
  499. for (hwnd = hwndP; hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT))
  500. {
  501. GetClientRect(hwnd, &rc);
  502. ClientToScreen(hwnd, (LPPOINT)&rc);
  503. ClientToScreen(hwnd, (LPPOINT)&rc+1);
  504. if ((int)LOWORD(dw) == rc.left && (int)HIWORD(dw) == rc.top)
  505. return hwnd;
  506. if (PtInRect(&rc, MAKEPOINT(dw)) && (hwndP = GetWindow(hwnd, GW_CHILD)))
  507. if (hwndP = LookForDC(hwndP,hdc))
  508. return hwndP;
  509. }
  510. return NULL;
  511. }
  512. HWND WindowFromDC(HDC hdc)
  513. {
  514. return LookForDC(GetDesktopWindow(), hdc);
  515. }
  516. #endif
  517. /****************************************************************************
  518. ****************************************************************************/
  519. BOOL RectSameSize(LPRECT lprc1, LPRECT lprc2)
  520. {
  521. return lprc1->right - lprc1->left == lprc2->right - lprc2->left &&
  522. lprc1->bottom - lprc1->top == lprc2->bottom - lprc2->top;
  523. }
  524. /****************************************************************************
  525. OleQueryObjPos - this function retuns the last drawn or activated
  526. position of a object
  527. ****************************************************************************/
  528. OLESTATUS FAR PASCAL _LOADDS OleQueryObjPos(
  529. LPOLEOBJECT lpobj, /* object to query */
  530. HWND FAR * lphwnd, /* window of the document containing the object */
  531. LPRECT lprc, /* rect (client cords) of object. */
  532. LPRECT lprcWBounds)/* rect (client cords) of bounding rect. */
  533. {
  534. OBJINFO oi;
  535. //
  536. // we dont do this any more
  537. //
  538. if (lprcWBounds)
  539. SetRectEmpty(lprcWBounds);
  540. //
  541. // because the server side calls this API the passed lpobj is
  542. // a server side LPOLEOBJECT, we can't search our table for this
  543. // object.
  544. //
  545. // this API is only callable by the server during the DoVerb
  546. // server callback
  547. //
  548. //!!! this only works for the last active object!!!!
  549. DPRINTF(("OleQueryObjPos(%lx)", lpobj));
  550. if (RegSetGetData(&oi, FALSE))
  551. {
  552. *lphwnd = oi.hwnd;
  553. // if (IsRectEmpty(&oi.rcActivate))
  554. if (!IsRectEmpty(&oi.rcDraw))
  555. {
  556. DPRINTF(("Using the OleDraw() rectange...."));
  557. //
  558. // use the draw rectangle
  559. //
  560. *lprc = oi.rcDraw;
  561. if (oi.hwndDraw)
  562. {
  563. ClientToScreen(oi.hwndDraw, (LPPOINT)lprc);
  564. ClientToScreen(oi.hwndDraw, (LPPOINT)lprc+1);
  565. }
  566. ScreenToClient(oi.hwnd, (LPPOINT)lprc);
  567. ScreenToClient(oi.hwnd, (LPPOINT)lprc+1);
  568. }
  569. else
  570. {
  571. //
  572. // use the activate rectangle
  573. //
  574. *lprc = oi.rcActivate;
  575. }
  576. if (oi.hwnd && !IsRectEmpty(lprc))
  577. return OLE_OK;
  578. else
  579. return OLE_ERROR_BLANK; // return a error, we dont know about this OBJ
  580. }
  581. else
  582. {
  583. *lphwnd = NULL;
  584. SetRectEmpty(lprc);
  585. return OLE_ERROR_BLANK; // return a error, we dont know about this OBJ
  586. }
  587. }
  588. /****************************************************************************
  589. ****************************************************************************/
  590. OLESTATUS FAR PASCAL _LOADDS DllLoadFromStream (lpstream, lpprotocol, lpclient, lhclientdoc, lpobjname, lplpobj, objType, aClass, cfFormat)
  591. LPOLESTREAM lpstream;
  592. LPSTR lpprotocol;
  593. LPOLECLIENT lpclient;
  594. LHCLIENTDOC lhclientdoc;
  595. LPSTR lpobjname;
  596. LPOLEOBJECT FAR * lplpobj;
  597. LONG objType;
  598. ATOM aClass;
  599. OLECLIPFORMAT cfFormat;
  600. {
  601. OLESTATUS retVal;
  602. DPRINTF(("OleLoadFromStream(%s,%s)", lpprotocol, lpobjname));
  603. retVal = DefLoadFromStream (lpstream, lpprotocol, lpclient,
  604. lhclientdoc, lpobjname, lplpobj,
  605. objType, aClass, cfFormat);
  606. if (retVal <= OLE_WAIT_FOR_RELEASE)
  607. ReplaceFunctions(*lplpobj);
  608. return retVal;
  609. }
  610. /****************************************************************************
  611. ****************************************************************************/
  612. OLESTATUS FAR PASCAL _LOADDS DllCreateFromClip (lpprotocol, lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat, objType)
  613. LPSTR lpprotocol;
  614. LPOLECLIENT lpclient;
  615. LHCLIENTDOC lhclientdoc;
  616. LPSTR lpobjname;
  617. LPOLEOBJECT FAR * lplpobj;
  618. OLEOPT_RENDER optRender;
  619. OLECLIPFORMAT cfFormat;
  620. LONG objType;
  621. {
  622. OLESTATUS retVal;
  623. DPRINTF(("OleCreateFromClip(%s,%s)", lpprotocol, lpobjname));
  624. retVal = DefCreateFromClip (lpprotocol, lpclient,
  625. lhclientdoc, lpobjname, lplpobj,
  626. optRender, cfFormat, objType);
  627. if (retVal <= OLE_WAIT_FOR_RELEASE)
  628. ReplaceFunctions(*lplpobj);
  629. return retVal;
  630. }
  631. /****************************************************************************
  632. ****************************************************************************/
  633. OLESTATUS FAR PASCAL _LOADDS DllCreateLinkFromClip (lpprotocol, lpclient, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat)
  634. LPSTR lpprotocol;
  635. LPOLECLIENT lpclient;
  636. LHCLIENTDOC lhclientdoc;
  637. LPSTR lpobjname;
  638. LPOLEOBJECT FAR * lplpobj;
  639. OLEOPT_RENDER optRender;
  640. OLECLIPFORMAT cfFormat;
  641. {
  642. OLESTATUS retVal;
  643. BOOL bReplace = FALSE;
  644. DPRINTF(("OleCreateLinkFromClip(%s,%s)", lpprotocol, lpobjname));
  645. retVal = DefCreateLinkFromClip (lpprotocol, lpclient,
  646. lhclientdoc, lpobjname, lplpobj,
  647. optRender, cfFormat);
  648. if (retVal <= OLE_WAIT_FOR_RELEASE)
  649. ReplaceFunctions(*lplpobj);
  650. return retVal;
  651. }
  652. /****************************************************************************
  653. ****************************************************************************/
  654. OLESTATUS FAR PASCAL _LOADDS DllCreateFromTemplate (lpprotocol, lpclient, lptemplate, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat)
  655. LPSTR lpprotocol;
  656. LPOLECLIENT lpclient;
  657. LPSTR lptemplate;
  658. LHCLIENTDOC lhclientdoc;
  659. LPSTR lpobjname;
  660. LPOLEOBJECT FAR * lplpobj;
  661. OLEOPT_RENDER optRender;
  662. OLECLIPFORMAT cfFormat;
  663. {
  664. OLESTATUS retVal;
  665. DPRINTF(("OleCreateFromTemplate(%s,%s,%s)", lpprotocol, lptemplate, lpobjname));
  666. retVal = DefCreateFromTemplate (lpprotocol, lpclient, lptemplate,
  667. lhclientdoc, lpobjname, lplpobj,
  668. optRender, cfFormat);
  669. if (retVal <= OLE_WAIT_FOR_RELEASE)
  670. ReplaceFunctions(*lplpobj);
  671. return retVal;
  672. }
  673. /****************************************************************************
  674. ****************************************************************************/
  675. OLESTATUS FAR PASCAL _LOADDS DllCreate (lpprotocol, lpclient, lpclass, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat)
  676. LPSTR lpprotocol;
  677. LPOLECLIENT lpclient;
  678. LPSTR lpclass;
  679. LHCLIENTDOC lhclientdoc;
  680. LPSTR lpobjname;
  681. LPOLEOBJECT FAR * lplpobj;
  682. OLEOPT_RENDER optRender;
  683. OLECLIPFORMAT cfFormat;
  684. {
  685. OLESTATUS retVal;
  686. DPRINTF(("OleCreate(%s,%s,%s)", lpprotocol, lpclass, lpobjname));
  687. retVal = DefCreate (lpprotocol, lpclient, lpclass,
  688. lhclientdoc, lpobjname, lplpobj,
  689. optRender, cfFormat);
  690. if (retVal <= OLE_WAIT_FOR_RELEASE)
  691. ReplaceFunctions(*lplpobj);
  692. return retVal;
  693. }
  694. /****************************************************************************
  695. ****************************************************************************/
  696. OLESTATUS FAR PASCAL _LOADDS DllCreateFromFile (lpprotocol, lpclient, lpclass, lpfile, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat)
  697. LPSTR lpprotocol;
  698. LPOLECLIENT lpclient;
  699. LPSTR lpclass;
  700. LPSTR lpfile;
  701. LHCLIENTDOC lhclientdoc;
  702. LPSTR lpobjname;
  703. LPOLEOBJECT FAR * lplpobj;
  704. OLEOPT_RENDER optRender;
  705. OLECLIPFORMAT cfFormat;
  706. {
  707. OLESTATUS retVal;
  708. DPRINTF(("OleCreateFromFile(%s,%s,%s,%s)", lpprotocol, lpclass, lpfile, lpobjname));
  709. retVal = DefCreateFromFile (lpprotocol, lpclient, lpclass, lpfile,
  710. lhclientdoc, lpobjname, lplpobj,
  711. optRender, cfFormat);
  712. if (retVal <= OLE_WAIT_FOR_RELEASE)
  713. ReplaceFunctions(*lplpobj);
  714. return retVal;
  715. }
  716. /****************************************************************************
  717. ****************************************************************************/
  718. OLESTATUS FAR PASCAL _LOADDS DllCreateLinkFromFile (lpprotocol, lpclient, lpclass, lpfile, lpitem, lhclientdoc, lpobjname, lplpobj, optRender, cfFormat)
  719. LPSTR lpprotocol;
  720. LPOLECLIENT lpclient;
  721. LPSTR lpclass;
  722. LPSTR lpfile;
  723. LPSTR lpitem;
  724. LHCLIENTDOC lhclientdoc;
  725. LPSTR lpobjname;
  726. LPOLEOBJECT FAR * lplpobj;
  727. OLEOPT_RENDER optRender;
  728. OLECLIPFORMAT cfFormat;
  729. {
  730. OLESTATUS retVal;
  731. DPRINTF(("OleCreateLinkFromFile(%s,%s,%s,%s,%s)", lpprotocol, lpclass, lpfile, lpitem, lpobjname));
  732. retVal = DefCreateLinkFromFile (lpprotocol, lpclient,
  733. lpclass, lpfile, lpitem,
  734. lhclientdoc, lpobjname, lplpobj,
  735. optRender, cfFormat);
  736. if (retVal <= OLE_WAIT_FOR_RELEASE)
  737. ReplaceFunctions(*lplpobj);
  738. return retVal;
  739. }
  740. /****************************************************************************
  741. ****************************************************************************/
  742. void ReplaceFunctions(LPOLEOBJECT lpobj)
  743. {
  744. // OBJINFO *poi;
  745. if (!CanReplace(lpobj))
  746. return;
  747. NewObj(lpobj);
  748. //
  749. // get the default handlers
  750. //
  751. if (vtblDef.Draw == NULL) // only get the handlers once!
  752. vtblDef = *lpobj->lpvtbl; // save default handlers
  753. //
  754. // make the OLE object use our handlers
  755. //
  756. lpobj->lpvtbl = (LPOLEOBJECTVTBL)&vtblDll;
  757. //
  758. // init our VTBL, ie replace any handlers we want to override.
  759. // any handlers we dont replace we set the the default ones.
  760. //
  761. vtblDll = vtblDef;
  762. ////(FARPROC)vtblDll.QueryProtocol = (FARPROC)DllQueryProtocol;
  763. ////(FARPROC)vtblDll.Release = (FARPROC)DllRelease;
  764. ////(FARPROC)vtblDll.Show = (FARPROC)DllShow;
  765. ////(FARPROC)vtblDll.DoVerb = (FARPROC)DllDoVerb;
  766. ////(FARPROC)vtblDll.GetData = (FARPROC)DllGetData;
  767. ////(FARPROC)vtblDll.SetData = (FARPROC)DllSetData;
  768. ////(FARPROC)vtblDll.SetTargetDevice = (FARPROC)DllSetTargetDevice;
  769. ////(FARPROC)vtblDll.SetBounds = (FARPROC)DllSetBounds;
  770. ////(FARPROC)vtblDll.EnumFormats = (FARPROC)DllEnumFormats;
  771. ////(FARPROC)vtblDll.SetColorScheme = (FARPROC)DllSetColorScheme;
  772. (FARPROC)vtblDll.Delete = (FARPROC)DllDelete;
  773. ////(FARPROC)vtblDll.SetHostNames = (FARPROC)DllSetHostNames;
  774. ////(FARPROC)vtblDll.SaveToStream = (FARPROC)DllSaveToStream;
  775. (FARPROC)vtblDll.Clone = (FARPROC)DllClone;
  776. (FARPROC)vtblDll.CopyFromLink = (FARPROC)DllCopyFromLink;
  777. ////(FARPROC)vtblDll.Equal = (FARPROC)DllEqual;
  778. ////(FARPROC)vtblDll.CopyToClipboard = (FARPROC)DllCopyToClipboard;
  779. (FARPROC)vtblDll.Draw = (FARPROC)DllDraw;
  780. (FARPROC)vtblDll.Activate = (FARPROC)DllActivate;
  781. ////(FARPROC)vtblDll.Execute = (FARPROC)DllExecute;
  782. ////(FARPROC)vtblDll.Close = (FARPROC)DllClose;
  783. ////(FARPROC)vtblDll.Update = (FARPROC)DllUpdate;
  784. ////(FARPROC)vtblDll.Reconnect = (FARPROC)DllReconnect;
  785. (FARPROC)vtblDll.ObjectConvert = (FARPROC)DllObjectConvert;
  786. ////(FARPROC)vtblDll.GetLinkUpdateOptions = (FARPROC)DllGetLinkUpdateOptions;
  787. ////(FARPROC)vtblDll.SetLinkUpdateOptions = (FARPROC)DllSetLinkUpdateOptions;
  788. ////(FARPROC)vtblDll.Rename = (FARPROC)DllRename;
  789. ////(FARPROC)vtblDll.QueryName = (FARPROC)DllQueryName;
  790. ////(FARPROC)vtblDll.QueryType = (FARPROC)DllQueryType;
  791. ////(FARPROC)vtblDll.QueryBounds = (FARPROC)DllQueryBounds;
  792. ////(FARPROC)vtblDll.QuerySize = (FARPROC)DllQuerySize;
  793. ////(FARPROC)vtblDll.QueryOpen = (FARPROC)DllQueryOpen;
  794. ////(FARPROC)vtblDll.QueryOutOfDate = (FARPROC)DllQueryOutOfDate;
  795. ////(FARPROC)vtblDll.QueryReleaseStatus = (FARPROC)DllQueryReleaseStatus;
  796. ////(FARPROC)vtblDll.QueryReleaseError = (FARPROC)DllQueryReleaseError;
  797. ////(FARPROC)vtblDll.QueryReleaseMethod = (FARPROC)DllQueryReleaseMethod;
  798. ////(FARPROC)vtblDll.RequestData = (FARPROC)DllRequestData;
  799. ////(FARPROC)vtblDll.ObjectLong = (FARPROC)DllObjectLong;
  800. ////(FARPROC)vtblDll.ChangeData = (FARPROC)DllChangeData;
  801. }
  802. /****************************************************************************
  803. ****************************************************************************/
  804. BOOL CanReplace(LPOLEOBJECT lpobj)
  805. {
  806. #if 0 // did not work anyway.
  807. //
  808. // we dont work on the wierd OLE shipped with PenWindows so don't load
  809. //
  810. #ifndef WIN32
  811. #pragma message("Disabling handler because we are on PenWindows...")
  812. #endif //!WIN32
  813. if (GetSystemMetrics(SM_PENWINDOWS))
  814. return FALSE;
  815. #endif
  816. return TRUE;
  817. }
  818. /****************************************************************************
  819. ****************************************************************************/
  820. LPVOID GetData(LPOLEOBJECT lpobj, WORD cf)
  821. {
  822. HANDLE h;
  823. if ( (*vtblDef.GetData)(lpobj, cf, &h) != OLE_OK || h == NULL)
  824. return NULL;
  825. return GlobalLock(h);
  826. }
  827. /****************************************************************************
  828. these are the actual handlers.....
  829. ****************************************************************************/
  830. /****************************************************************************
  831. ****************************************************************************/
  832. LPVOID FAR PASCAL _LOADDS DllQueryProtocol (
  833. LPOLEOBJECT lpobj,
  834. LPSTR lpsz)
  835. {
  836. DPRINTF(("OleQueryProtocol(%ls)", lpsz));
  837. return vtblDef.QueryProtocol(lpobj, lpsz);
  838. }
  839. /****************************************************************************
  840. ****************************************************************************/
  841. OLESTATUS FAR PASCAL _LOADDS DllRelease (
  842. LPOLEOBJECT lpobj)
  843. {
  844. DPRINTF(("OleRelease()"));
  845. return vtblDef.Release(lpobj);
  846. }
  847. /****************************************************************************
  848. ****************************************************************************/
  849. OLESTATUS FAR PASCAL _LOADDS DllShow (
  850. LPOLEOBJECT lpobj,
  851. BOOL fShow)
  852. {
  853. DPRINTF(("OleShow(%d)", fShow));
  854. return vtblDef.Show(lpobj, fShow);
  855. }
  856. /****************************************************************************
  857. ****************************************************************************/
  858. OLESTATUS FAR PASCAL _LOADDS DllDoVerb (
  859. LPOLEOBJECT lpobj,
  860. UINT verb,
  861. BOOL fShow,
  862. BOOL fActivate)
  863. {
  864. DPRINTF(("OleDoVerb(%d, %d, %d)", verb, fShow, fActivate));
  865. return vtblDef.DoVerb(lpobj, verb, fShow, fActivate);
  866. }
  867. /****************************************************************************
  868. ****************************************************************************/
  869. OLESTATUS FAR PASCAL _LOADDS DllGetData (
  870. LPOLEOBJECT lpobj,
  871. OLECLIPFORMAT cf,
  872. LPHANDLE lph)
  873. {
  874. DPRINTF(("OleGetData(%d)", cf));
  875. return vtblDef.GetData(lpobj, cf, lph);
  876. }
  877. /****************************************************************************
  878. ****************************************************************************/
  879. OLESTATUS FAR PASCAL _LOADDS DllSetData (
  880. LPOLEOBJECT lpobj,
  881. OLECLIPFORMAT cf,
  882. HANDLE h)
  883. {
  884. DPRINTF(("OleSetData(%d, %d)", cf, h));
  885. return vtblDef.SetData(lpobj, cf, h);
  886. }
  887. /****************************************************************************
  888. ****************************************************************************/
  889. OLESTATUS FAR PASCAL _LOADDS DllSetTargetDevice (
  890. LPOLEOBJECT lpobj,
  891. HANDLE h)
  892. {
  893. DPRINTF(("OleSetTargetDevice()"));
  894. return vtblDef.SetTargetDevice(lpobj, h);
  895. }
  896. /****************************************************************************
  897. ****************************************************************************/
  898. OLESTATUS FAR PASCAL _LOADDS DllSetBounds (
  899. LPOLEOBJECT lpobj,
  900. LPRECT lprc)
  901. {
  902. DPRINTF(("OleSetBounds([%d,%d,%d,%d])", PUSHRC(lprc)));
  903. return vtblDef.SetBounds(lpobj, lprc);
  904. }
  905. /****************************************************************************
  906. ****************************************************************************/
  907. OLECLIPFORMAT FAR PASCAL _LOADDS DllEnumFormats (
  908. LPOLEOBJECT lpobj,
  909. OLECLIPFORMAT cf)
  910. {
  911. DPRINTF(("OleEnumFormats(%d)", cf));
  912. return vtblDef.EnumFormats(lpobj, cf);
  913. }
  914. /****************************************************************************
  915. ****************************************************************************/
  916. OLESTATUS FAR PASCAL _LOADDS DllSetColorScheme (
  917. LPOLEOBJECT lpobj,
  918. LPLOGPALETTE lppal)
  919. {
  920. DPRINTF(("OleSetColorScheme()"));
  921. return vtblDef.SetColorScheme(lpobj, lppal);
  922. }
  923. /****************************************************************************
  924. ****************************************************************************/
  925. OLESTATUS FAR PASCAL _LOADDS DllDelete (
  926. LPOLEOBJECT lpobj)
  927. {
  928. DPRINTF(("OleDelete(%lx)", lpobj));
  929. DelObj(lpobj);
  930. CleanObjects();
  931. return vtblDef.Delete(lpobj);
  932. }
  933. /****************************************************************************
  934. ****************************************************************************/
  935. OLESTATUS FAR PASCAL _LOADDS DllSetHostNames (
  936. LPOLEOBJECT lpobj,
  937. LPSTR szClientName,
  938. LPSTR szDocName)
  939. {
  940. DPRINTF(("OleSetHostNames(%ls,%ls)", szClientName, szDocName));
  941. return vtblDef.SetHostNames(lpobj, szClientName, szDocName);
  942. }
  943. /****************************************************************************
  944. ****************************************************************************/
  945. OLESTATUS FAR PASCAL _LOADDS DllSaveToStream (
  946. LPOLEOBJECT lpobj,
  947. LPOLESTREAM lpstream)
  948. {
  949. DPRINTF(("OleSaveToStream()"));
  950. return vtblDef.SaveToStream(lpobj, lpstream);
  951. }
  952. /****************************************************************************
  953. ****************************************************************************/
  954. OLESTATUS FAR PASCAL _LOADDS DllClone (
  955. LPOLEOBJECT lpobj,
  956. LPOLECLIENT lpClient,
  957. LHCLIENTDOC lhClientDoc,
  958. LPSTR szObjName,
  959. LPOLEOBJECT FAR*lplpobj)
  960. {
  961. OLESTATUS err;
  962. DPRINTF(("OleClone(%ls)", szObjName));
  963. err = vtblDef.Clone(lpobj, lpClient, lhClientDoc, szObjName, lplpobj);
  964. //
  965. // if the object cloned correctly then clone our object information
  966. //
  967. if (err <= OLE_WAIT_FOR_RELEASE)
  968. {
  969. OBJINFO *poi, *poiT;
  970. if ((poiT = FindObj(lpobj)) && (poi = NewObj(NULL)))
  971. {
  972. poi->lpobj = *lplpobj;
  973. poi->hwnd = poiT->hwnd;
  974. poi->rcActivate = poiT->rcActivate;
  975. poi->hwndDraw = poiT->hwndDraw;
  976. poi->rcDraw = poiT->rcDraw;
  977. }
  978. }
  979. return err;
  980. }
  981. /****************************************************************************
  982. ****************************************************************************/
  983. OLESTATUS FAR PASCAL _LOADDS DllCopyFromLink (
  984. LPOLEOBJECT lpobj,
  985. LPOLECLIENT lpClient,
  986. LHCLIENTDOC lhClientDoc,
  987. LPSTR szObjName,
  988. LPOLEOBJECT FAR*lplpobj)
  989. {
  990. OLESTATUS err;
  991. DPRINTF(("OleCopyFromLink(%ls)", szObjName));
  992. err = vtblDef.CopyFromLink(lpobj, lpClient, lhClientDoc, szObjName, lplpobj);
  993. if (err <= OLE_WAIT_FOR_RELEASE)
  994. NewObj(*lplpobj);
  995. return err;
  996. }
  997. /****************************************************************************
  998. ****************************************************************************/
  999. OLESTATUS FAR PASCAL _LOADDS DllEqual (
  1000. LPOLEOBJECT lpobj1,
  1001. LPOLEOBJECT lpobj2)
  1002. {
  1003. DPRINTF(("OleEqual()"));
  1004. return vtblDef.Equal(lpobj1, lpobj2);
  1005. }
  1006. /****************************************************************************
  1007. ****************************************************************************/
  1008. OLESTATUS FAR PASCAL _LOADDS DllCopyToClipboard (
  1009. LPOLEOBJECT lpobj)
  1010. {
  1011. DPRINTF(("OleCopyToClipboard()"));
  1012. return vtblDef.CopyToClipboard(lpobj);
  1013. }
  1014. /****************************************************************************
  1015. ****************************************************************************/
  1016. OLESTATUS FAR PASCAL _LOADDS DllDraw (
  1017. LPOLEOBJECT lpobj,
  1018. HDC hdc,
  1019. LPRECT lprcBounds,
  1020. LPRECT lprcWBounds,
  1021. HDC hdcFormat)
  1022. {
  1023. OBJINFO *poi;
  1024. RECT rc;
  1025. DPRINTF(("OleDraw(%lx,[%d,%d,%d,%d], [%d,%d,%d,%d])", lpobj, PUSHRC(lprcBounds), PUSHRC(lprcWBounds)));
  1026. #ifdef DEBUG
  1027. if (OleIsDcMeta(hdc))
  1028. DPRINTF(("OleDraw: drawing to a meta-file"));
  1029. else if (IsDcMemory(hdc))
  1030. DPRINTF(("OleDraw: drawing to a bitmap"));
  1031. #endif
  1032. if ((poi = FindObj(lpobj)) && !OleIsDcMeta(hdc) && !IsDcMemory(hdc))
  1033. {
  1034. //!!!get the window from the HDC!!!
  1035. poi->hwndDraw = WindowFromDC(hdc);
  1036. DPRINTF(("OleDraw: hwndDraw = %04X", poi->hwndDraw));
  1037. if (lprcBounds && !IsRectEmpty(lprcBounds))
  1038. {
  1039. poi->rcDraw = *lprcBounds;
  1040. //
  1041. // convert the bound rectange into coordinates.
  1042. // relative to hwndDraw
  1043. //
  1044. LPtoDP(hdc, (LPPOINT)&poi->rcDraw, 2);
  1045. if (poi->hwndDraw == NULL)
  1046. {
  1047. #ifdef WIN32
  1048. POINT pTemp;
  1049. if (GetDCOrgEx(hdc, &pTemp)) {
  1050. OffsetRect(&poi->rcDraw, pTemp.x, pTemp.y);
  1051. }
  1052. #else
  1053. DWORD dw;
  1054. dw = GetDCOrg(hdc);
  1055. OffsetRect(&poi->rcDraw, LOWORD(dw), HIWORD(dw));
  1056. #endif
  1057. }
  1058. }
  1059. if (GetClipBox(hdc, &rc) == NULLREGION)
  1060. return OLE_OK;
  1061. }
  1062. return vtblDef.Draw(lpobj, hdc, lprcBounds, lprcWBounds, hdcFormat);
  1063. }
  1064. /****************************************************************************
  1065. scan WinWords stack and "extract" the info it should have passed to
  1066. OleActivate() this has been tested with WinWord 2.0 and 2.0a.
  1067. we expect future verisons of WinWord to pass the correct info to
  1068. OleActivate() so we will never get here.
  1069. ****************************************************************************/
  1070. #ifndef WIN32
  1071. BOOL NEAR PASCAL GetOpusRect(LPRECT lprcBound)
  1072. {
  1073. LPRECT lprc;
  1074. LPVOID lp;
  1075. int i,dx,dy;
  1076. //
  1077. // see if the current app is WinWord
  1078. //
  1079. if (!IsApp("WINWORD.EXE"))
  1080. return FALSE;
  1081. //
  1082. // lets scan the stack looking for a RECT, this is a total
  1083. // hack to get MSWORD to work.
  1084. //
  1085. _asm
  1086. {
  1087. mov bx,ss:[bp] ; get saved BP DllActivate()
  1088. and bx, not 1
  1089. mov bx,ss:[bx] ; get saved saved BP OleActivate()
  1090. and bx, not 1
  1091. mov bx,ss:[bx] ; get saved saved saved BP "winword"
  1092. and bx, not 1
  1093. mov word ptr lp[0], bx
  1094. mov word ptr lp[2], ss
  1095. }
  1096. #ifdef DEBUG
  1097. DPRINTF(("****** SCANING WINWORDs STACK ********"));
  1098. lprc = lp;
  1099. for (i=0; i<1000; i++)
  1100. {
  1101. dx = lprc->right - lprc->left;
  1102. dy = lprc->bottom - lprc->top;
  1103. if (dx >= 158 && dx <= 162 &&
  1104. dy >= 118 && dy <= 122)
  1105. {
  1106. DPRINTF(("found a RECT at offset %d, [%d, %d, %d, %d]",
  1107. (LPBYTE)lprc - (LPBYTE)lp, PUSHRC(lprc)));
  1108. }
  1109. ((LPBYTE)lprc)++;
  1110. }
  1111. DPRINTF(("**************************************"));
  1112. #endif
  1113. lprc = (LPRECT)((LPBYTE)lp + 6);
  1114. if (lprc->right - lprc->left > 0 && lprc->bottom - lprc->top > 0)
  1115. {
  1116. DPRINTF(("*** HACK FOR WINWORD, [%d, %d, %d, %d]", PUSHRC(lprc)));
  1117. *lprcBound = *lprc;
  1118. return TRUE;
  1119. }
  1120. return FALSE;
  1121. }
  1122. #endif //!WIN32
  1123. #ifdef WIN32
  1124. /*
  1125. ** This is a pointer to the currently playing ole object. It is only
  1126. ** valid in the context of the client application.
  1127. **
  1128. */
  1129. LPOLEOBJECT lpobjPlaying;
  1130. HWND hwndOleServer;
  1131. /*
  1132. ** These are the process and thread ID's of the currently
  1133. ** playing client application. These variables have the value 0 in all
  1134. ** other applications.
  1135. **
  1136. */
  1137. DWORD dwProcessIDPlaying;
  1138. #endif
  1139. /****************************************************************************
  1140. Note the use of a BOOL to pass an HWND in this fine piece of code...
  1141. ****************************************************************************/
  1142. OLESTATUS FAR PASCAL _LOADDS DllActivate (
  1143. LPOLEOBJECT lpobj,
  1144. WORD verb,
  1145. BOOL fShow,
  1146. BOOL fActivate,
  1147. HWND hwnd,
  1148. LPRECT lprcBound)
  1149. {
  1150. OBJINFO *poi;
  1151. RECT rc;
  1152. DPRINTF(("OleActivate(%lx, %d, %d, %d, %04X, [%d,%d,%d,%d])", lpobj, verb, fShow, fActivate, hwnd, PUSHRC(lprcBound)));
  1153. #ifdef WIN32
  1154. lpobjPlaying = lpobj;
  1155. dwProcessIDPlaying = GetCurrentProcessId();
  1156. #endif
  1157. //
  1158. // hack for Write
  1159. //
  1160. if (IsWindow((HWND)(UINT_PTR)fActivate))
  1161. {
  1162. DPRINTF(("OleActivate: Write pre-realase work around"));
  1163. hwnd = (HWND)(UINT_PTR)fActivate;
  1164. fActivate = TRUE;
  1165. }
  1166. if (poi = FindObj(lpobj))
  1167. {
  1168. poi->hwnd = hwnd;
  1169. if (poi->hwnd == NULL)
  1170. {
  1171. if (GetFocus())
  1172. {
  1173. DPRINTF(("OleActivate: no window specifed, using the focus window"));
  1174. poi->hwnd = GetFocus();
  1175. }
  1176. else
  1177. {
  1178. DPRINTF(("OleActivate: no window specifed, using the active window"));
  1179. poi->hwnd = GetActiveWindow();
  1180. }
  1181. }
  1182. if (lprcBound && !IsRectEmpty(lprcBound))
  1183. {
  1184. poi->rcActivate = *lprcBound;
  1185. }
  1186. #ifndef WIN32
  1187. else
  1188. {
  1189. GetOpusRect(&poi->rcActivate);
  1190. }
  1191. #endif //!WIN32
  1192. //
  1193. // MS-Publisher gives use the *wrong* rectangle in the OleActivate call
  1194. // and never calls OleDraw() we are hosed!
  1195. //
  1196. // so we check if the rect is off in space, and dont use it if so.
  1197. //
  1198. if (poi->hwnd)
  1199. {
  1200. GetClientRect(poi->hwnd, &rc);
  1201. IntersectRect(&rc,&rc,&poi->rcActivate);
  1202. if (IsRectEmpty(&rc))
  1203. {
  1204. DPRINTF(("OleActivate: rectangle specifed is not valid"));
  1205. SetRectEmpty(&poi->rcActivate);
  1206. }
  1207. }
  1208. if (IsRectEmpty(&poi->rcActivate))
  1209. {
  1210. DPRINTF(("OleActivate: stupid ole app!!!"));
  1211. }
  1212. //
  1213. // Shove it in the registry
  1214. //
  1215. {
  1216. RegSetGetData(poi, TRUE);
  1217. }
  1218. }
  1219. return vtblDef.Activate(lpobj, verb, fShow, fActivate, hwnd, lprcBound);
  1220. }
  1221. /****************************************************************************
  1222. ****************************************************************************/
  1223. OLESTATUS FAR PASCAL _LOADDS DllExecute (
  1224. LPOLEOBJECT lpobj,
  1225. HANDLE hCmds,
  1226. WORD reserved)
  1227. {
  1228. DPRINTF(("OleExecute(%ls)", GlobalLock(hCmds)));
  1229. return vtblDef.Execute(lpobj, hCmds, reserved);
  1230. }
  1231. /****************************************************************************
  1232. ****************************************************************************/
  1233. OLESTATUS FAR PASCAL _LOADDS DllClose (
  1234. LPOLEOBJECT lpobj)
  1235. {
  1236. DPRINTF(("OleClose(%lx)", lpobj));
  1237. ////DelObj(lpobj);
  1238. return vtblDef.Close(lpobj);
  1239. }
  1240. /****************************************************************************
  1241. ****************************************************************************/
  1242. OLESTATUS FAR PASCAL _LOADDS DllUpdate (
  1243. LPOLEOBJECT lpobj)
  1244. {
  1245. DPRINTF(("OleUpdate()"));
  1246. return vtblDef.Update(lpobj);
  1247. }
  1248. /****************************************************************************
  1249. ****************************************************************************/
  1250. OLESTATUS FAR PASCAL _LOADDS DllReconnect (
  1251. LPOLEOBJECT lpobj)
  1252. {
  1253. DPRINTF(("OleReconnect()"));
  1254. return vtblDef.Reconnect(lpobj);
  1255. }
  1256. /****************************************************************************
  1257. ****************************************************************************/
  1258. OLESTATUS FAR PASCAL _LOADDS DllObjectConvert (
  1259. LPOLEOBJECT lpobj,
  1260. LPSTR szProtocol,
  1261. LPOLECLIENT lpClient,
  1262. LHCLIENTDOC lhClientDoc,
  1263. LPSTR szObjName,
  1264. LPOLEOBJECT FAR*lplpobj)
  1265. {
  1266. OLESTATUS err;
  1267. DPRINTF(("OleObjectConvert(%ls,%ls)", szProtocol, szObjName));
  1268. err = vtblDef.ObjectConvert(lpobj, szProtocol, lpClient, lhClientDoc, szObjName, lplpobj);
  1269. if (err <= OLE_WAIT_FOR_RELEASE)
  1270. NewObj(*lplpobj);
  1271. return err;
  1272. }
  1273. /****************************************************************************
  1274. ****************************************************************************/
  1275. OLESTATUS FAR PASCAL _LOADDS DllGetLinkUpdateOptions (
  1276. LPOLEOBJECT lpobj,
  1277. OLEOPT_UPDATE FAR *lpoleopt)
  1278. {
  1279. DPRINTF(("OleGetLinkUpdateOptions()"));
  1280. return vtblDef.GetLinkUpdateOptions(lpobj, lpoleopt);
  1281. }
  1282. /****************************************************************************
  1283. ****************************************************************************/
  1284. OLESTATUS FAR PASCAL _LOADDS DllSetLinkUpdateOptions (
  1285. LPOLEOBJECT lpobj,
  1286. OLEOPT_UPDATE oleopt)
  1287. {
  1288. DPRINTF(("OleSetLinkUpdateOptions()"));
  1289. return vtblDef.SetLinkUpdateOptions(lpobj, oleopt);
  1290. }
  1291. /****************************************************************************
  1292. ****************************************************************************/
  1293. OLESTATUS FAR PASCAL _LOADDS DllRename (
  1294. LPOLEOBJECT lpobj,
  1295. LPSTR szName)
  1296. {
  1297. DPRINTF(("OleRename(%ls)", szName));
  1298. return vtblDef.Rename(lpobj, szName);
  1299. }
  1300. /****************************************************************************
  1301. ****************************************************************************/
  1302. OLESTATUS FAR PASCAL _LOADDS DllQueryName (
  1303. LPOLEOBJECT lpobj,
  1304. LPSTR szObjName,
  1305. UINT FAR * lpwSize)
  1306. {
  1307. DPRINTF(("OleQueryName(%ls)", szObjName));
  1308. return vtblDef.QueryName(lpobj, szObjName, lpwSize);
  1309. }
  1310. /****************************************************************************
  1311. ****************************************************************************/
  1312. OLESTATUS FAR PASCAL _LOADDS DllQueryType (
  1313. LPOLEOBJECT lpobj,
  1314. LPLONG lpType)
  1315. {
  1316. DPRINTF(("OleQueryType()"));
  1317. return vtblDef.QueryType(lpobj, lpType);
  1318. }
  1319. /****************************************************************************
  1320. ****************************************************************************/
  1321. OLESTATUS FAR PASCAL _LOADDS DllQueryBounds (
  1322. LPOLEOBJECT lpobj,
  1323. LPRECT lprc)
  1324. {
  1325. DPRINTF(("OleQueryBounds()"));
  1326. return vtblDef.QueryBounds(lpobj, lprc);
  1327. }
  1328. /****************************************************************************
  1329. ****************************************************************************/
  1330. OLESTATUS FAR PASCAL _LOADDS DllQuerySize (
  1331. LPOLEOBJECT lpobj,
  1332. DWORD FAR * lpdwSize)
  1333. {
  1334. DPRINTF(("OleQuerySize()"));
  1335. return vtblDef.QuerySize(lpobj, lpdwSize);
  1336. }
  1337. /****************************************************************************
  1338. ****************************************************************************/
  1339. OLESTATUS FAR PASCAL _LOADDS DllQueryOpen (
  1340. LPOLEOBJECT lpobj)
  1341. {
  1342. DPRINTF(("OleQueryOpen()"));
  1343. return vtblDef.QueryOpen(lpobj);
  1344. }
  1345. /****************************************************************************
  1346. ****************************************************************************/
  1347. OLESTATUS FAR PASCAL _LOADDS DllQueryOutOfDate (
  1348. LPOLEOBJECT lpobj)
  1349. {
  1350. DPRINTF(("OleQueryOutOfDate()"));
  1351. return vtblDef.QueryOutOfDate(lpobj);
  1352. }
  1353. /****************************************************************************
  1354. ****************************************************************************/
  1355. OLESTATUS FAR PASCAL _LOADDS DllQueryReleaseStatus (
  1356. LPOLEOBJECT lpobj)
  1357. {
  1358. DPRINTF(("OleQueryReleaseStatus()"));
  1359. return vtblDef.QueryReleaseStatus(lpobj);
  1360. }
  1361. /****************************************************************************
  1362. ****************************************************************************/
  1363. OLESTATUS FAR PASCAL _LOADDS DllQueryReleaseError (
  1364. LPOLEOBJECT lpobj)
  1365. {
  1366. DPRINTF(("OleQueryReleaseError()"));
  1367. return vtblDef.QueryReleaseError(lpobj);
  1368. }
  1369. /****************************************************************************
  1370. ****************************************************************************/
  1371. OLESTATUS FAR PASCAL _LOADDS DllRequestData (
  1372. LPOLEOBJECT lpobj,
  1373. OLECLIPFORMAT cf)
  1374. {
  1375. DPRINTF(("OleRequestData(%d)", cf));
  1376. return vtblDef.RequestData(lpobj, cf);
  1377. }
  1378. /****************************************************************************
  1379. ****************************************************************************/
  1380. OLESTATUS FAR PASCAL _LOADDS DllObjectLong (
  1381. LPOLEOBJECT lpobj,
  1382. UINT u,
  1383. LPLONG lpl)
  1384. {
  1385. DPRINTF(("OleObjectLong()"));
  1386. return vtblDef.ObjectLong(lpobj, u, lpl);
  1387. }
  1388. /****************************************************************************
  1389. ****************************************************************************/
  1390. OLE_RELEASE_METHOD FAR PASCAL _LOADDS DllQueryReleaseMethod (
  1391. LPOLEOBJECT lpobj)
  1392. {
  1393. DPRINTF(("OleQueryReleaseMethod()"));
  1394. return vtblDef.QueryReleaseMethod(lpobj);
  1395. }
  1396. /****************************************************************************
  1397. ****************************************************************************/
  1398. OLESTATUS FAR PASCAL _LOADDS DllChangeData (
  1399. LPOLEOBJECT lpobj,
  1400. HANDLE h,
  1401. LPOLECLIENT lpClient,
  1402. BOOL f)
  1403. {
  1404. DPRINTF(("OleChangeData()"));
  1405. return vtblDef.ChangeData(lpobj, h, lpClient, f);
  1406. }
  1407. ///////////////////////////////////////////////////////////////////////////////
  1408. //
  1409. // DEBUG STUFF
  1410. //
  1411. ///////////////////////////////////////////////////////////////////////////////
  1412. #ifdef DEBUG
  1413. #ifndef WIN32
  1414. void FAR cdecl dprintf(LPSTR szFormat, ...)
  1415. {
  1416. char ach[128];
  1417. va_list va;
  1418. extern FAR PASCAL OutputDebugStr(LPSTR);
  1419. lstrcpy(ach, "MCIOLE: ");
  1420. va_start (va, szFormat);
  1421. wvsprintf(ach + 8,szFormat,va);
  1422. va_end (va);
  1423. lstrcat(ach,"\r\n");
  1424. OutputDebugString(ach);
  1425. }
  1426. #else //!WIN32
  1427. /*
  1428. *
  1429. * In theory I need to include STDARGS and STDIO, but I don't get any warnings
  1430. * That was because the debug output stuff was never enabled (DBG/DEBUG ...)
  1431. *
  1432. */
  1433. void FAR cdecl dprintf(LPSTR szFormat, ...)
  1434. {
  1435. char ach[128];
  1436. int s;
  1437. va_list va;
  1438. if (oleDebugLevel == 0 ) {
  1439. return;
  1440. }
  1441. va_start(va, szFormat);
  1442. s = sprintf( ach, "MCIOLE32: (tid %x) ", GetCurrentThreadId() );
  1443. s += vsprintf (ach+s,szFormat, va);
  1444. va_end(va);
  1445. ach[s++] = '\n';
  1446. ach[s] = 0;
  1447. OutputDebugString(ach);
  1448. }
  1449. #endif //WIN32
  1450. #endif
  1451. #ifdef WIN32
  1452. /*****************************************************************************\
  1453. **
  1454. ** Stuff to support mouse HookProc
  1455. **
  1456. \*****************************************************************************/
  1457. #ifdef USE_MOUSE_HOOK
  1458. LRESULT CALLBACK MouseHook( int hc, WPARAM wParam, LPARAM lParam );
  1459. #else
  1460. LONG_PTR CALLBACK GetMessageHook( int hc, WPARAM wParam, LPARAM lParam );
  1461. #endif
  1462. BOOL InstallHook( HWND hwndServer, DWORD wow_thread_id );
  1463. BOOL RemoveHook( VOID );
  1464. /*
  1465. ** hHookMouse is the handle to the hook proc. This global is only
  1466. ** valid in the context of the process that installed the hook (mplay32.exe).
  1467. ** In all other address spaces this value is null.
  1468. **
  1469. */
  1470. HHOOK hHookMouse = NULL;
  1471. /*****************************************************************************\
  1472. ** InstallHook
  1473. **
  1474. ** Called from mplay32.exe to install a global HookProc. Returning
  1475. ** TRUE means everything worked OK. This should only be card from mplay32.
  1476. **
  1477. \*****************************************************************************/
  1478. BOOL InstallHook( HWND hwndServer, DWORD wow_thread_id )
  1479. {
  1480. DPRINTF(( "Install hook to thread ID = %x", wow_thread_id ));
  1481. if ( wow_thread_id ) {
  1482. /*
  1483. ** Get a pointer to file mapped shared memory.
  1484. */
  1485. lpvMem = MapViewOfFile( hMapObject, FILE_MAP_WRITE, 0, 0, 0 );
  1486. if (lpvMem == NULL) {
  1487. return FALSE;
  1488. }
  1489. lpvMem->hwndServer = hwndServer;
  1490. lpvMem->wow_app_thread_id = wow_thread_id;
  1491. }
  1492. //
  1493. // Set the thread id for WOW. In principle this means that
  1494. // we don't need to give WOW the thread id since the hook should
  1495. // only run on this thread.
  1496. //
  1497. // For some reason specifying the thread helps give WOW enough
  1498. // cycles to actually process the hook proc (if we don't specify it
  1499. // we don't ever get in with a mouse click to cancel the play).
  1500. //
  1501. #ifdef USE_MOUSE_HOOK
  1502. hHookMouse = SetWindowsHookEx( WH_MOUSE, MouseHook,
  1503. GetModuleHandle( "mciole32" ),
  1504. wow_thread_id );
  1505. #else
  1506. hHookMouse = SetWindowsHookEx( WH_GETMESSAGE, GetMessageHook,
  1507. GetModuleHandle( "mciole32" ),
  1508. wow_thread_id );
  1509. #endif
  1510. DPRINTF(( "Mouse hook %s", hHookMouse ? "installed" : "failed" ));
  1511. return hHookMouse != NULL;
  1512. }
  1513. /*****************************************************************************\
  1514. ** RemoveHook
  1515. **
  1516. ** Called from mplay32.exe to remove a global HookProc. Returning TRUE
  1517. ** means everything worked OK.
  1518. **
  1519. \*****************************************************************************/
  1520. BOOL RemoveHook( VOID )
  1521. {
  1522. BOOL fRemove;
  1523. fRemove = UnhookWindowsHookEx( hHookMouse );
  1524. DPRINTF(( "RemoveMouseHook %s", fRemove ? "removed" : "error" ));
  1525. if (lpvMem != NULL) {
  1526. DPRINTF(( "Thread ID = %x", lpvMem->wow_app_thread_id ));
  1527. lpvMem->hwndServer = (HWND)NULL;
  1528. lpvMem->wow_app_thread_id = 0L;
  1529. }
  1530. return fRemove;
  1531. }
  1532. #ifdef USE_MOUSE_HOOK
  1533. /*****************************************************************************\
  1534. ** MouseHook
  1535. **
  1536. ** Global mouse hook proc called whenever anything happens to the mouse.
  1537. **
  1538. \*****************************************************************************/
  1539. LRESULT CALLBACK MouseHook( int hc, WPARAM wParam, LPARAM lParam )
  1540. {
  1541. LPMOUSEHOOKSTRUCT lpmh = (LPVOID)lParam;
  1542. UINT message = (UINT)wParam;
  1543. if (hc == HC_ACTION) {
  1544. /*
  1545. ** Are we being called in the context of the client thats
  1546. ** currently playing ?
  1547. */
  1548. // DPRINTF(( "Mouse hook called <%x>", message ));
  1549. if ( dwProcessIDPlaying == GetCurrentProcessId() ) {
  1550. /*
  1551. ** If the left or right button is down always stop the
  1552. ** play on place.
  1553. */
  1554. if ( message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ) {
  1555. DPRINTF(( "Stopping play in place" ));
  1556. vtblDef.Close( lpobjPlaying );
  1557. }
  1558. /*
  1559. ** If the Non-client left or right button is down AND the user
  1560. ** is not clicking on the title bar (called a caption in Windows)
  1561. ** stop the play in place.
  1562. */
  1563. else if ( message == WM_NCLBUTTONDOWN
  1564. || message == WM_NCRBUTTONDOWN ) {
  1565. if ( lpmh->wHitTestCode != HTCAPTION ) {
  1566. DPRINTF(( "Stopping play in place" ));
  1567. vtblDef.Close( lpobjPlaying );
  1568. }
  1569. }
  1570. }
  1571. }
  1572. /*
  1573. ** Chain to the next hook proc. The use of hHookMouse below is not an
  1574. ** error, this code gets executed in the context many different
  1575. ** processes. The global hHookMouse is only valid on the process that
  1576. ** installed the hook (mplay32.exe), otherwise it contains null.
  1577. ** ScottLu tells me that this is correct behaviour for a global hook
  1578. ** proc.
  1579. */
  1580. return CallNextHookEx( hHookMouse, hc, wParam, lParam );
  1581. }
  1582. #else
  1583. /*****************************************************************************\
  1584. ** GetMessageHook
  1585. **
  1586. ** Global GetMessageHook hook proc called whenever a message is removed from
  1587. ** a message queue.
  1588. **
  1589. \*****************************************************************************/
  1590. LONG_PTR CALLBACK GetMessageHook( int hc, WPARAM wParam, LPARAM lParam )
  1591. {
  1592. LPMSG lpmh = (LPVOID)lParam;
  1593. UINT message = lpmh->message;
  1594. if (hc == HC_ACTION) {
  1595. /*
  1596. ** Are we being called in the context of the client thats
  1597. ** currently playing ?
  1598. */
  1599. if ( dwProcessIDPlaying == GetCurrentProcessId() ) {
  1600. /*
  1601. ** If the left or right button is down always stop the
  1602. ** play on place.
  1603. */
  1604. if ( message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ) {
  1605. DPRINTF(( "Stopping play in place" ));
  1606. vtblDef.Close( lpobjPlaying );
  1607. }
  1608. /*
  1609. ** If the Non-client left or right button is down AND the user
  1610. ** is not clicking on the title bar (called a caption in Windows)
  1611. ** stop the play in place.
  1612. */
  1613. else if ( message == WM_NCLBUTTONDOWN
  1614. || message == WM_NCRBUTTONDOWN ) {
  1615. if ( lpmh->wParam != (WPARAM)HTCAPTION ) {
  1616. DPRINTF(( "Stopping play in place" ));
  1617. vtblDef.Close( lpobjPlaying );
  1618. }
  1619. }
  1620. }
  1621. /*
  1622. ** If we are running in WOW and the thread Ids match we have to
  1623. ** stop the play in place by sending a private message to mplay32.exe
  1624. */
  1625. else if ( lpvMem != NULL && fRunningInWOW ) {
  1626. if ( lpvMem->wow_app_thread_id == GetCurrentThreadId() ) {
  1627. /*
  1628. ** If the left or right button is down always stop the
  1629. ** play on place.
  1630. */
  1631. if ( message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN ) {
  1632. DPRINTF(( "Stopping WOW play in place" ));
  1633. SendMessage( lpvMem->hwndServer, WM_USER+500, 0L, 0L );
  1634. }
  1635. /*
  1636. ** If the Non-client left or right button is down AND the user
  1637. ** is not clicking on the title bar (called a caption in Windows)
  1638. ** stop the play in place.
  1639. */
  1640. else if ( message == WM_NCLBUTTONDOWN
  1641. || message == WM_NCRBUTTONDOWN ) {
  1642. if ( lpmh->wParam != (WPARAM)HTCAPTION ) {
  1643. DPRINTF(( "Stopping WOW play in place" ));
  1644. SendMessage( lpvMem->hwndServer, WM_USER+500, 0L, 0L );
  1645. }
  1646. }
  1647. }
  1648. }
  1649. }
  1650. /*
  1651. ** Chain to the next hook proc. The use of hHookMouse below is not an
  1652. ** error, this code gets executed in the context many different
  1653. ** processes. The global hHookMouse is only valid on the process that
  1654. ** installed the hook (mplay32.exe), otherwise it contains null.
  1655. ** ScottLu tells me that this is correct behaviour for a global hook
  1656. ** proc.
  1657. */
  1658. return CallNextHookEx( hHookMouse, hc, wParam, lParam );
  1659. }
  1660. #endif
  1661. #endif