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.

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