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.

1777 lines
47 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: Item.c Object(item) main module
  3. *
  4. * Purpose: Includes All the object releated routiens.
  5. *
  6. * Created: Oct 1990.
  7. *
  8. * Copyright (c) 1990, 1991 Microsoft Corporation
  9. *
  10. * History:
  11. * Raor (../10/1990) Designed, coded
  12. *
  13. *
  14. \***************************************************************************/
  15. #include "cmacs.h"
  16. #include "windows.h"
  17. #include "ole.h"
  18. #include "dde.h"
  19. #include "srvr.h"
  20. extern HANDLE hdllInst;
  21. extern FARPROC lpFindItemWnd;
  22. extern FARPROC lpItemCallBack;
  23. extern FARPROC lpSendDataMsg;
  24. extern FARPROC lpSendRenameMsg;
  25. extern FARPROC lpDeleteClientInfo;
  26. extern FARPROC lpEnumForTerminate;
  27. extern ATOM cfNative;
  28. extern ATOM cfBinary;
  29. extern ATOM aClose;
  30. extern ATOM aChange;
  31. extern ATOM aSave;
  32. extern ATOM aEditItems;
  33. extern ATOM aStdDocName;
  34. extern WORD cfLink;
  35. extern WORD cfOwnerLink;
  36. extern BOOL bWin30;
  37. HWND hwndItem;
  38. HANDLE hddeRename;
  39. HWND hwndRename;
  40. WORD enummsg;
  41. WORD enuminfo;
  42. LPOLEOBJECT enumlpoleobject;
  43. OLECLIENTVTBL clVtbl;
  44. BOOL bClientUnlink;
  45. BOOL fAdviseSaveDoc;
  46. BOOL fAdviseSaveItem;
  47. char * stdStrTable[STDHOSTNAMES+1] = {NULL,
  48. "StdTargetDevice",
  49. "StdDocDimensions",
  50. "StdColorScheme",
  51. "StdHostNames"};
  52. extern HANDLE (FAR PASCAL *lpfnSetMetaFileBitsBetter) (HANDLE);
  53. void ChangeOwner (HANDLE hmfp);
  54. // !!!change child enumeration.
  55. // !!!No consistency in errors (Sometimes Bools and sometimes OLESTATUS).
  56. //SearchItem: Searches for a given item in a document tree.
  57. //If found, returns the corresponding child windows handle.
  58. HWND INTERNAL SearchItem (lpdoc, lpitemname)
  59. LPDOC lpdoc;
  60. LPSTR lpitemname;
  61. {
  62. ATOM aItem;
  63. Puts ("SearchItem");
  64. // If the item passed is an atom, get its name.
  65. if (!HIWORD(lpitemname))
  66. aItem = (ATOM) (LOWORD((DWORD)lpitemname));
  67. else if (!lpitemname[0])
  68. aItem = NULL;
  69. else
  70. aItem = GlobalFindAtom (lpitemname);
  71. hwndItem = NULL;
  72. // !!! We should avoid hwndItem static. It should not cause
  73. // any problems since while enumerating we will not be calling
  74. // any window procs or no PostMessages are entertained.
  75. EnumChildWindows (lpdoc->hwnd, lpFindItemWnd,
  76. MAKELONG (aItem, ITEM_FIND));
  77. return hwndItem;
  78. }
  79. // FindItem: Given the itemname and the document handle,
  80. // searches for the the item (object) in the document tree.
  81. // Items are child windows for the document window.
  82. // !!! change the child windows to somekind of
  83. // linked lists at the item level. This will free up
  84. // the space taken by the item windows.
  85. int INTERNAL FindItem (lpdoc, lpitemname, lplpclient)
  86. LPDOC lpdoc;
  87. LPSTR lpitemname;
  88. LPCLIENT FAR * lplpclient;
  89. {
  90. LPCLIENT lpclient;
  91. HWND hwnd;
  92. char buf[MAX_STR];
  93. Puts ("FindItem");
  94. hwnd = SearchItem (lpdoc, lpitemname);
  95. if (!HIWORD(lpitemname)){
  96. if (LOWORD(lpitemname))
  97. GlobalGetAtomName ((ATOM)LOWORD((DWORD)lpitemname),
  98. (LPSTR)buf, MAX_STR);
  99. else
  100. buf[0] = NULL;
  101. lpitemname = (LPSTR)buf;
  102. }
  103. if (hwnd) {
  104. // we found the item window
  105. lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
  106. #ifdef FIREWALLS
  107. ASSERT ((CheckPointer(lpclient, WRITE_ACCESS)),
  108. "In Item the client handle missing")
  109. ASSERT ((CheckPointer(lpclient->lpoleobject, WRITE_ACCESS)),
  110. "In Item object handle missing")
  111. #endif
  112. *lplpclient = lpclient;
  113. return OLE_OK;
  114. }
  115. // Item (object)window is not create yet. Let us create one.
  116. return RegisterItem ((LHDOC)lpdoc, lpitemname, lplpclient, TRUE);
  117. }
  118. //RegisterItem: Given the document handle and the item string
  119. //creates item with the given document.
  120. int INTERNAL RegisterItem (lhdoc, lpitemname, lplpclient, bSrvr)
  121. LHDOC lhdoc;
  122. LPSTR lpitemname;
  123. LPCLIENT FAR * lplpclient;
  124. BOOL bSrvr;
  125. {
  126. LPDOC lpdoc;
  127. HANDLE hclient = NULL;
  128. LPCLIENT lpclient = NULL;
  129. int retval = OLE_ERROR_MEMORY;
  130. LPOLESERVERDOC lpoledoc;
  131. LPOLEOBJECT lpoleobject = NULL;
  132. Puts ("CreateItem");
  133. lpdoc = (LPDOC)lhdoc;
  134. #ifdef FIREWALLS
  135. ASSERT ((CheckPointer (lplpclient, WRITE_ACCESS)), "invalid lplpclient");
  136. #endif
  137. // First create the callback client structure.
  138. hclient = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_DDESHARE, sizeof (CLIENT));
  139. if(!(hclient && (lpclient = (LPCLIENT)GlobalLock (hclient))))
  140. goto errRtn;
  141. lpclient->hclient = hclient;
  142. hclient = NULL;
  143. if (!HIWORD(lpitemname)) {
  144. ASSERT (!bSrvr, "invalid lpitemname in RegisterItem\n");
  145. lpclient->aItem = LOWORD((DWORD)lpitemname);
  146. }
  147. else if (!lpitemname[0])
  148. lpclient->aItem = NULL;
  149. else
  150. lpclient->aItem = GlobalAddAtom (lpitemname);
  151. lpclient->oleClient.lpvtbl = &clVtbl;
  152. lpclient->oleClient.lpvtbl->CallBack = (int (CALLBACK *)(LPOLECLIENT, OLE_NOTIFICATION, LPOLEOBJECT))lpItemCallBack;
  153. lpoledoc = lpdoc->lpoledoc;
  154. // Call the server app to create its own object structure and link
  155. // it to the given document.
  156. // Call the server if the item is not one of the standard items.
  157. if (bSrvr) {
  158. retval = (*lpoledoc->lpvtbl->GetObject)(lpoledoc, lpitemname,
  159. (LPOLEOBJECT FAR *)&lpoleobject, (LPOLECLIENT)lpclient);
  160. if (retval != OLE_OK)
  161. goto errRtn;
  162. }
  163. lpclient->lpoleobject = lpoleobject;
  164. lpclient->hwnd = CreateWindow ("ItemWndClass", "ITEM",
  165. WS_CHILD,0,0,0,0,lpdoc->hwnd,NULL, hdllInst, NULL);
  166. if (lpclient->hwnd == NULL)
  167. goto errRtn;
  168. // save the ptr to the item in the window.
  169. SetWindowLong (lpclient->hwnd, 0, (LONG)lpclient);
  170. *lplpclient = lpclient;
  171. return OLE_OK;
  172. errRtn:
  173. if (lpclient)
  174. RevokeObject ((LPOLECLIENT)lpclient, FALSE);
  175. else {
  176. if(hclient)
  177. GlobalFree (hclient);
  178. }
  179. return retval;
  180. }
  181. OLESTATUS FAR PASCAL OleRevokeObject (lpoleclient)
  182. LPOLECLIENT lpoleclient;
  183. {
  184. return RevokeObject (lpoleclient, TRUE);
  185. }
  186. // OleRevokeObject: Revokes an object (unregisres an object
  187. // from the document tree.
  188. OLESTATUS INTERNAL RevokeObject (lpoleclient, bUnlink)
  189. LPOLECLIENT lpoleclient;
  190. BOOL bUnlink;
  191. {
  192. HANDLE hclient;
  193. LPCLIENT lpclient;
  194. lpclient = (LPCLIENT)lpoleclient;
  195. PROBE_WRITE(lpoleclient);
  196. if (lpclient->lpoleobject) {
  197. // first call the object for deletetion.
  198. #ifdef FIREWALLS
  199. if (!CheckPointer (lpclient->lpoleobject, WRITE_ACCESS))
  200. ASSERT (0, "Invalid LPOLEOBECT")
  201. if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  202. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  203. else
  204. ASSERT(lpclient->lpoleobject->lpvtbl->Release,
  205. "Invalid pointer to Release method")
  206. #endif
  207. (*lpclient->lpoleobject->lpvtbl->Release)(lpclient->lpoleobject);
  208. }
  209. if (ISATOM(lpclient->aItem)) {
  210. GlobalDeleteAtom (lpclient->aItem);
  211. lpclient->aItem = NULL;
  212. }
  213. if (lpclient->hwnd) {
  214. SetWindowLong (lpclient->hwnd, 0, (LONG)NULL);
  215. // another static for enumerating the properties.
  216. // we need to change these .
  217. bClientUnlink = bUnlink;
  218. EnumProps(lpclient->hwnd, lpDeleteClientInfo);
  219. // post all the messages with yield which have been collected in enum
  220. // UnblockPostMsgs (lpclient->hwnd, FALSE);
  221. DestroyWindow (lpclient->hwnd);
  222. }
  223. GlobalUnlock (hclient = lpclient->hclient);
  224. GlobalFree (hclient);
  225. return OLE_OK;
  226. }
  227. BOOL FAR PASCAL DeleteClientInfo (hwnd, lpstr, hclinfo)
  228. HWND hwnd;
  229. LPSTR lpstr;
  230. HANDLE hclinfo;
  231. {
  232. PCLINFO pclinfo = NULL;
  233. HWND hwndDoc;
  234. LPDOC lpdoc;
  235. #ifdef FIREWALLS
  236. ASSERT (hclinfo, "Client info null in item property list");
  237. #endif
  238. // delete the printer dev info block
  239. if(pclinfo = (PCLINFO)LocalLock (hclinfo)){
  240. if(pclinfo->hdevInfo)
  241. GlobalFree (pclinfo->hdevInfo);
  242. if (bClientUnlink) {
  243. // terminate the conversation for the client.
  244. TerminateDocClients ((hwndDoc = GetParent(hwnd)), NULL, pclinfo->hwnd);
  245. lpdoc = (LPDOC)GetWindowLong (hwndDoc, 0);
  246. // for some reason this delete is gving circular lists for properties
  247. //DeleteClient (hwndDoc, pclinfo->hwnd);
  248. //lpdoc->cClients--;
  249. }
  250. LocalUnlock (hclinfo);
  251. }
  252. LocalFree (hclinfo);
  253. RemoveProp (hwnd, lpstr);
  254. return TRUE;
  255. }
  256. // Call back for the Object windows numeration. data field
  257. // has the command and the extra information
  258. BOOL FAR PASCAL FindItemWnd (hwnd, data)
  259. HWND hwnd;
  260. LONG data;
  261. {
  262. LPCLIENT lpclient;
  263. int cmd;
  264. HANDLE hclinfo;
  265. PCLINFO pclinfo;
  266. lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
  267. #ifdef FIREWALLS
  268. // ASSERT (lpclient, "In Item the client handle missing")
  269. #endif
  270. cmd = HIWORD(data);
  271. switch (cmd) {
  272. case ITEM_FIND:
  273. if (lpclient->aItem == (ATOM)(LOWORD (data))) {
  274. // we found the window we required. Remember the
  275. // object window.
  276. hwndItem = hwnd;
  277. return FALSE; // terminate enumeration.
  278. }
  279. break;
  280. case ITEM_SAVED:
  281. if (lpclient->lpoleobject) {
  282. if (ItemCallBack ((LPOLECLIENT) lpclient, OLE_SAVED,
  283. lpclient->lpoleobject) == OLE_ERROR_CANT_UPDATE_CLIENT)
  284. fAdviseSaveDoc = FALSE;
  285. }
  286. break;
  287. case ITEM_DELETECLIENT:
  288. // delete the client from our list if we have one
  289. hclinfo = FindClient (hwnd, (HWND) (LOWORD(data)));
  290. if (hclinfo){
  291. // delete the printer dev info block
  292. if(pclinfo = (PCLINFO)LocalLock (hclinfo)){
  293. if(pclinfo->hdevInfo)
  294. GlobalFree (pclinfo->hdevInfo);
  295. LocalUnlock (hclinfo);
  296. }
  297. LocalFree (hclinfo);
  298. DeleteClient ( hwnd, (HWND) (LOWORD(data)));
  299. }
  300. break;
  301. case ITEM_DELETE:
  302. // delete the client it self.
  303. RevokeObject ((LPOLECLIENT)lpclient, FALSE);
  304. break;
  305. }
  306. return TRUE; // continue enumeration.
  307. }
  308. //DeleteFromItemsList: Deletes a client from the object lists of
  309. //all the objects of a given document. Thie client possibly
  310. //is terminating the conversation with our doc window.
  311. void INTERNAL DeleteFromItemsList (hwndDoc, hwndClient)
  312. HWND hwndDoc;
  313. HWND hwndClient;
  314. {
  315. EnumChildWindows (hwndDoc, lpFindItemWnd,
  316. MAKELONG (hwndClient, ITEM_DELETECLIENT));
  317. }
  318. // DeleteAllItems: Deletes all the objects of a given
  319. // document window.
  320. void INTERNAL DeleteAllItems (hwndDoc)
  321. HWND hwndDoc;
  322. {
  323. EnumChildWindows (hwndDoc, lpFindItemWnd,
  324. MAKELONG (NULL, ITEM_DELETE));
  325. }
  326. // Object widnow proc:
  327. long FAR PASCAL ItemWndProc(hwnd, msg, wParam, lParam)
  328. HWND hwnd;
  329. WORD msg;
  330. WORD wParam;
  331. LONG lParam;
  332. {
  333. LPCLIENT lpclient;
  334. lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
  335. switch (msg) {
  336. case WM_DESTROY:
  337. DEBUG_OUT("Item: Destroy window",0)
  338. #ifdef FIREWALLS
  339. ASSERT (!lpclient, "while destroy Item client is not null")
  340. #endif
  341. break;
  342. default:
  343. DEBUG_OUT("item: Default message",0)
  344. return DefWindowProc (hwnd, msg, wParam, lParam);
  345. }
  346. return 0L;
  347. }
  348. // PokeData: Prepares and gives the data to the server app thru
  349. // the SetData object method.
  350. OLESTATUS INTERNAL PokeData (lpdoc, hwndClient, lparam)
  351. LPDOC lpdoc;
  352. HWND hwndClient;
  353. LONG lparam;
  354. {
  355. int retval = OLE_ERROR_MEMORY;
  356. LPCLIENT lpclient;
  357. DDEPOKE FAR * lpPoke = NULL;
  358. HANDLE hPoke = NULL;
  359. HANDLE hnew = NULL;
  360. int format;
  361. BOOL fRelease = FALSE;
  362. // Get the object handle first. Look in the registration
  363. // tree and if one is not created otherwise create one.
  364. retval = FindItem (lpdoc, (LPSTR) MAKEINTATOM(HIWORD(lparam)),
  365. (LPCLIENT FAR *)&lpclient);
  366. if (retval != OLE_OK)
  367. goto errRtn;
  368. hPoke = (HANDLE)(LOWORD (lparam));
  369. if(!(hPoke && (lpPoke = (DDEPOKE FAR *) GlobalLock (hPoke))))
  370. goto errRtn;
  371. GlobalUnlock (hPoke);
  372. format = lpPoke->cfFormat;
  373. fRelease = lpPoke->fRelease;
  374. // We found the item. Now prepare the data to be given to the object
  375. if (!(hnew = MakeItemData (lpPoke, hPoke, format)))
  376. goto errRtn;
  377. // Now send the data to the object
  378. #ifdef FIREWALLS
  379. if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  380. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  381. else
  382. ASSERT (lpclient->lpoleobject->lpvtbl->SetData,
  383. "Invalid pointer to SetData method")
  384. #endif
  385. retval = (*lpclient->lpoleobject->lpvtbl->SetData) (lpclient->lpoleobject,
  386. format, hnew);
  387. // We free the data if server returns OLE_ERROR_SETDATA_FORMAT.
  388. // Otherwise server must've deleted it.
  389. if (retval == OLE_ERROR_SETDATA_FORMAT) {
  390. if (!FreeGDIdata (hnew, format))
  391. GlobalFree (hnew);
  392. }
  393. errRtn:
  394. if (retval == OLE_OK && fRelease) {
  395. if (hPoke)
  396. GlobalFree (hPoke);
  397. }
  398. return retval;
  399. }
  400. OLESTATUS INTERNAL UnAdviseData (lpdoc, hwndClient, lparam)
  401. LPDOC lpdoc;
  402. HWND hwndClient;
  403. LONG lparam;
  404. {
  405. char buf[MAX_STR];
  406. int options;
  407. LPCLIENT lpclient;
  408. int retval = OLE_ERROR_MEMORY;
  409. HANDLE hclinfo = NULL;
  410. PCLINFO pclinfo = NULL;
  411. if (!(HIWORD (lparam)))
  412. buf[0] = NULL;
  413. else
  414. GlobalGetAtomName ((ATOM)(HIWORD (lparam)), (LPSTR)buf, MAX_STR);
  415. // Scan for the advise options like "Close", "Save" etc
  416. // at the end of the item.
  417. if((retval = ScanItemOptions ((LPSTR)buf, (int far *)&options)) !=
  418. OLE_OK)
  419. goto errRtn;
  420. if (buf[0] == NULL) {
  421. // Unadvise for null should terminate all the advises
  422. DeleteFromItemsList (lpdoc->hwnd, hwndClient);
  423. return OLE_OK;
  424. }
  425. // Now get the corresponding object.
  426. retval = FindItem (lpdoc, (LPSTR)buf, (LPCLIENT FAR *)&lpclient);
  427. if (retval != OLE_OK)
  428. goto errRtn;
  429. // Find the client structure to be attcahed to the object.
  430. if ((hclinfo = FindClient (lpclient->hwnd, hwndClient)) == NULL ||
  431. (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL ){
  432. retval = OLE_ERROR_MEMORY;
  433. goto errRtn;
  434. }
  435. pclinfo->options &= (~(0x0001 << options));
  436. errRtn:
  437. if (pclinfo)
  438. LocalUnlock (hclinfo);
  439. return retval;
  440. }
  441. // AdviseStdItems: This routine takes care of the DDEADVISE for a
  442. //particular object in given document. Creates a client strutcure
  443. //and attaches to the property list of the object window.
  444. OLESTATUS INTERNAL AdviseStdItems (lpdoc, hwndClient, lparam, lpfack)
  445. LPDOC lpdoc;
  446. HWND hwndClient;
  447. LONG lparam;
  448. BOOL FAR * lpfack;
  449. {
  450. HANDLE hopt = NULL;
  451. DDEADVISE FAR *lpopt;
  452. OLESTATUS retval = OLE_ERROR_MEMORY;
  453. hopt = (HANDLE) (LOWORD (lparam));
  454. if(!(lpopt = (DDEADVISE FAR *) GlobalLock (hopt)))
  455. goto errrtn;
  456. #ifdef FIREWALLS
  457. ASSERT ((ATOM) (HIWORD (lparam) == aStdDocName), "AdviseStdItem is not Documentname");
  458. #endif
  459. *lpfack = lpopt->fAckReq;
  460. retval = SetStdInfo (lpdoc, hwndClient, (LPSTR)"StdDocumentName", NULL);
  461. if (lpopt)
  462. GlobalUnlock (hopt);
  463. errrtn:
  464. if (retval == OLE_OK)
  465. // !!! make sure that we have to free the data for error case
  466. GlobalFree (hopt);
  467. return retval;
  468. }
  469. //AdviseData: This routine takes care of the DDEADVISE for a
  470. //particular object in given document. Creates a client strutcure
  471. //and attaches to the property list of the object window.
  472. OLESTATUS INTERNAL AdviseData (lpdoc, hwndClient, lparam, lpfack)
  473. LPDOC lpdoc;
  474. HWND hwndClient;
  475. LONG lparam;
  476. BOOL FAR * lpfack;
  477. {
  478. HANDLE hopt = NULL;
  479. DDEADVISE FAR *lpopt = NULL;
  480. int format = NULL;
  481. char buf[MAX_STR];
  482. int options;
  483. LPCLIENT lpclient;
  484. int retval = OLE_ERROR_MEMORY;
  485. HANDLE hclinfo = NULL;
  486. PCLINFO pclinfo = NULL;
  487. hopt = (HANDLE) (LOWORD (lparam));
  488. if(!(lpopt = (DDEADVISE FAR *) GlobalLock (hopt)))
  489. goto errRtn;
  490. if (!(HIWORD (lparam)))
  491. buf[0] = NULL;
  492. else
  493. GlobalGetAtomName ((ATOM)(HIWORD (lparam)), (LPSTR)buf, MAX_STR);
  494. // Scan for the advise options like "Close", "Save" etc
  495. // at the end of the item.
  496. if((retval = ScanItemOptions ((LPSTR)buf, (int far *)&options)) !=
  497. OLE_OK)
  498. goto errRtn;
  499. // Now get the corresponding object.
  500. retval = FindItem (lpdoc, (LPSTR)buf, (LPCLIENT FAR *)&lpclient);
  501. if (retval != OLE_OK)
  502. goto errRtn;
  503. if (!IsFormatAvailable (lpclient, lpopt->cfFormat)){
  504. retval = OLE_ERROR_DATATYPE; // this format is not supported;
  505. goto errRtn;
  506. }
  507. *lpfack = lpopt->fAckReq;
  508. // Create the client structure to be attcahed to the object.
  509. if (!(hclinfo = FindClient (lpclient->hwnd, hwndClient)))
  510. hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
  511. if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL){
  512. retval = OLE_ERROR_MEMORY;
  513. goto errRtn;
  514. }
  515. // Remember the client window (Needed for sending DATA later on
  516. // when the data change message comes from the server)
  517. pclinfo->hwnd = hwndClient;
  518. if (lpopt->cfFormat == (int)cfNative)
  519. pclinfo->bnative = TRUE;
  520. else
  521. pclinfo->format = lpopt->cfFormat;
  522. // Remeber the data transfer options.
  523. pclinfo->options |= (0x0001 << options);
  524. pclinfo->bdata = !lpopt->fDeferUpd;
  525. LocalUnlock (hclinfo);
  526. pclinfo = NULL;
  527. // if the entry exists already, delete it.
  528. DeleteClient (lpclient->hwnd, hwndClient);
  529. // Now add this client to item client list
  530. // !!! This error recovery is not correct.
  531. if(!AddClient (lpclient->hwnd, hwndClient, hclinfo))
  532. goto errRtn;
  533. errRtn:
  534. if (lpopt)
  535. GlobalUnlock (hopt);
  536. if (pclinfo)
  537. LocalUnlock (hclinfo);
  538. if (retval == OLE_OK) {
  539. // !!! make sure that we have to free the data
  540. GlobalFree (hopt);
  541. }else {
  542. if (hclinfo)
  543. LocalFree (hclinfo);
  544. }
  545. return retval;
  546. }
  547. BOOL INTERNAL IsFormatAvailable (lpclient, cfFormat)
  548. LPCLIENT lpclient;
  549. OLECLIPFORMAT cfFormat;
  550. {
  551. OLECLIPFORMAT cfNext = 0;
  552. do{
  553. #ifdef FIREWALLS
  554. if (!CheckPointer (lpclient->lpoleobject, WRITE_ACCESS))
  555. ASSERT (0, "Invalid LPOLEOBECT")
  556. else if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  557. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  558. else
  559. ASSERT (lpclient->lpoleobject->lpvtbl->EnumFormats,
  560. "Invalid pointer to EnumFormats method")
  561. #endif
  562. cfNext = (*lpclient->lpoleobject->lpvtbl->EnumFormats)
  563. (lpclient->lpoleobject, cfNext);
  564. if (cfNext == cfFormat)
  565. return TRUE;
  566. }while (cfNext != 0);
  567. return FALSE;
  568. }
  569. //ScanItemOptions: Scan for the item options like Close/Save etc.
  570. OLESTATUS INTERNAL ScanItemOptions (lpbuf, lpoptions)
  571. LPSTR lpbuf;
  572. int far *lpoptions;
  573. {
  574. ATOM aModifier;
  575. *lpoptions = OLE_CHANGED;
  576. while ( *lpbuf && *lpbuf != '/')
  577. {
  578. #if defined(FE_SB) //[J1]
  579. lpbuf = AnsiNext( lpbuf ); //[J1]
  580. #else //[J1]
  581. lpbuf++;
  582. #endif
  583. } //[J1]
  584. // no modifier same as /change
  585. if (*lpbuf == NULL)
  586. return OLE_OK;
  587. *lpbuf++ = NULL; // seperate out the item string
  588. // We are using this in the caller.
  589. if (!(aModifier = GlobalFindAtom (lpbuf)))
  590. return OLE_ERROR_SYNTAX;
  591. if (aModifier == aChange)
  592. return OLE_OK;
  593. // Is it a save?
  594. if (aModifier == aSave){
  595. *lpoptions = OLE_SAVED;
  596. return OLE_OK;
  597. }
  598. // Is it a Close?
  599. if (aModifier == aClose){
  600. *lpoptions = OLE_CLOSED;
  601. return OLE_OK;
  602. }
  603. // unknow modifier
  604. return OLE_ERROR_SYNTAX;
  605. }
  606. //RequestData: Sends data in response to a DDE Request message.
  607. // for agiven doc and an object.
  608. OLESTATUS INTERNAL RequestData (lpdoc, hwndClient, lparam, lphdde)
  609. LPDOC lpdoc;
  610. HWND hwndClient;
  611. LONG lparam;
  612. LPHANDLE lphdde;
  613. {
  614. OLESTATUS retval = OLE_OK;
  615. HANDLE hdata;
  616. LPCLIENT lpclient;
  617. char buf[6];
  618. // If edit environment Send data if we can
  619. if ((HIWORD (lparam)) == aEditItems)
  620. return RequestDataStd (lparam, lphdde);
  621. // Get the object.
  622. retval = FindItem (lpdoc, (LPSTR) MAKEINTATOM(HIWORD(lparam)),
  623. (LPCLIENT FAR *)&lpclient);
  624. if (retval != OLE_OK)
  625. goto errRtn;
  626. retval = OLE_ERROR_DATATYPE;
  627. if (!IsFormatAvailable (lpclient, (int)(LOWORD (lparam))))
  628. goto errRtn;
  629. // Now ask the item for the given format data
  630. #ifdef FIREWALLS
  631. ASSERT (lpclient->lpoleobject->lpvtbl->GetData,
  632. "Invalid pointer to GetData method")
  633. #endif
  634. MapToHexStr ((LPSTR)buf, hwndClient);
  635. SendDevInfo (lpclient, (LPSTR)buf);
  636. retval = (*lpclient->lpoleobject->lpvtbl->GetData) (lpclient->lpoleobject,
  637. (int)(LOWORD (lparam)), (LPHANDLE)& hdata);
  638. if (retval != OLE_OK)
  639. goto errRtn;
  640. if (LOWORD(lparam) == CF_METAFILEPICT)
  641. ChangeOwner (hdata);
  642. // Duplicate the DDE data
  643. if(MakeDDEData(hdata, (int)(LOWORD (lparam)), lphdde, TRUE)){
  644. // !!! Why do we have to duplicate the atom
  645. DuplicateAtom ((ATOM)(HIWORD (lparam)));
  646. return OLE_OK;
  647. }
  648. else
  649. return OLE_ERROR_MEMORY;
  650. errRtn:
  651. return retval;
  652. }
  653. //MakeDDEData: Create a Global DDE data handle from the server
  654. // app data handle.
  655. BOOL INTERNAL MakeDDEData (hdata, format, lph, fResponse)
  656. HANDLE hdata;
  657. LPHANDLE lph;
  658. int format;
  659. BOOL fResponse;
  660. {
  661. DWORD size;
  662. HANDLE hdde = NULL;
  663. DDEDATA FAR *lpdata= NULL;
  664. BOOL bnative;
  665. LPSTR lpdst;
  666. LPSTR lpsrc;
  667. if (!hdata) {
  668. *lph = NULL;
  669. return TRUE;
  670. }
  671. if (bnative = !(format == CF_METAFILEPICT || format == CF_DIB ||
  672. format == CF_BITMAP))
  673. size = GlobalSize (hdata) + sizeof (DDEDATA);
  674. else
  675. size = sizeof (LONG) + sizeof (DDEDATA);
  676. hdde = (HANDLE) GlobalAlloc (GMEM_DDESHARE | GMEM_ZEROINIT, size);
  677. if (hdde == NULL || (lpdata = (DDEDATA FAR *) GlobalLock (hdde)) == NULL)
  678. goto errRtn;
  679. // set the data otions. Ask the client to delete
  680. // it always.
  681. lpdata->fRelease = TRUE; // release the data
  682. lpdata->cfFormat = format;
  683. lpdata->fResponse = fResponse;
  684. if (!bnative)
  685. // If not native, stick in the handle what the server gave us.
  686. *(LPHANDLE)lpdata->Value = hdata;
  687. else {
  688. // copy the native data junk here.
  689. lpdst = (LPSTR)lpdata->Value;
  690. if(!(lpsrc = (LPSTR)GlobalLock (hdata)))
  691. goto errRtn;
  692. size -= sizeof (DDEDATA);
  693. UtilMemCpy (lpdst, lpsrc, size);
  694. GlobalUnlock (hdata);
  695. GlobalFree (hdata);
  696. }
  697. GlobalUnlock (hdde);
  698. *lph = hdde;
  699. return TRUE;
  700. errRtn:
  701. if (lpdata)
  702. GlobalUnlock (hdde);
  703. if (hdde)
  704. GlobalFree (hdde);
  705. if (bnative)
  706. GlobalFree (hdata);
  707. return FALSE;
  708. }
  709. // ItemCallback: Calback routine for the server to inform the
  710. // data changes. When the change message is received, DDE data
  711. // message is sent to each of the clients depending on the
  712. // options.
  713. int FAR PASCAL ItemCallback (lpoleclient, msg, lpoleobject)
  714. LPOLECLIENT lpoleclient;
  715. WORD msg; // notification message
  716. LPOLEOBJECT lpoleobject;
  717. {
  718. LPCLIENT lpclient;
  719. int retval = OLE_OK;
  720. HANDLE hdata = NULL;
  721. LPSTR lpdata = NULL;
  722. LPDOC lpdoc;
  723. HWND hStdWnd;
  724. lpclient = (LPCLIENT)lpoleclient;
  725. lpdoc = (LPDOC)GetWindowLong (GetParent (lpclient->hwnd), 0);
  726. if (msg == OLE_RENAMED) {
  727. #ifdef FIREWALLS
  728. if (!CheckPointer (lpoleobject, WRITE_ACCESS))
  729. ASSERT (0, "Invalid lpoleobject")
  730. else if (!CheckPointer (lpoleobject->lpvtbl, WRITE_ACCESS))
  731. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  732. else
  733. ASSERT (lpoleobject->lpvtbl->GetData,
  734. "Invalid pointer to GetData method")
  735. #endif
  736. if (IsFormatAvailable (lpclient, cfLink)) {
  737. // Get the link data.
  738. retval = (*lpoleobject->lpvtbl->GetData) (lpoleobject,
  739. (int)cfLink, (LPHANDLE)&hdata);
  740. }
  741. else {
  742. if(IsFormatAvailable (lpclient, cfOwnerLink)) {
  743. // Get the link data.
  744. retval = (*lpoleobject->lpvtbl->GetData) (lpoleobject,
  745. (int)cfOwnerLink, (LPHANDLE)& hdata);
  746. #ifdef FIREWALLS
  747. ASSERT (retval != OLE_BUSY, "Getdata returns with OLE_BUSY")
  748. #endif
  749. } else
  750. retval = OLE_ERROR_DATATYPE;
  751. }
  752. if (retval != OLE_OK)
  753. goto errrtn;
  754. if (!(lpdata = (LPSTR)GlobalLock (hdata)))
  755. goto errrtn;
  756. if (lpdoc->aDoc) {
  757. GlobalDeleteAtom (lpdoc->aDoc);
  758. lpdoc->aDoc = NULL;
  759. }
  760. // Move the string to the beginning and still terminated by null;
  761. lstrcpy (lpdata, lpdata + lstrlen (lpdata) + 1);
  762. lpdoc->aDoc = GlobalAddAtom (lpdata);
  763. // Now make the DDE data block
  764. GlobalUnlock (hdata);
  765. lpdata = NULL;
  766. // find if any StdDocName item is present at all
  767. if (!(hStdWnd = SearchItem (lpdoc, (LPSTR) MAKEINTATOM(aStdDocName))))
  768. GlobalFree (hdata);
  769. else {
  770. // hdata is freed by Makeddedata
  771. if (!MakeDDEData (hdata, (int)cfBinary, (LPHANDLE)&hddeRename,
  772. FALSE)) {
  773. retval = OLE_ERROR_MEMORY;
  774. goto errrtn;
  775. }
  776. EnumProps(hStdWnd, lpSendRenameMsg);
  777. // post all the messages with yield which have been collected in enum
  778. // UnblockPostMsgs (hStdWnd, FALSE);
  779. GlobalFree (hddeRename);
  780. }
  781. // static. Avoid this. This may not cause any problems for now.
  782. // if there is any better way, change it.
  783. hwndRename = hStdWnd;
  784. // Post termination for each of the doc clients.
  785. EnumProps (lpdoc->hwnd, lpEnumForTerminate);
  786. lpdoc->fEmbed = FALSE;
  787. // post all the messages with yield which have been collected in enum
  788. // UnblockPostMsgs (lpdoc->hwnd, FALSE);
  789. return OLE_OK;
  790. errrtn:
  791. if (lpdata)
  792. GlobalUnlock (hdata);
  793. if (hdata)
  794. GlobalFree (hdata);
  795. return retval;
  796. } else {
  797. // !!! any better way to do instead of putting in static
  798. // (There may not be any problems since we are not allowing
  799. // any messages to get thru while we are posting messages).
  800. if ((enummsg = msg) == OLE_SAVED)
  801. fAdviseSaveItem = FALSE;
  802. enumlpoleobject = lpoleobject;
  803. #ifdef FIREWALLS
  804. ASSERT (lpclient->hwnd && IsWindowValid (lpclient->hwnd), " Not valid object")
  805. #endif
  806. // Enumerate all the clients and send DDE_DATA if necessary.
  807. EnumProps(lpclient->hwnd, lpSendDataMsg);
  808. // post all the messages with yield which have been collected in enum
  809. // UnblockPostMsgs (lpclient->hwnd, FALSE);
  810. if ((msg == OLE_SAVED) && lpdoc->fEmbed && !fAdviseSaveItem)
  811. return OLE_ERROR_CANT_UPDATE_CLIENT;
  812. return OLE_OK;
  813. }
  814. }
  815. BOOL FAR PASCAL EnumForTerminate (hwnd, lpstr, hdata)
  816. HWND hwnd;
  817. LPSTR lpstr;
  818. HANDLE hdata;
  819. {
  820. LPDOC lpdoc;
  821. lpdoc = (LPDOC)GetWindowLong (hwnd , 0);
  822. // This client is in the rename list. So, no terminate
  823. if(hwndRename && FindClient (hwndRename, (HWND)hdata))
  824. return TRUE;
  825. if (PostMessageToClientWithBlock ((HWND)hdata, WM_DDE_TERMINATE, hwnd, NULL))
  826. lpdoc->termNo++;
  827. //DeleteClient (hwnd, (HWND)hdata);
  828. //lpdoc->cClients--;
  829. return TRUE;
  830. }
  831. BOOL FAR PASCAL SendRenameMsg (hwnd, lpstr, hclinfo)
  832. HWND hwnd;
  833. LPSTR lpstr;
  834. HANDLE hclinfo;
  835. {
  836. ATOM aData = NULL;
  837. HANDLE hdde = NULL;
  838. PCLINFO pclinfo = NULL;
  839. HWND hwndClient;
  840. if (!(pclinfo = (PCLINFO) LocalLock (hclinfo)))
  841. goto errrtn;
  842. // Make the item atom with the options.
  843. aData = DuplicateAtom (aStdDocName);
  844. hdde = DuplicateData (hddeRename);
  845. hwndClient = pclinfo->hwnd;
  846. LocalUnlock (hclinfo);
  847. // Post the message
  848. if (!PostMessageToClientWithBlock (hwndClient, WM_DDE_DATA, (HWND)GetParent (hwnd),
  849. MAKELONG (hdde, aData)))
  850. goto errrtn;
  851. return TRUE;
  852. errrtn:
  853. if (hdde)
  854. GlobalFree (hdde);
  855. if (aData)
  856. GlobalDeleteAtom (aData);
  857. return TRUE;
  858. }
  859. //SendDataMsg: Send data to the clients, if the data change options
  860. //match the data advise options.
  861. BOOL FAR PASCAL SendDataMsg (hwnd, lpstr, hclinfo)
  862. HWND hwnd;
  863. LPSTR lpstr;
  864. HANDLE hclinfo;
  865. {
  866. PCLINFO pclinfo = NULL;
  867. HANDLE hdde = NULL;
  868. ATOM aData = NULL;
  869. int retval;
  870. HANDLE hdata;
  871. LPCLIENT lpclient;
  872. if (!(pclinfo = (PCLINFO) LocalLock (hclinfo)))
  873. goto errRtn;
  874. lpclient = (LPCLIENT)GetWindowLong (hwnd, 0);
  875. #ifdef FIREWALLS
  876. ASSERT ((CheckPointer(lpclient, WRITE_ACCESS)),
  877. "In Item the client handle missing")
  878. #endif
  879. // if the client dead, then no message
  880. if (!IsWindowValid(pclinfo->hwnd))
  881. goto errRtn;
  882. if (pclinfo->options & (0x0001 << enummsg)) {
  883. fAdviseSaveItem = TRUE;
  884. SendDevInfo (lpclient, lpstr);
  885. // send message if the client needs data for every change or
  886. // only for the selective ones he wants.
  887. // now look for the data option.
  888. if (pclinfo->bnative){
  889. // prepare native data
  890. if (pclinfo->bdata){
  891. // Wants the data with DDE_DATA message
  892. // Get native data from the server.
  893. #ifdef FIREWALLS
  894. if (!CheckPointer (enumlpoleobject, WRITE_ACCESS))
  895. ASSERT (0, "Invalid LPOLEOBECT")
  896. else if (!CheckPointer (enumlpoleobject->lpvtbl,WRITE_ACCESS))
  897. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  898. else
  899. ASSERT (enumlpoleobject->lpvtbl->GetData,
  900. "Invalid pointer to GetData method")
  901. #endif
  902. retval = (*enumlpoleobject->lpvtbl->GetData) (enumlpoleobject,
  903. (int)cfNative, (LPHANDLE)& hdata);
  904. #ifdef FIREWALLS
  905. ASSERT (retval != OLE_BUSY, "Getdata returns with OLE_BUSY");
  906. #endif
  907. if (retval != OLE_OK)
  908. goto errRtn;
  909. // Prepare the DDE data block.
  910. if(!MakeDDEData (hdata, (int)cfNative, (LPHANDLE)&hdde, FALSE))
  911. goto errRtn;
  912. }
  913. // Make the item atom with the options.
  914. aData = MakeDataAtom (lpclient->aItem, enummsg);
  915. // Post the message
  916. if (!PostMessageToClientWithBlock (pclinfo->hwnd, WM_DDE_DATA,
  917. (HWND)GetParent (hwnd), MAKELONG (hdde, aData)))
  918. goto errRtn;
  919. hdde = NULL;
  920. aData = NULL;
  921. }
  922. // Now post the data for the disply format
  923. if (pclinfo->format){
  924. if (pclinfo->bdata){
  925. #ifdef FIREWALLS
  926. if (!CheckPointer (enumlpoleobject, WRITE_ACCESS))
  927. ASSERT (0, "Invalid LPOLEOBECT")
  928. else if (!CheckPointer (enumlpoleobject->lpvtbl,WRITE_ACCESS))
  929. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  930. else
  931. ASSERT (enumlpoleobject->lpvtbl->GetData,
  932. "Invalid pointer to GetData method")
  933. #endif
  934. retval = (*enumlpoleobject->lpvtbl->GetData) (enumlpoleobject,
  935. pclinfo->format, (LPHANDLE)& hdata);
  936. #ifdef FIREWALLS
  937. ASSERT (retval != OLE_BUSY, "Getdata returns with OLE_BUSY");
  938. #endif
  939. if (retval != OLE_OK)
  940. goto errRtn;
  941. if (pclinfo->format == CF_METAFILEPICT)
  942. ChangeOwner (hdata);
  943. if(!MakeDDEData (hdata, pclinfo->format, (LPHANDLE)&hdde, FALSE))
  944. goto errRtn;
  945. }
  946. // atom is deleted. So, we need to duplicate for every post
  947. aData = MakeDataAtom (lpclient->aItem, enummsg);
  948. // now post the message to the client;
  949. if (!PostMessageToClientWithBlock (pclinfo->hwnd, WM_DDE_DATA,
  950. (HWND)GetParent (hwnd), MAKELONG (hdde, aData)))
  951. goto errRtn;
  952. hdde = NULL;
  953. aData = NULL;
  954. }
  955. }
  956. errRtn:
  957. if (pclinfo)
  958. LocalUnlock (hclinfo);
  959. if (hdde)
  960. GlobalFree (hdde);
  961. if (aData)
  962. GlobalDeleteAtom (aData);
  963. return TRUE;
  964. }
  965. // IsAdviseStdItems: returns true if the item is one of the standard items
  966. // StdDocName;
  967. BOOL INTERNAL IsAdviseStdItems (aItem)
  968. ATOM aItem;
  969. {
  970. if ( aItem == aStdDocName)
  971. return TRUE;
  972. else
  973. return FALSE;
  974. }
  975. // GetStdItemIndex: returns index to Stditems in the "stdStrTable" if the item
  976. // is one of the standard items StdHostNames, StdTargetDevice,
  977. // StdDocDimensions, StdColorScheme
  978. int INTERNAL GetStdItemIndex (aItem)
  979. ATOM aItem;
  980. {
  981. char str[MAX_STR];
  982. if (!aItem)
  983. return NULL;
  984. if (!GlobalGetAtomName (aItem, (LPSTR) str, MAX_STR))
  985. return NULL;
  986. if (!lstrcmpi (str, stdStrTable[STDTARGETDEVICE]))
  987. return STDTARGETDEVICE;
  988. else if (!lstrcmpi (str, stdStrTable[STDHOSTNAMES]))
  989. return STDHOSTNAMES;
  990. else if (!lstrcmpi (str, stdStrTable[STDDOCDIMENSIONS]))
  991. return STDDOCDIMENSIONS;
  992. else if (!lstrcmpi (str, stdStrTable[STDCOLORSCHEME]))
  993. return STDCOLORSCHEME;
  994. return NULL;
  995. }
  996. // PokeStdItems: Pokes the data for the standard items.
  997. // For StdHostnames, StdDocDimensions and SetColorScheme the data is
  998. // sent immediately and for the the StdTargetDeviceinfo the
  999. // data is set in each client block and the data is sent just
  1000. // before the GetData call for rendering the right data.
  1001. OLESTATUS INTERNAL PokeStdItems (lpdoc, hwndClient, lparam)
  1002. LPDOC lpdoc;
  1003. HWND hwndClient;
  1004. LONG lparam;
  1005. {
  1006. int index;
  1007. DDEDATA FAR * lpdata = NULL;
  1008. HANDLE hdata = NULL;
  1009. HANDLE hnew = NULL;
  1010. LPOLESERVERDOC lpoledoc;
  1011. LPHOSTNAMES lphostnames;
  1012. OLESTATUS retval = OLE_ERROR_MEMORY;
  1013. int format;
  1014. BOOL fRelease;
  1015. RECT rcDoc;
  1016. index = HIWORD(lparam);
  1017. hdata = (HANDLE)(LOWORD (lparam));
  1018. if(!(hdata && (lpdata = (DDEDATA FAR *)GlobalLock (hdata))))
  1019. goto errRtn;
  1020. format = lpdata->cfFormat;
  1021. fRelease = lpdata->fRelease;
  1022. #ifdef FIREWALSS
  1023. ASSERT (format == (int)cfBinary, "Format is not binary");
  1024. #endif
  1025. // we have extracted the data successfully.
  1026. lpoledoc = lpdoc->lpoledoc;
  1027. #ifdef FIREWALLS
  1028. if (!CheckPointer (lpoledoc, WRITE_ACCESS))
  1029. ASSERT (0, "Invalid LPOLESERVERDOC")
  1030. else if (!CheckPointer (lpoledoc->lpvtbl, WRITE_ACCESS))
  1031. ASSERT (0, "Invalid LPOLESERVERDOCVTBL")
  1032. #endif
  1033. if (index == STDHOSTNAMES){
  1034. lphostnames = (LPHOSTNAMES)lpdata->Value;
  1035. #ifdef FIREWALLS
  1036. ASSERT (lpoledoc->lpvtbl->SetHostNames,
  1037. "Invalid pointer to SetHostNames method")
  1038. #endif
  1039. retval = (*lpoledoc->lpvtbl->SetHostNames)(lpdoc->lpoledoc,
  1040. (LPSTR)lphostnames->data,
  1041. ((LPSTR)lphostnames->data) +
  1042. lphostnames->documentNameOffset);
  1043. goto end;
  1044. }
  1045. if (index == STDDOCDIMENSIONS){
  1046. #ifdef FIREWALLS
  1047. ASSERT (lpoledoc->lpvtbl->SetDocDimensions,
  1048. "Invalid pointer to SetDocDimensions method")
  1049. #endif
  1050. rcDoc.left = 0;
  1051. rcDoc.top = ((LPRECT)(lpdata->Value))->top;
  1052. rcDoc.bottom = 0;
  1053. rcDoc.right = ((LPRECT)lpdata->Value)->left;
  1054. retval = (*lpoledoc->lpvtbl->SetDocDimensions)(lpdoc->lpoledoc,
  1055. (LPRECT)&rcDoc);
  1056. goto end;
  1057. }
  1058. if (index == STDCOLORSCHEME) {
  1059. #ifdef FIREWALLS
  1060. ASSERT (lpoledoc->lpvtbl->SetColorScheme,
  1061. "Invalid pointer to SetColorScheme method")
  1062. #endif
  1063. retval = (*lpoledoc->lpvtbl->SetColorScheme)(lpdoc->lpoledoc,
  1064. (LPLOGPALETTE) lpdata->Value);
  1065. goto end;
  1066. }
  1067. #ifdef FIREWALLS
  1068. ASSERT (index == STDTARGETDEVICE, "Unknown standard item");
  1069. #endif
  1070. // case of the printer decvice info
  1071. if (!(hnew = MakeItemData ((DDEPOKE FAR *)lpdata, hdata, format)))
  1072. goto errRtn;
  1073. // Go thru the all the items lists for this doc and replace the
  1074. // printer device info information.
  1075. // Free the block we duplicated.
  1076. retval = SetStdInfo (lpdoc, hwndClient,
  1077. (LPSTR) (MAKELONG(STDTARGETDEVICE,0)),hnew);
  1078. end:
  1079. errRtn:
  1080. if (hnew)
  1081. // can only be global memory block
  1082. GlobalFree (hnew);
  1083. if (lpdata) {
  1084. GlobalUnlock (hdata);
  1085. if (retval == OLE_OK && fRelease)
  1086. GlobalFree (hdata);
  1087. }
  1088. return retval;
  1089. }
  1090. // SetStdInfo: Sets the targetdevice info. Creates a client
  1091. // for "StdTargetDevice". This item is created only within the
  1092. // lib and it is never visible in server app. When the change
  1093. // message comes from the server app, before we ask for
  1094. // the data, we send the targetdevice info if there is
  1095. // info for the client whom we are trying to send the data
  1096. // on advise.
  1097. int INTERNAL SetStdInfo (lpdoc, hwndClient, lpitemname, hdata)
  1098. LPDOC lpdoc;
  1099. HWND hwndClient;
  1100. LPSTR lpitemname;
  1101. HANDLE hdata;
  1102. {
  1103. HWND hwnd;
  1104. HANDLE hclinfo = NULL;
  1105. PCLINFO pclinfo = NULL;
  1106. LPCLIENT lpclient;
  1107. OLESTATUS retval = OLE_OK;
  1108. // first create/find the StdTargetDeviceItem.
  1109. if ((hwnd = SearchItem (lpdoc, lpitemname))
  1110. == NULL){
  1111. retval = RegisterItem ((LHDOC)lpdoc, lpitemname,
  1112. (LPCLIENT FAR *)&lpclient, FALSE);
  1113. if (retval != OLE_OK)
  1114. goto errRtn;
  1115. hwnd = lpclient->hwnd;
  1116. }
  1117. #ifdef FIREWALLS
  1118. ASSERT (retval == OLE_OK, "No StdTragetDevice or StdDocname item");
  1119. #endif
  1120. if(hclinfo = FindClient (hwnd, hwndClient)){
  1121. if (pclinfo = (PCLINFO) LocalLock (hclinfo)){
  1122. if (pclinfo->hdevInfo)
  1123. GlobalFree (pclinfo->hdevInfo);
  1124. pclinfo->bnewDevInfo = TRUE;
  1125. if (hdata)
  1126. pclinfo->hdevInfo = DuplicateData (hdata);
  1127. else
  1128. pclinfo->hdevInfo = NULL;
  1129. pclinfo->hwnd = hwndClient;
  1130. LocalUnlock (hclinfo);
  1131. // We do not have to reset the client because we did not
  1132. // change the handle it self.
  1133. }
  1134. } else {
  1135. // Create the client structure to be attcahed to the object.
  1136. hclinfo = LocalAlloc (LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof (CLINFO));
  1137. if (hclinfo == NULL || (pclinfo = (PCLINFO) LocalLock (hclinfo)) == NULL)
  1138. goto errRtn;
  1139. pclinfo->bnewDevInfo = TRUE;
  1140. if (hdata)
  1141. pclinfo->hdevInfo = DuplicateData (hdata);
  1142. else
  1143. pclinfo->hdevInfo = NULL;
  1144. pclinfo->hwnd = hwndClient;
  1145. LocalUnlock (hclinfo);
  1146. // Now add this client to item client list
  1147. // !!! This error recovery is not correct.
  1148. if (!AddClient (hwnd, hwndClient, hclinfo))
  1149. goto errRtn;
  1150. }
  1151. return OLE_OK;
  1152. errRtn:
  1153. if (pclinfo)
  1154. LocalUnlock (hclinfo);
  1155. if (hclinfo)
  1156. LocalFree (hclinfo);
  1157. return OLE_ERROR_MEMORY;
  1158. }
  1159. // SendDevInfo: Sends targetdevice info to the the object.
  1160. // Caches the last targetdevice info sent to the object.
  1161. // If the targetdevice block is same as the one in the
  1162. // cache, then no targetdevice info is sent.
  1163. // (!!! There might be some problem here getting back
  1164. // the same global handle).
  1165. void INTERNAL SendDevInfo (lpclient, lppropname)
  1166. LPCLIENT lpclient;
  1167. LPSTR lppropname;
  1168. {
  1169. HANDLE hclinfo = NULL;
  1170. PCLINFO pclinfo = NULL;
  1171. HANDLE hdata;
  1172. OLESTATUS retval;
  1173. HWND hwnd;
  1174. LPDOC lpdoc;
  1175. lpdoc = (LPDOC)GetWindowLong (GetParent (lpclient->hwnd), 0);
  1176. // find if any StdTargetDeviceInfo item is present at all
  1177. hwnd = SearchItem (lpdoc, (LPSTR) (MAKELONG(STDTARGETDEVICE, 0)));
  1178. if (hwnd == NULL)
  1179. return;
  1180. hclinfo = GetProp (hwnd, lppropname);
  1181. // This client has not set any target device info. no need to send
  1182. // any stdtargetdevice info
  1183. if (hclinfo != NULL) {
  1184. if (!(pclinfo = (PCLINFO)LocalLock (hclinfo)))
  1185. goto end;
  1186. // if we cached it, do not send it again.
  1187. if ((!pclinfo->bnewDevInfo) && pclinfo->hdevInfo == lpclient->hdevInfo)
  1188. goto end;
  1189. pclinfo->bnewDevInfo = FALSE;
  1190. if(!(hdata = DuplicateData (pclinfo->hdevInfo)))
  1191. goto end;
  1192. } else {
  1193. // already screen
  1194. if (!lpclient->hdevInfo)
  1195. goto end;
  1196. //for screen send NULL.
  1197. hdata = NULL;
  1198. }
  1199. // Now send the targetdevice info
  1200. #ifdef FIREWALLS
  1201. if (!CheckPointer (lpclient->lpoleobject, WRITE_ACCESS))
  1202. ASSERT (0, "Invalid LPOLEOBECT")
  1203. else if (!CheckPointer (lpclient->lpoleobject->lpvtbl, WRITE_ACCESS))
  1204. ASSERT (0, "Invalid LPOLEOBJECTVTBL")
  1205. else
  1206. ASSERT (lpclient->lpoleobject->lpvtbl->SetTargetDevice,
  1207. "Invalid pointer to SetTargetDevice method")
  1208. #endif
  1209. retval = (*lpclient->lpoleobject->lpvtbl->SetTargetDevice)
  1210. (lpclient->lpoleobject, hdata);
  1211. if (retval == OLE_OK) {
  1212. if (pclinfo)
  1213. lpclient->hdevInfo = pclinfo->hdevInfo;
  1214. else
  1215. lpclient->hdevInfo = NULL;
  1216. }
  1217. // !!! error case who frees the data?'
  1218. end:
  1219. if (pclinfo)
  1220. LocalUnlock (hclinfo);
  1221. return;
  1222. }
  1223. void ChangeOwner (hmfp)
  1224. HANDLE hmfp;
  1225. {
  1226. LPMETAFILEPICT lpmfp;
  1227. if (lpmfp = (LPMETAFILEPICT) GlobalLock (hmfp)) {
  1228. if (bWin30)
  1229. GiveToGDI (lpmfp->hMF);
  1230. else {
  1231. if (lpfnSetMetaFileBitsBetter)
  1232. (*lpfnSetMetaFileBitsBetter) (lpmfp->hMF);
  1233. }
  1234. GlobalUnlock (hmfp);
  1235. }
  1236. }
  1237. HANDLE INTERNAL MakeItemData (lpPoke, hPoke, cfFormat)
  1238. DDEPOKE FAR * lpPoke;
  1239. HANDLE hPoke;
  1240. OLECLIPFORMAT cfFormat;
  1241. {
  1242. HANDLE hnew;
  1243. LPSTR lpnew;
  1244. DWORD dwSize;
  1245. if (cfFormat == CF_METAFILEPICT)
  1246. return DuplicateMetaFile (*(LPHANDLE)lpPoke->Value);
  1247. if (cfFormat == CF_BITMAP)
  1248. return DuplicateBitmap (*(LPHANDLE)lpPoke->Value);
  1249. if (cfFormat == CF_DIB)
  1250. return DuplicateData (*(LPHANDLE)lpPoke->Value);
  1251. // Now we are dealing with normal case
  1252. if (!(dwSize = GlobalSize (hPoke)))
  1253. return NULL;
  1254. dwSize = dwSize - sizeof (DDEPOKE) + sizeof(BYTE);
  1255. if (hnew = GlobalAlloc (GMEM_MOVEABLE, dwSize)) {
  1256. if (lpnew = GlobalLock (hnew)) {
  1257. UtilMemCpy (lpnew, (LPSTR) lpPoke->Value, dwSize);
  1258. GlobalUnlock (hnew);
  1259. }
  1260. else {
  1261. GlobalFree (hnew);
  1262. hnew = NULL;
  1263. }
  1264. }
  1265. return hnew;
  1266. }
  1267. HANDLE INTERNAL DuplicateMetaFile (hSrcData)
  1268. HANDLE hSrcData;
  1269. {
  1270. LPMETAFILEPICT lpSrcMfp;
  1271. LPMETAFILEPICT lpDstMfp = NULL;
  1272. HANDLE hMF = NULL;
  1273. HANDLE hDstMfp = NULL;
  1274. if (!(lpSrcMfp = (LPMETAFILEPICT) GlobalLock(hSrcData)))
  1275. return NULL;
  1276. GlobalUnlock (hSrcData);
  1277. if (!(hMF = CopyMetaFile (lpSrcMfp->hMF, NULL)))
  1278. return NULL;
  1279. if (!(hDstMfp = GlobalAlloc (GMEM_MOVEABLE, sizeof(METAFILEPICT))))
  1280. goto errMfp;
  1281. if (!(lpDstMfp = (LPMETAFILEPICT) GlobalLock (hDstMfp)))
  1282. goto errMfp;
  1283. GlobalUnlock (hDstMfp);
  1284. *lpDstMfp = *lpSrcMfp;
  1285. lpDstMfp->hMF = hMF;
  1286. return hDstMfp;
  1287. errMfp:
  1288. if (hMF)
  1289. DeleteMetaFile (hMF);
  1290. if (hDstMfp)
  1291. GlobalFree (hDstMfp);
  1292. return NULL;
  1293. }
  1294. HBITMAP INTERNAL DuplicateBitmap (hold)
  1295. HBITMAP hold;
  1296. {
  1297. HBITMAP hnew;
  1298. HANDLE hMem;
  1299. LPSTR lpMem;
  1300. LONG retVal = TRUE;
  1301. DWORD dwSize;
  1302. BITMAP bm;
  1303. // !!! another way to duplicate the bitmap
  1304. GetObject (hold, sizeof(BITMAP), (LPSTR) &bm);
  1305. dwSize = ((DWORD) bm.bmHeight) * ((DWORD) bm.bmWidthBytes) *
  1306. ((DWORD) bm.bmPlanes) * ((DWORD) bm.bmBitsPixel);
  1307. if (!(hMem = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwSize)))
  1308. return NULL;
  1309. if (!(lpMem = GlobalLock (hMem))){
  1310. GlobalFree (hMem);
  1311. return NULL;
  1312. }
  1313. GetBitmapBits (hold, dwSize, lpMem);
  1314. if (hnew = CreateBitmap (bm.bmWidth, bm.bmHeight,
  1315. bm.bmPlanes, bm.bmBitsPixel, NULL))
  1316. retVal = SetBitmapBits (hnew, dwSize, lpMem);
  1317. GlobalUnlock (hMem);
  1318. GlobalFree (hMem);
  1319. if (hnew && (!retVal)) {
  1320. DeleteObject (hnew);
  1321. hnew = NULL;
  1322. }
  1323. return hnew;
  1324. }