Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1177 lines
43 KiB

  1. /*
  2. * object.c - OLE object support routines
  3. *
  4. * Created by Microsoft Corporation.
  5. * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  6. */
  7. //*** INCLUDES ****
  8. #include <windows.h> //* WINDOWS
  9. #include <shellapi.h> //* SHELL
  10. #include <ole.h> //* OLE
  11. #include "global.h" //* global variables and structures
  12. #include "stream.h" //* application includes:
  13. #include "dialog.h"
  14. #include "object.h"
  15. #include "clidemo.h"
  16. #include "demorc.h"
  17. #include "utility.h"
  18. #include "register.h"
  19. #define HIMETRIC_PER_INCH 2540
  20. //*** VARIABLES ***
  21. //*** Globals
  22. INT cOleWait = 0;
  23. INT giXppli ;
  24. INT giYppli ;
  25. /***************************************************************************
  26. * CallBack()
  27. *
  28. * This routine will be called whenever an object has been changed,
  29. * saved, renamed, is being painted, or an asynchronous operation has
  30. * completed. This routine is called by the OLE client DLL in the
  31. * above situations. A pointer to this function is kept in the client
  32. * vtbl. It is our obligation as a client application to insure that a
  33. * pointer to this procedure is in the vtbl.
  34. *
  35. * IMMPORTANT: notice that we are posting messages here rather that doing
  36. * the work right away. Well, this is done to avoid any possibility of
  37. * getting into another dispatch message loop. A MessageBox woul do this!
  38. *
  39. * Returns int - see below
  40. *
  41. * The return value is generally ignored, except for these notifications:
  42. * OLE_QUERY_PAINT and OLE_QUERY_RETRY. For these two notifications,
  43. * returning TRUE means continue the current operation(eg painting or retry)
  44. * Returning FALSE means stop the current operation. This is useful as an
  45. * object which takes a long time to paint can be interrupted in order to
  46. * perform other operations.
  47. ***************************************************************************/
  48. INT APIENTRY CallBack( //* ENTRY:
  49. LPOLECLIENT lpClient, //* client application pointer
  50. OLE_NOTIFICATION flags, //* notification code being sent
  51. LPOLEOBJECT lpObject //* OLE object pointer
  52. ){ //* LOCAL:
  53. APPITEMPTR pItem; //* application item pointer
  54. pItem = (APPITEMPTR)lpClient;
  55. switch (flags)
  56. {
  57. case OLE_CLOSED: //* server has closed
  58. if (!pItem->fVisible)
  59. {
  60. PostMessage(hwndFrame, WM_DELETE, 0L, (DWORD)pItem);
  61. Dirty(DOC_UNDIRTY);
  62. }
  63. SetFocus( hwndFrame );
  64. break;
  65. case OLE_SAVED: //* server has saved object
  66. case OLE_CHANGED: //* object has changes
  67. cOleWait++;
  68. pItem->fServerChangedBounds = pItem->fVisible = TRUE;
  69. PostMessage(pItem->hwnd, WM_CHANGE, 0, 0L);
  70. break;
  71. case OLE_RELEASE: //* notification that an asynchronous
  72. ToggleBlockTimer(FALSE); //* toggle timer off
  73. if (hRetry)
  74. PostMessage(hRetry,WM_COMMAND,IDCANCEL,0L);
  75. if (cOleWait) //* operation has completed
  76. {
  77. pItem->fRetry = TRUE;
  78. if (!--cOleWait)
  79. Hourglass(FALSE);
  80. Release(pItem);
  81. }
  82. break;
  83. case OLE_QUERY_RETRY: //* Continue retrying.
  84. ToggleBlockTimer(FALSE); //* toggle timer off
  85. if (!hRetry && pItem->fRetry)
  86. PostMessage(hwndFrame,WM_RETRY,0L, (DWORD)pItem);
  87. return (pItem->fRetry);
  88. case OLE_QUERY_PAINT: //* continue repainting
  89. return TRUE; //* a false return terminates either
  90. default:
  91. break;
  92. }
  93. return 0; //* return value is ignored in
  94. //* most cases, see header
  95. }
  96. /***************************************************************************
  97. * Release()
  98. *
  99. * Check for an error on the OLE_RELEASE notification.
  100. **************************************************************************/
  101. static VOID Release( //* ENTRY:
  102. APPITEMPTR pItem //* Item pointer
  103. ){ //* LOCAL:
  104. DWORD wParam; //* error code parameter
  105. if ((wParam = OleQueryReleaseError(pItem->lpObject)) == OLE_OK)
  106. return;
  107. switch (OleQueryReleaseMethod(pItem->lpObject))
  108. {
  109. case OLE_LNKPASTE:
  110. pItem->fVisible = FALSE;
  111. break;
  112. case OLE_CREATEFROMTEMPLATE:
  113. case OLE_CREATE:
  114. pItem->fVisible = FALSE;
  115. cOleWait++;
  116. PostMessage(hwndFrame, WM_DELETE,1L, (DWORD)pItem);
  117. Dirty(DOC_UNDIRTY);
  118. }
  119. //* post a message to the main window
  120. //* which will display a message box
  121. PostMessage(hwndFrame,WM_ERROR,wParam,0);
  122. }
  123. /***************************************************************************
  124. * Error()
  125. *
  126. * This function checks for error conditions
  127. * generated by OLE API callsFor OLE_WAIT_FOR_RELEASE,
  128. * we keep track of the number of objects waiting, when
  129. * this count is zero, it is safe to exit the application.
  130. *
  131. * Returns OLESTATUS - 0 if OLE_WAIT_FOR_RELEASE or OLE_OK
  132. * otherwise the OLESTATUS returned after an action
  133. * is taken.
  134. *************************************************************************/
  135. OLESTATUS FAR Error( //* ENTRY
  136. OLESTATUS olestat //* OLE status
  137. ){
  138. switch (olestat)
  139. {
  140. case OLE_WAIT_FOR_RELEASE:
  141. if (!cOleWait)
  142. Hourglass(TRUE);
  143. cOleWait++; //* increment wait count
  144. case OLE_OK:
  145. return 0;
  146. case OLE_ERROR_STATIC: //* static object
  147. ErrorMessage(W_STATIC_OBJECT);
  148. break;
  149. case OLE_ERROR_REQUEST_PICT:
  150. case OLE_ERROR_ADVISE_RENAME:
  151. case OLE_ERROR_DOVERB:
  152. case OLE_ERROR_SHOW:
  153. case OLE_ERROR_OPEN:
  154. case OLE_ERROR_NETWORK:
  155. case OLE_ERROR_ADVISE_PICT:
  156. case OLE_ERROR_COMM: //* Invalid links
  157. InvalidLink();
  158. break;
  159. case OLE_BUSY:
  160. RetryMessage(NULL,RD_CANCEL);
  161. default:
  162. break;
  163. }
  164. return olestat;
  165. }
  166. /****************************************************************************
  167. * PreItemCreate()
  168. *
  169. * This routine allocates an application item structure. A pointer to this
  170. * structure is passed as the client structure, therefore we need to
  171. * have a pointer to the vtbl as the first entry. We are doing this
  172. * to allow acess to the application item information during a OLE
  173. * DLL callback. This approach simplifies matters.
  174. *
  175. * Returns APPITEMPTR - a pointer to a new application item structure
  176. * which can operate as a client structure.
  177. ***************************************************************************/
  178. APPITEMPTR FAR PreItemCreate( //* ENTRY:
  179. LPOLECLIENT lpClient, //* OLE client pointer
  180. BOOL fShow, //* show/no-show flag
  181. LHCLIENTDOC lhcDoc //* client document handle
  182. ){ //* LOCAL:
  183. HANDLE hitem; //* temp handle for new item
  184. APPITEMPTR pItem; //* application item pointer
  185. if (hitem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(APPITEM)))
  186. if (pItem = (APPITEMPTR)LocalLock(hitem))
  187. { //* set the vtbl pointer
  188. pItem->oleclient.lpvtbl = lpClient->lpvtbl;
  189. pItem->lpObjectUndo = NULL;
  190. pItem->fVisible = fShow;
  191. pItem->fServerChangedBounds = FALSE;
  192. pItem->lhcDoc = lhcDoc;
  193. return pItem; //* SUCCESS return
  194. }
  195. ErrorMessage(E_FAILED_TO_ALLOC);
  196. return NULL; //* ERROR return
  197. }
  198. /***************************************************************************
  199. * ItemWndProc()
  200. *
  201. * This function handles item window message processing.
  202. * There is an item window for each OLE object. This was done to
  203. * to simplify hit testing and repainting. These windows are child
  204. * windows.
  205. * returns long - standard child routine
  206. **************************************************************************/
  207. LONG APIENTRY ItemWndProc( //* ENTRY:
  208. HWND hwnd, //* standard windows parameters
  209. UINT msg,
  210. DWORD wParam,
  211. LONG lParam
  212. ){ //* LOCAL:
  213. static POINT dragPt; //* Mouse drag point
  214. static RECT dragRect; //* Mouse drag rectangle
  215. static BOOL fCaptured; //* captured flag
  216. APPITEMPTR pItem; //* application item pointer
  217. PAINTSTRUCT ps; //* paint structure
  218. POINT pt; //* point
  219. RECT rc; //* bounding rectangle
  220. // char lpstr[256];
  221. switch (msg)
  222. {
  223. case WM_SIZE:
  224. if (pItem = (APPITEMPTR)GetWindowLong(hwnd,0))
  225. {
  226. if (!pItem->fServerChangedBounds && pItem->otObject == OT_EMBEDDED)
  227. ObjSetBounds(pItem);
  228. else
  229. pItem->fServerChangedBounds = FALSE;
  230. }
  231. break;
  232. case WM_CHANGE:
  233. --cOleWait;
  234. pItem = (APPITEMPTR)GetWindowLong(hwnd,0);
  235. if (!Error(OleQueryBounds(pItem->lpObject, &rc)))
  236. {
  237. ConvertToClient(&rc);
  238. SetWindowPos(
  239. hwnd,
  240. NULL,
  241. 0,
  242. 0,
  243. rc.right - rc.left + 2*GetSystemMetrics(SM_CXFRAME),
  244. rc.bottom - rc.top + 2*GetSystemMetrics(SM_CYFRAME),
  245. SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  246. );
  247. if (!pItem->fNew && !fLoadFile)
  248. ShowNewWindow(pItem);
  249. else
  250. InvalidateRect(hwnd, NULL, TRUE);
  251. Dirty(DOC_DIRTY);
  252. }
  253. break;
  254. case WM_NCLBUTTONDOWN:
  255. SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
  256. return (DefWindowProc(hwnd, msg, wParam, lParam));
  257. case WM_PAINT:
  258. BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
  259. GetClientRect(hwnd, &rc);
  260. pItem = (APPITEMPTR)GetWindowLong(hwnd, 0);
  261. //* Call OLE draw
  262. Error(OleDraw(pItem->lpObject, ps.hdc, &rc, NULL, NULL));
  263. EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
  264. break;
  265. case WM_LBUTTONDBLCLK: //* execute a verb
  266. ANY_OBJECT_BUSY;
  267. ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowLong(hwnd,0));
  268. break;
  269. case WM_LBUTTONDOWN:
  270. GetWindowRect(hwnd, (LPRECT)&dragRect);
  271. ScreenToClient(hwndFrame, (LPPOINT)&dragRect);
  272. ScreenToClient(hwndFrame, (LPPOINT)&dragRect.right);
  273. dragPt.x = (LONG)(SHORT)LOWORD(lParam);
  274. dragPt.y = (LONG)(SHORT)HIWORD(lParam);
  275. ClientToScreen(hwnd, (LPPOINT)&dragPt);
  276. ScreenToClient(hwndFrame, (LPPOINT)&dragPt);
  277. SetCapture(hwnd);
  278. fCaptured = TRUE;
  279. SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
  280. break;
  281. case WM_LBUTTONUP:
  282. if (!fCaptured)
  283. break;
  284. ReleaseCapture();
  285. fCaptured = FALSE;
  286. Dirty(DOC_DIRTY);
  287. break;
  288. case WM_MOUSEMOVE:
  289. if (!fCaptured)
  290. break;
  291. pt.x = (LONG)(SHORT)LOWORD(lParam);
  292. pt.y = (LONG)(SHORT)HIWORD(lParam);
  293. ClientToScreen(hwnd, (LPPOINT)&pt);
  294. ScreenToClient(hwndFrame, (LPPOINT)&pt);
  295. OffsetRect(
  296. (LPRECT)&dragRect,
  297. pt.x - dragPt.x,
  298. pt.y - dragPt.y
  299. );
  300. MoveWindow(
  301. hwnd,
  302. dragRect.left, dragRect.top,
  303. dragRect.right - dragRect.left,
  304. dragRect.bottom - dragRect.top, TRUE
  305. );
  306. dragPt.x = pt.x;
  307. dragPt.y = pt.y;
  308. break;
  309. default:
  310. return (DefWindowProc(hwnd, msg, wParam, lParam));
  311. }
  312. return 0L;
  313. }
  314. /****************************************************************************
  315. * PostItemCreate()
  316. *
  317. * This function creates a child window which will contain the newly
  318. * created OLE object. A pointer to our item information is stored in the
  319. * extra bytes of this window. This is where we internally keep track
  320. * of information related to the object as well as the
  321. * pointer to the object for subsequent OLE API calls. This routine is
  322. * called after an OLE object has been created by the client library.
  323. *
  324. * Returns BOOL - TRUE if application item has been created.
  325. ****************************************************************************/
  326. BOOL FAR PostItemCreate( //* ENTRY:
  327. LPOLEOBJECT lpObject, //* OLE object pointer
  328. LONG otObject, //* OLE object type
  329. LPRECT lprcObject, //* object bounding rect
  330. APPITEMPTR pItem //* application item pointer
  331. ){ //* LOCAL:
  332. INT i; //* index
  333. RECT rc; //* bounding rectangle
  334. CHAR pData[OBJECT_LINK_MAX];//* copy of link data
  335. if (lprcObject) //* if the size of the objects
  336. rc = *lprcObject; //* bounding rectangle is not
  337. else if (OleQueryBounds(lpObject, &rc) == OLE_OK)
  338. ConvertToClient(&rc);
  339. else
  340. SetRect(&rc, 0, 0, 0, 0);
  341. if (!(pItem->hwnd = CreateWindow( //* Create the child window
  342. szItemClass, "",
  343. WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME,
  344. rc.left,rc.top,
  345. rc.right - rc.left + 2 * GetSystemMetrics(SM_CXFRAME),
  346. rc.bottom - rc.top + 2 * GetSystemMetrics(SM_CYFRAME),
  347. hwndFrame, NULL, hInst, NULL
  348. ))) goto Error;
  349. //* in windows extra bytes
  350. SetWindowLong(pItem->hwnd, 0, (LONG)pItem);
  351. pItem->otObject = otObject;
  352. pItem->lpObject = lpObject;
  353. pItem->fRetry = TRUE;
  354. if( pItem->otObject == OT_EMBEDDED )//* if object is embedded tell library
  355. { //* the container name and object name.
  356. UINT cb=CBOBJNAMEMAX; //* The name will be the server window title.
  357. CHAR sz[CBOBJNAMEMAX]; //* when the object is edited.
  358. OleQueryName(lpObject, (LPSTR)sz, (UINT FAR *)&cb );
  359. WaitForObject(pItem);
  360. Error(OleSetHostNames(lpObject, (LPSTR)szAppName, (LPSTR)sz ));
  361. WaitForObject(pItem);
  362. }
  363. else if (pItem->otObject == OT_LINK)//* if the object is linked
  364. { //* retrieve update options
  365. WaitForObject(pItem);
  366. if(Error(OleGetLinkUpdateOptions(pItem->lpObject, &pItem->uoObject)))
  367. goto Error;
  368. if (ObjGetData(pItem,pData))
  369. {
  370. for (i=0; pData[i];i++); //* Skip past the server name
  371. pItem->aLinkName = AddAtom(&pData[++i]);
  372. }
  373. else
  374. pItem->aLinkName = AddAtom("");
  375. }
  376. iObjects++;
  377. Dirty(DOC_DIRTY);
  378. //* a user interface recommendations.
  379. return TRUE; //* SUCCESS return
  380. Error: //* ERROR Tag
  381. ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
  382. FreeAppItem(pItem);
  383. return FALSE; //* ERROR return
  384. }
  385. /***************************************************************************
  386. * ConvertToClient()
  387. *
  388. * This function will convert to client from himetric.
  389. **************************************************************************/
  390. VOID FAR ConvertToClient( //* ENTRY:
  391. LPRECT lprc //* pointer to bounding rectangle
  392. ){ //* LOCAL
  393. //* If we have an empty rectangle then set the default size
  394. if (!(lprc->left || lprc->top || lprc->right || lprc->bottom))
  395. SetRect(lprc, 0, 0, CXDEFAULT, CYDEFAULT);
  396. else
  397. {
  398. //* We got the himetric units, converts them to pixels now.
  399. lprc->right = MulDiv (giXppli, (lprc->right - lprc->left),
  400. HIMETRIC_PER_INCH);
  401. lprc->bottom = MulDiv (giYppli, (lprc->top - lprc->bottom),
  402. HIMETRIC_PER_INCH);
  403. lprc->left = 0;
  404. lprc->top = 0;
  405. }
  406. }
  407. /***************************************************************************
  408. * ObjInsert()
  409. *
  410. * Query the user for object type to insert and insert the new OLE object
  411. ***************************************************************************/
  412. VOID FAR ObjInsert( //* ENTRY:
  413. LHCLIENTDOC lhcDoc, //* OLE document handle
  414. LPOLECLIENT lpClient //* pointer to OLE client structure
  415. ){ //* LOCAL:
  416. LPOLEOBJECT lpObject; //* pointer to OLE object
  417. APPITEMPTR pItem; //* item pointer
  418. CHAR szServerName[CBPATHMAX];//* Class name for OleCreate()
  419. CHAR szClassName[CBPATHMAX];//* Class name for OleCreate()
  420. CHAR szTmp[CBOBJNAMEMAX]; //* buffer to unique object name
  421. if (DialogBoxParam(hInst, MAKEINTRESOURCE(DTCREATE),hwndFrame,
  422. fnInsertNew, (LPARAM)((LPSTR)szClassName)) != IDCANCEL)
  423. {
  424. if (pItem = PreItemCreate(lpClient, FALSE, lhcDoc))
  425. {
  426. RegGetClassId(szServerName, szClassName);
  427. pItem->aServer = AddAtom(szServerName);
  428. if ( Error( OleCreate(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),
  429. (LPSTR)szClassName, lhcDoc,CreateNewUniqueName(szTmp),
  430. &lpObject,olerender_draw, 0)))
  431. {
  432. ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  433. FreeAppItem(pItem);
  434. }
  435. else
  436. PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  437. }
  438. }
  439. }
  440. /***************************************************************************
  441. * ObjDelete()
  442. *
  443. * Delete an OLE object. For this application, all OLE objects
  444. * are associated with a child window; therefore the window must be
  445. * destroyed.
  446. *
  447. * NOTE: There is one case when we call OleRelease and the other when
  448. * we call OleDelete. We call OleRelease when we are deregistering
  449. * a document and OleDelete when removing an object from a document.
  450. **************************************************************************/
  451. VOID FAR ObjDelete( //* ENTRY:
  452. APPITEMPTR pItem, //* pointer to application item
  453. BOOL fDelete //* delete or release flag
  454. ){ //* LOCAL:
  455. if (pItem->lpObjectUndo)
  456. {
  457. Error(OleDelete(pItem->lpObjectUndo));
  458. //* wait for asynchronous operation
  459. WaitForObject(pItem);
  460. }
  461. if (fDelete ? Error(OleDelete(pItem->lpObject))
  462. : Error(OleRelease(pItem->lpObject)))
  463. {
  464. ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
  465. return; //* ERROR return
  466. }
  467. if (pItem->fVisible)
  468. {
  469. ShowWindow(pItem->hwnd, SW_HIDE);
  470. pItem->fVisible = FALSE;
  471. }
  472. //* the operation has to complete
  473. WaitForObject(pItem); //* before the application structure
  474. FreeAppItem(pItem);
  475. iObjects--;
  476. }
  477. /***************************************************************************
  478. * ObjPaste()
  479. *
  480. * This function obtains an object from the clipboard.
  481. * Handles both embedded and linked objects. An item window is
  482. * created for each new object.
  483. *
  484. * Returns BOOL - TRUE if object was pasted succesfully.
  485. **************************************************************************/
  486. VOID FAR ObjPaste( //* ENTRY:
  487. BOOL fPaste, //* Paste/PasteLink flag
  488. LHCLIENTDOC lhcDoc, //* client document handle
  489. LPOLECLIENT lpClient //* pointer to client
  490. ){ //* LOCAL:
  491. LPOLEOBJECT lpObject; //* object pointer
  492. LONG otObject; //* object type
  493. APPITEMPTR pItem; //* application item pointer
  494. CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
  495. if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  496. return; //* ERROR return
  497. if (!OpenClipboard(hwndFrame))
  498. goto Error; //* ERROR jump
  499. if (fPaste) //* PASTE the object.
  500. { //* Try "StdFileEditing" protocol
  501. if (Error(OleCreateFromClip(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),lhcDoc,
  502. CreateNewUniqueName(szTmp),&lpObject, olerender_draw,0)))
  503. {
  504. //* next try "Static" protocol
  505. if (Error(OleCreateFromClip(
  506. STATICP, (LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  507. CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  508. goto Error; //* ERROR jump
  509. }
  510. }
  511. else
  512. { //* LINK therefore must be
  513. // "STdFileEditing" protocol
  514. if (Error(OleCreateLinkFromClip(
  515. STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), lhcDoc,
  516. CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  517. goto Error; //* ERROR jump
  518. }
  519. OleQueryType(lpObject, &otObject);
  520. CloseClipboard();
  521. if (!PostItemCreate(lpObject, otObject, NULL, pItem))
  522. return; //* ERROR return
  523. ShowNewWindow(pItem);
  524. return; //* SUCCESS return
  525. Error: //* TAG Error
  526. ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
  527. CloseClipboard();
  528. FreeAppItem(pItem);
  529. return; //* ERROR return
  530. }
  531. /***************************************************************************
  532. * ObjCopy()
  533. *
  534. * This function places an OLE object on the clipboard via the \
  535. * OleCopyToClipboard() function.
  536. *
  537. * Returns BOOL - TRUE if object successfully placed on clipboard
  538. **************************************************************************/
  539. BOOL FAR ObjCopy( //* ENTRY:
  540. APPITEMPTR pItem //* pointer to app item
  541. ){ //* LOCAL:
  542. BOOL fReturn = TRUE; //* return value
  543. if (!OpenClipboard(hwndFrame))
  544. return FALSE; //* ERROR return
  545. EmptyClipboard();
  546. if (Error(OleCopyToClipboard(pItem->lpObject)))
  547. fReturn = FALSE; //* prepare for ERROR out
  548. CloseClipboard();
  549. return fReturn; //* ERROR or SUCCESS
  550. }
  551. /***************************************************************************
  552. * ObjCreateFromTemplate()
  553. *
  554. * Creates an embedded object from file.
  555. **************************************************************************/
  556. VOID FAR ObjCreateFromTemplate( //* ENTRY:
  557. LHCLIENTDOC lhcDoc, //* client document handle
  558. LPOLECLIENT lpClient //* client vtbl. pointer
  559. ){ //* LOCAL:
  560. LPOLEOBJECT lpObject; //* OLE object pointer
  561. APPITEMPTR pItem; //* application item pointer
  562. CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
  563. CHAR szFileName[CBPATHMAX];//* file name string
  564. *szFileName = 0;
  565. if (!OfnGetName(hwndFrame, szFileName, IDM_INSERTFILE))
  566. return; //* ERROR operation aborted by user
  567. if (!(pItem = PreItemCreate(lpClient, FALSE, lhcDoc)))
  568. return; //* ERROR
  569. if (Error(OleCreateFromTemplate(STDFILEEDITING, (LPOLECLIENT)pItem, szFileName,
  570. lhcDoc, CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
  571. {
  572. ErrorMessage(E_CREATE_FROM_TEMPLATE);
  573. FreeAppItem(pItem);
  574. return; //* ERROR
  575. }
  576. PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
  577. } //* SUCCESS
  578. /****************************************************************************
  579. * ObjGetData()
  580. *
  581. * Get the object link data. The data that is retrieved from OLE is copied
  582. * into lpLinkData if lpLinkData is not NULL. Otherwise, space is dynamically
  583. * allocated or reallocated; space is allocated if pItem->lpLinkData is NULL
  584. * otherwise the pointer is reallocated. The data is returned is freed if
  585. * there has been an OLE_WARN_DELETE_DATA error.
  586. ***************************************************************************/
  587. BOOL FAR ObjGetData( //* ENTRY:
  588. APPITEMPTR pItem, //* OLE object
  589. LPSTR lpLinkData //* pointer to linkdata
  590. ){ //* LOCAL:
  591. HANDLE hData; //* handle to OLE link data
  592. LPSTR lpData; //* pointer to OLE link data
  593. LPSTR lpWork; //* copy of OLE link data
  594. BOOL fFree = FALSE; //* free OLE memory flag
  595. LONG lSize; //* size of OLE link data
  596. INT i;
  597. switch (Error(OleGetData(pItem->lpObject,
  598. (OLECLIPFORMAT)(pItem->otObject == OT_LINK ? vcfLink : vcfOwnerLink), &hData)))
  599. {
  600. case OLE_WARN_DELETE_DATA:
  601. fFree = TRUE;
  602. case OLE_OK:
  603. if(lpData = GlobalLock(hData))
  604. {
  605. //* copy the link data to new buffer
  606. lSize=SizeOfLinkData(lpData);
  607. if (!lpLinkData)
  608. {
  609. if (!pItem->lpLinkData) //* allocate
  610. AllocLinkData(pItem,lSize);
  611. else //* otherwise reallocate
  612. ReallocLinkData(pItem,lSize);
  613. lpWork = pItem->lpLinkData;
  614. }
  615. else
  616. lpWork = lpLinkData;
  617. if (lpWork)
  618. for (i=0L; i<(INT)lSize; i++)
  619. *(lpWork+i)=*(lpData+i);
  620. GlobalUnlock(hData); //* free the linked data as needed
  621. if (fFree)
  622. GlobalFree(hData);
  623. return TRUE; //* SUCCESS
  624. }
  625. default:
  626. return FALSE; //* FAILURE
  627. }
  628. }
  629. /***************************************************************************
  630. * ObjChangeLink()
  631. *
  632. * Change the linkdata. This routine will change the document portion of
  633. * link data to lpDoc. The old linkdata is expected to be in
  634. * lpaItem->lpLinkData
  635. **************************************************************************/
  636. VOID FAR ObjChangeLinkData( //* ENTRY:
  637. APPITEMPTR pItem, //* OLE object
  638. LPSTR lpDoc //* document name
  639. ){ //* LOCAL:
  640. LONG lSize; //* used to link data size
  641. LPSTR lpLinkData; //* OLE link data pointer
  642. static CHAR pWork[OBJECT_LINK_MAX]; //* used to construct new link data
  643. INT i; //* index
  644. HANDLE hData;
  645. pItem->aLinkName = AddAtom(lpDoc);
  646. for (
  647. lpLinkData = pItem->lpLinkData, i=0;
  648. pWork[i] = *lpLinkData;
  649. lpLinkData++, i++
  650. );
  651. //* into working buffer.
  652. lstrcpy((LPSTR)&pWork[++i],lpDoc); //* copy new document name.
  653. for (; pWork[i]; i++); //* skip to end of document name
  654. for (++lpLinkData;*lpLinkData;lpLinkData++);
  655. //* copy item name.
  656. lstrcpy((LPSTR)&pWork[++i],++lpLinkData);
  657. for (; pWork[i]; i++); //* skip to end of buffer
  658. //* which is the end of item info.
  659. pWork[++i] = 0; //* add extra null.
  660. lSize = SizeOfLinkData(pWork); //* reallocate space so there is
  661. ReallocLinkData(pItem,lSize); //* a properly sized block of info
  662. //* to send the linked data to the
  663. if (lpLinkData = pItem->lpLinkData) //* OLE DLL.
  664. for (i=0; i<(INT)lSize; i++) //* copy new linkdata into this space
  665. *lpLinkData++ = pWork[i];
  666. else
  667. return; //* ERROR return
  668. Error(OleSetData(pItem->lpObject, vcfLink, GlobalHandle(pItem->lpLinkData)));
  669. /*
  670. * The handle passed into OleSetData is owned by the OLE client library
  671. * and should not be used after the call. On win32s, it is inaccessible
  672. * after the call, so restore it by calling OleGetData. Note that the
  673. * data is *still* owned by the library, but we will now have access
  674. * to the memory.
  675. */
  676. Error(OleGetData(pItem->lpObject, vcfLink, &hData));
  677. if (hData) {
  678. pItem->lpLinkData = GlobalLock(hData);
  679. }
  680. } //* SUCCESS return
  681. /****************************************************************************
  682. * ObjSaveUndo()
  683. *
  684. * Clone the OLE object so that any changes to object can be undone if the
  685. * user choses to exit without update.
  686. ***************************************************************************/
  687. VOID FAR ObjSaveUndo( //* ENTRY:
  688. APPITEMPTR pItem //* application item
  689. ){ //* LOCAL:
  690. CHAR szTmp[CBOBJNAMEMAX]; //* holder of object name
  691. LPSTR lpClone; //* pointer to clond object name
  692. UINT i=CBOBJNAMEMAX;
  693. if (!pItem->lpObjectUndo)
  694. {
  695. OleQueryName(pItem->lpObject, szTmp, &i);
  696. //* give clone a unique name by
  697. //* altering object name prefix.
  698. for (lpClone = OBJCLONE, i=0; *lpClone; szTmp[i++] = *lpClone++);
  699. if (Error(OleClone(pItem->lpObject, (LPOLECLIENT)pItem,
  700. pItem->lhcDoc, szTmp, &(pItem->lpObjectUndo))))
  701. return; //* ERROR return
  702. pItem->otObjectUndo = pItem->otObject;
  703. pItem->uoObjectUndo = pItem->uoObject;
  704. pItem->aLinkUndo = pItem->aLinkName;
  705. GetClientRect(pItem->hwnd, &pItem->rect);
  706. if (OleQueryOpen(pItem->lpObject) == OLE_OK)
  707. pItem->fOpen = TRUE;
  708. }
  709. } //* SUCCESS return
  710. /****************************************************************************
  711. * ObjUndo()
  712. *
  713. * Restore an object to its state before changes. The lpObject Undo is a
  714. * clone to the original object with a different name, therefore, all we
  715. * have to do is rename that object and ditch the changed object.
  716. ***************************************************************************/
  717. VOID FAR ObjUndo( //* ENTRY:
  718. APPITEMPTR pItem //* application item
  719. ){ //* LOCAL:
  720. CHAR szTmp[CBOBJNAMEMAX]; //* object name holder
  721. UINT i = CBOBJNAMEMAX;
  722. OleQueryName(pItem->lpObject, szTmp, &i);
  723. if (Error(OleDelete(pItem->lpObject)))
  724. return; //* ERROR return
  725. //* reset app item vars
  726. pItem->lpObject = pItem->lpObjectUndo;
  727. pItem->otObject = pItem->otObjectUndo;
  728. pItem->uoObject = pItem->uoObjectUndo;
  729. pItem->aLinkName = pItem->aLinkUndo;
  730. pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
  731. pItem->otObjectUndo = (LONG)NULL;
  732. if (Error(OleRename(pItem->lpObject,szTmp)))
  733. return; //* ERROR return
  734. if (pItem->fOpen)
  735. {
  736. Error(OleReconnect(pItem->lpObject));
  737. pItem->fOpen = FALSE;
  738. }
  739. SetWindowPos(
  740. pItem->hwnd,
  741. NULL, 0, 0,
  742. pItem->rect.right - pItem->rect.left + 2*GetSystemMetrics(SM_CXFRAME),
  743. pItem->rect.bottom - pItem->rect.top + 2*GetSystemMetrics(SM_CYFRAME),
  744. SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
  745. );
  746. InvalidateRect(pItem->hwnd,NULL,TRUE);
  747. } //* SUCCESS return
  748. /****************************************************************************
  749. * ObjDelUndo()
  750. *
  751. * Delete the undo object if the user is happy with the changes he/she made.
  752. ***************************************************************************/
  753. VOID FAR ObjDelUndo( //* ENTRY:
  754. APPITEMPTR pItem //* application item
  755. ){
  756. if (Error(OleDelete(pItem->lpObjectUndo)))
  757. return; //* ERROR return
  758. pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
  759. pItem->otObjectUndo = (LONG)NULL;
  760. DeleteAtom(pItem->aLinkUndo);
  761. pItem->lpObjectUndo = NULL;
  762. } //* SUCCESS return
  763. /****************************************************************************
  764. * ObjFreeze()
  765. *
  766. * Convert an object to a static object.
  767. ***************************************************************************/
  768. VOID FAR ObjFreeze( //* ENTRY:
  769. APPITEMPTR pItem //* application item
  770. ){ //* LOCAL:
  771. CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name
  772. LPSTR lpTemp; //* temporary prefix string
  773. LPOLEOBJECT lpObjectTmp; //* temporary object pointer
  774. UINT i=CBOBJNAMEMAX;
  775. OleQueryName(pItem->lpObject, szTmp, &i);
  776. //* create a unique name by changing
  777. //* the object name prefix
  778. for (lpTemp = OBJTEMP, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
  779. //* this API creates a static object
  780. if (Error(OleObjectConvert(pItem->lpObject, STATICP, (LPOLECLIENT)pItem,
  781. pItem->lhcDoc, szTmp, &lpObjectTmp)))
  782. return;
  783. //* delete old object
  784. if (Error(OleDelete(pItem->lpObject)))
  785. return;
  786. WaitForObject(pItem);
  787. pItem->lpObject = lpObjectTmp;
  788. pItem->otObject = OT_STATIC;
  789. pItem->uoObject = -1L;
  790. for (lpTemp = OBJPREFIX, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
  791. if (Error(OleRename(pItem->lpObject,szTmp)))
  792. return;
  793. }
  794. /***************************************************************************
  795. * ObjCreateWrap()
  796. *
  797. * Create a wrapped object from the drag and drop feature of the 3.1 shell.
  798. * NOTE: We are assuming that only one file has been dropped. See the SDK
  799. * documentation for instructions on how to deal with multiple files.
  800. ***************************************************************************/
  801. VOID FAR ObjCreateWrap( //* ENTRY:
  802. HANDLE hdrop, //* handle to dropped object
  803. LHCLIENTDOC lhcDoc, //* document handle
  804. LPOLECLIENT lpClient //* pointer to client structure
  805. ){ //* LOCAL:
  806. CHAR szDragDrop[CBPATHMAX];//* Drag and drop file name
  807. LPOLEOBJECT lpObject; //* pointer to OLE object
  808. POINT pt; //* position of dropped object
  809. RECT rc; //* object size and position
  810. CHAR szTmp[CBOBJNAMEMAX]; //* buffer for unique object name
  811. APPITEMPTR pItem; //* application item pointer
  812. INT x,y; //* icon sizes
  813. x = GetSystemMetrics(SM_CXICON) / 2;
  814. y = GetSystemMetrics(SM_CYICON) / 2;
  815. //* Get the drag and drop filename
  816. //* position
  817. DragQueryPoint(hdrop, &pt);
  818. DragQueryFile(hdrop, 0, szDragDrop, CBPATHMAX);
  819. DragFinish(hdrop);
  820. SetRect(&rc, pt.x - x, pt.y - y, pt.x + x, pt.y + y);
  821. if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
  822. return; //* ERROR return
  823. //* create OLE object
  824. if (Error(OleCreateFromFile(STDFILEEDITING, (LPOLECLIENT)pItem,
  825. "Package", szDragDrop, lhcDoc, CreateNewUniqueName(szTmp),
  826. &lpObject, olerender_draw, 0)))
  827. {
  828. ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
  829. FreeAppItem(pItem);
  830. return; //* ERROR return
  831. }
  832. if (PostItemCreate(lpObject, OT_EMBEDDED, &rc, pItem))
  833. ShowNewWindow(pItem);
  834. } //* SUCCESS return
  835. /***************************************************************************
  836. * UpdateObjectMenuItem()
  837. *
  838. * Add an object popup menu for the chosen object if multiple verbs exist.
  839. * The registration system is used to determine which verbs exist for the
  840. * given object.
  841. **************************************************************************/
  842. VOID FAR UpdateObjectMenuItem( //* ENTRY:
  843. HMENU hMenu //* main menu
  844. ){ //* LOCAL
  845. INT cVerbs; //* verb
  846. APPITEMPTR pItem; //* application item ponter
  847. DWORD dwSize = KEYNAMESIZE;
  848. CHAR szClass[KEYNAMESIZE], szBuffer[200];
  849. CHAR szVerb[KEYNAMESIZE];
  850. HMENU hPopupNew=NULL;
  851. HKEY hkeyTemp;
  852. CHAR pLinkData[OBJECT_LINK_MAX];
  853. //* delete current item and submenu
  854. DeleteMenu(hMenu, POS_OBJECT, MF_BYPOSITION );
  855. if (!(pItem = GetTopItem()) )
  856. goto Error; //* ERROR jump
  857. else if (!pItem->fVisible)
  858. goto Error; //* ERROR jump
  859. //* if STATIC ?
  860. if ((pItem->otObject != OT_EMBEDDED) && (pItem->otObject != OT_LINK))
  861. goto Error; //* ERROR jump
  862. if (!ObjGetData(pItem, pLinkData)) //* get linkdata as key reg database
  863. goto Error; //* ERROR jump
  864. //* open reg database
  865. szClass[0] = 0;
  866. if (RegOpenKey(HKEY_CLASSES_ROOT, szClass, &hkeyTemp))
  867. goto Error; //* ERROR jump
  868. //* check if class is reg-db
  869. if (RegQueryValue(HKEY_CLASSES_ROOT, pLinkData, szClass, &dwSize))
  870. {
  871. RegCloseKey(hkeyTemp);
  872. goto Error; //* ERROR jump
  873. }
  874. for (cVerbs=0; ;++cVerbs) //* extract all verbs from reg-db
  875. {
  876. dwSize = KEYNAMESIZE;
  877. wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
  878. (LPSTR)pLinkData,cVerbs);
  879. if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
  880. break;
  881. if (!hPopupNew)
  882. hPopupNew = CreatePopupMenu();
  883. InsertMenu(hPopupNew, (UINT)-1, MF_BYPOSITION, IDM_VERBMIN+cVerbs, szVerb);
  884. }
  885. //* NOTE: For International versions the following verb menu
  886. //* may need to be formatted differently.
  887. switch (cVerbs) //* determine how many verbs found
  888. {
  889. case 0: //* none
  890. wsprintf(szBuffer, "Edit %s %s", (LPSTR)szClass, (LPSTR)"&Object");
  891. InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  892. break;
  893. case 1: //* one
  894. wsprintf(szBuffer, "%s %s %s", (LPSTR)szVerb, (LPSTR)szClass,
  895. (LPSTR)"&Object");
  896. DestroyMenu(hPopupNew);
  897. InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
  898. break;
  899. default: //* > 1
  900. wsprintf(szBuffer, "%s %s", (LPSTR)szClass, (LPSTR)"&Object");
  901. InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION | MF_POPUP, (UINT)hPopupNew, szBuffer);
  902. EnableMenuItem(hMenu, POS_OBJECT, MF_ENABLED|MF_BYPOSITION);
  903. break;
  904. }
  905. RegCloseKey(hkeyTemp); //* close reg-db
  906. return; //* SUCCESS return
  907. Error: //* ERROR tag
  908. InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, 0, "&Object");
  909. EnableMenuItem(hMenu, POS_OBJECT, MF_GRAYED | MF_BYPOSITION);
  910. } //* ERROR return
  911. /***************************************************************************
  912. * ExecuteVerb()
  913. *
  914. * Execute the verb for the given object.
  915. ***************************************************************************/
  916. VOID FAR ExecuteVerb( //* ENTRY:
  917. UINT iVerb, //* verb
  918. APPITEMPTR pItem //* application item pointer
  919. ){ //* LOCAL
  920. RECT rc; //* holds client area bounding rect
  921. if (pItem->otObject == OT_STATIC) //* if the object is static beep
  922. {
  923. ErrorMessage(W_STATIC_OBJECT);
  924. return; //* return
  925. }
  926. //* get cliet area rectangle
  927. GetClientRect(hwndFrame, (LPRECT)&rc);
  928. //* execute OLE verb
  929. if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE, hwndFrame, &rc)))
  930. return;
  931. WaitForObject(pItem); //* wait for async. operation
  932. ObjSetBounds(pItem);
  933. } //* SUCCESS return
  934. /****************************************************************************
  935. * ObjSetBounds
  936. *
  937. * Set the object bounds. The object bounds are the child windos bounding
  938. * rectangle. OLE servers recieve need the bounding rectangle in HIMETRIC
  939. * coordinates. So, we convert from screen coordinates to HIMETRIC.
  940. *
  941. * Returns BOOL - TRUE if successful.
  942. ***************************************************************************/
  943. BOOL FAR ObjSetBounds( //* ENTRY:
  944. APPITEMPTR pItem //* application item pointer
  945. ){ //* LOCAL:
  946. RECT itemRect; //* bounding rectangle
  947. GetWindowRect(pItem->hwnd,&itemRect);//* get item window react
  948. itemRect.right -= GetSystemMetrics(SM_CXFRAME);
  949. itemRect.left += GetSystemMetrics(SM_CXFRAME);
  950. itemRect.top += GetSystemMetrics(SM_CYFRAME);
  951. itemRect.bottom -= GetSystemMetrics(SM_CYFRAME);
  952. itemRect.right = MulDiv ((itemRect.right - itemRect.left),
  953. HIMETRIC_PER_INCH, giXppli);
  954. itemRect.bottom = - MulDiv((itemRect.bottom - itemRect.top),
  955. HIMETRIC_PER_INCH, giYppli);
  956. itemRect.top = 0;
  957. itemRect.left = 0;
  958. //* set the rect for the server
  959. if (Error(OleSetBounds(pItem->lpObject,(LPRECT)&itemRect)))
  960. return FALSE; //* ERROR return
  961. WaitForObject(pItem); //* wait for async. operation
  962. return TRUE; //* SUCCESS return
  963. }