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.

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