1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * DDEML library
3*c2c66affSColin Finck *
4*c2c66affSColin Finck * Copyright 1997 Alexandre Julliard
5*c2c66affSColin Finck * Copyright 1997 Len White
6*c2c66affSColin Finck * Copyright 1999 Keith Matthews
7*c2c66affSColin Finck * Copyright 2000 Corel
8*c2c66affSColin Finck * Copyright 2001 Eric Pouech
9*c2c66affSColin Finck * Copyright 2004, 2005 Dmitry Timoshkov
10*c2c66affSColin Finck *
11*c2c66affSColin Finck * This library is free software; you can redistribute it and/or
12*c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
13*c2c66affSColin Finck * License as published by the Free Software Foundation; either
14*c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
15*c2c66affSColin Finck *
16*c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
17*c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19*c2c66affSColin Finck * Lesser General Public License for more details.
20*c2c66affSColin Finck *
21*c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
22*c2c66affSColin Finck * License along with this library; if not, write to the Free Software
23*c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24*c2c66affSColin Finck */
25*c2c66affSColin Finck
26*c2c66affSColin Finck #include <user32.h>
27*c2c66affSColin Finck
28*c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(ddeml);
29*c2c66affSColin Finck
30*c2c66affSColin Finck static LRESULT CALLBACK WDML_ClientProc(HWND, UINT, WPARAM, LPARAM); /* only for one client, not conv list */
31*c2c66affSColin Finck const char WDML_szClientConvClassA[] = "DDEMLAnsiClient";
32*c2c66affSColin Finck const WCHAR WDML_szClientConvClassW[] = L"DDEMLUnicodeClient";
33*c2c66affSColin Finck
34*c2c66affSColin Finck /******************************************************************************
35*c2c66affSColin Finck * DdeConnectList [USER32.@] Establishes conversation with DDE servers
36*c2c66affSColin Finck *
37*c2c66affSColin Finck * PARAMS
38*c2c66affSColin Finck * idInst [I] Instance identifier
39*c2c66affSColin Finck * hszService [I] Handle to service name string
40*c2c66affSColin Finck * hszTopic [I] Handle to topic name string
41*c2c66affSColin Finck * hConvList [I] Handle to conversation list
42*c2c66affSColin Finck * pCC [I] Pointer to structure with context data
43*c2c66affSColin Finck *
44*c2c66affSColin Finck * RETURNS
45*c2c66affSColin Finck * Success: Handle to new conversation list
46*c2c66affSColin Finck * Failure: 0
47*c2c66affSColin Finck */
DdeConnectList(DWORD idInst,HSZ hszService,HSZ hszTopic,HCONVLIST hConvList,PCONVCONTEXT pCC)48*c2c66affSColin Finck HCONVLIST WINAPI DdeConnectList(DWORD idInst, HSZ hszService, HSZ hszTopic,
49*c2c66affSColin Finck HCONVLIST hConvList, PCONVCONTEXT pCC)
50*c2c66affSColin Finck {
51*c2c66affSColin Finck FIXME("(%d,%p,%p,%p,%p): stub\n", idInst, hszService, hszTopic, hConvList, pCC);
52*c2c66affSColin Finck return (HCONVLIST)1;
53*c2c66affSColin Finck }
54*c2c66affSColin Finck
55*c2c66affSColin Finck /*****************************************************************
56*c2c66affSColin Finck * DdeQueryNextServer [USER32.@]
57*c2c66affSColin Finck */
DdeQueryNextServer(HCONVLIST hConvList,HCONV hConvPrev)58*c2c66affSColin Finck HCONV WINAPI DdeQueryNextServer(HCONVLIST hConvList, HCONV hConvPrev)
59*c2c66affSColin Finck {
60*c2c66affSColin Finck FIXME("(%p,%p): stub\n", hConvList, hConvPrev);
61*c2c66affSColin Finck return 0;
62*c2c66affSColin Finck }
63*c2c66affSColin Finck
64*c2c66affSColin Finck /******************************************************************************
65*c2c66affSColin Finck * DdeDisconnectList [USER32.@] Destroys list and terminates conversations
66*c2c66affSColin Finck *
67*c2c66affSColin Finck *
68*c2c66affSColin Finck * PARAMS
69*c2c66affSColin Finck * hConvList [I] Handle to conversation list
70*c2c66affSColin Finck *
71*c2c66affSColin Finck * RETURNS
72*c2c66affSColin Finck * Success: TRUE
73*c2c66affSColin Finck * Failure: FALSE
74*c2c66affSColin Finck */
DdeDisconnectList(HCONVLIST hConvList)75*c2c66affSColin Finck BOOL WINAPI DdeDisconnectList(HCONVLIST hConvList)
76*c2c66affSColin Finck {
77*c2c66affSColin Finck FIXME("(%p): stub\n", hConvList);
78*c2c66affSColin Finck return TRUE;
79*c2c66affSColin Finck }
80*c2c66affSColin Finck
81*c2c66affSColin Finck /*****************************************************************
82*c2c66affSColin Finck * DdeConnect (USER32.@)
83*c2c66affSColin Finck */
DdeConnect(DWORD idInst,HSZ hszService,HSZ hszTopic,PCONVCONTEXT pCC)84*c2c66affSColin Finck HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
85*c2c66affSColin Finck PCONVCONTEXT pCC)
86*c2c66affSColin Finck {
87*c2c66affSColin Finck HWND hwndClient;
88*c2c66affSColin Finck WDML_INSTANCE* pInstance;
89*c2c66affSColin Finck WDML_CONV* pConv;
90*c2c66affSColin Finck ATOM aSrv = 0, aTpc = 0;
91*c2c66affSColin Finck
92*c2c66affSColin Finck TRACE("(0x%x,%p,%p,%p)\n", idInst, hszService, hszTopic, pCC);
93*c2c66affSColin Finck
94*c2c66affSColin Finck pInstance = WDML_GetInstance(idInst);
95*c2c66affSColin Finck if (!pInstance)
96*c2c66affSColin Finck return NULL;
97*c2c66affSColin Finck
98*c2c66affSColin Finck /* make sure this conv is never created */
99*c2c66affSColin Finck pConv = WDML_FindConv(pInstance, WDML_CLIENT_SIDE, hszService, hszTopic);
100*c2c66affSColin Finck if (pConv != NULL)
101*c2c66affSColin Finck {
102*c2c66affSColin Finck ERR("This Conv already exists: (%p)\n", pConv);
103*c2c66affSColin Finck return NULL;
104*c2c66affSColin Finck }
105*c2c66affSColin Finck
106*c2c66affSColin Finck /* we need to establish a conversation with
107*c2c66affSColin Finck server, so create a window for it */
108*c2c66affSColin Finck
109*c2c66affSColin Finck if (pInstance->unicode)
110*c2c66affSColin Finck {
111*c2c66affSColin Finck WNDCLASSEXW wndclass;
112*c2c66affSColin Finck
113*c2c66affSColin Finck wndclass.cbSize = sizeof(wndclass);
114*c2c66affSColin Finck wndclass.style = 0;
115*c2c66affSColin Finck wndclass.lpfnWndProc = WDML_ClientProc;
116*c2c66affSColin Finck wndclass.cbClsExtra = 0;
117*c2c66affSColin Finck wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR);
118*c2c66affSColin Finck wndclass.hInstance = 0;
119*c2c66affSColin Finck wndclass.hIcon = 0;
120*c2c66affSColin Finck wndclass.hCursor = 0;
121*c2c66affSColin Finck wndclass.hbrBackground = 0;
122*c2c66affSColin Finck wndclass.lpszMenuName = NULL;
123*c2c66affSColin Finck wndclass.lpszClassName = WDML_szClientConvClassW;
124*c2c66affSColin Finck wndclass.hIconSm = 0;
125*c2c66affSColin Finck
126*c2c66affSColin Finck RegisterClassExW(&wndclass);
127*c2c66affSColin Finck
128*c2c66affSColin Finck hwndClient = CreateWindowW(WDML_szClientConvClassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
129*c2c66affSColin Finck }
130*c2c66affSColin Finck else
131*c2c66affSColin Finck {
132*c2c66affSColin Finck WNDCLASSEXA wndclass;
133*c2c66affSColin Finck
134*c2c66affSColin Finck wndclass.cbSize = sizeof(wndclass);
135*c2c66affSColin Finck wndclass.style = 0;
136*c2c66affSColin Finck wndclass.lpfnWndProc = WDML_ClientProc;
137*c2c66affSColin Finck wndclass.cbClsExtra = 0;
138*c2c66affSColin Finck wndclass.cbWndExtra = 2 * sizeof(ULONG_PTR);
139*c2c66affSColin Finck wndclass.hInstance = 0;
140*c2c66affSColin Finck wndclass.hIcon = 0;
141*c2c66affSColin Finck wndclass.hCursor = 0;
142*c2c66affSColin Finck wndclass.hbrBackground = 0;
143*c2c66affSColin Finck wndclass.lpszMenuName = NULL;
144*c2c66affSColin Finck wndclass.lpszClassName = WDML_szClientConvClassA;
145*c2c66affSColin Finck wndclass.hIconSm = 0;
146*c2c66affSColin Finck
147*c2c66affSColin Finck RegisterClassExA(&wndclass);
148*c2c66affSColin Finck
149*c2c66affSColin Finck hwndClient = CreateWindowA(WDML_szClientConvClassA, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
150*c2c66affSColin Finck }
151*c2c66affSColin Finck
152*c2c66affSColin Finck SetWindowLongPtrW(hwndClient, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance);
153*c2c66affSColin Finck
154*c2c66affSColin Finck if (hszService)
155*c2c66affSColin Finck {
156*c2c66affSColin Finck aSrv = WDML_MakeAtomFromHsz(hszService);
157*c2c66affSColin Finck if (!aSrv) goto theEnd;
158*c2c66affSColin Finck }
159*c2c66affSColin Finck if (hszTopic)
160*c2c66affSColin Finck {
161*c2c66affSColin Finck aTpc = WDML_MakeAtomFromHsz(hszTopic);
162*c2c66affSColin Finck if (!aTpc) goto theEnd;
163*c2c66affSColin Finck }
164*c2c66affSColin Finck
165*c2c66affSColin Finck /* note: sent messages shall not use packing */
166*c2c66affSColin Finck SendMessageTimeoutW( HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hwndClient, MAKELPARAM(aSrv, aTpc),
167*c2c66affSColin Finck SMTO_ABORTIFHUNG, 0, NULL );
168*c2c66affSColin Finck
169*c2c66affSColin Finck pInstance = WDML_GetInstance(idInst);
170*c2c66affSColin Finck if (!pInstance)
171*c2c66affSColin Finck {
172*c2c66affSColin Finck goto theEnd;
173*c2c66affSColin Finck }
174*c2c66affSColin Finck
175*c2c66affSColin Finck /* At this point, Client WM_DDE_ACK should have saved hwndServer
176*c2c66affSColin Finck for this instance id and hwndClient if server responds.
177*c2c66affSColin Finck So get HCONV and return it. And add it to conv list */
178*c2c66affSColin Finck pConv = WDML_GetConvFromWnd(hwndClient);
179*c2c66affSColin Finck if (pConv == NULL || pConv->hwndServer == 0)
180*c2c66affSColin Finck {
181*c2c66affSColin Finck WARN("Done with INITIATE, but no Server window available\n");
182*c2c66affSColin Finck pConv = NULL;
183*c2c66affSColin Finck pInstance->lastError = DMLERR_NO_CONV_ESTABLISHED;
184*c2c66affSColin Finck goto theEnd;
185*c2c66affSColin Finck }
186*c2c66affSColin Finck TRACE("Connected to Server window (%p)\n", pConv->hwndServer);
187*c2c66affSColin Finck pConv->wConvst = XST_CONNECTED;
188*c2c66affSColin Finck
189*c2c66affSColin Finck /* finish init of pConv */
190*c2c66affSColin Finck if (pCC != NULL)
191*c2c66affSColin Finck {
192*c2c66affSColin Finck pConv->convContext = *pCC;
193*c2c66affSColin Finck }
194*c2c66affSColin Finck else
195*c2c66affSColin Finck {
196*c2c66affSColin Finck memset(&pConv->convContext, 0, sizeof(pConv->convContext));
197*c2c66affSColin Finck pConv->convContext.cb = sizeof(pConv->convContext);
198*c2c66affSColin Finck pConv->convContext.iCodePage = (pInstance->unicode) ? CP_WINUNICODE : CP_WINANSI;
199*c2c66affSColin Finck }
200*c2c66affSColin Finck
201*c2c66affSColin Finck theEnd:
202*c2c66affSColin Finck
203*c2c66affSColin Finck if (aSrv) GlobalDeleteAtom(aSrv);
204*c2c66affSColin Finck if (aTpc) GlobalDeleteAtom(aTpc);
205*c2c66affSColin Finck return (HCONV)pConv;
206*c2c66affSColin Finck }
207*c2c66affSColin Finck
208*c2c66affSColin Finck /*****************************************************************
209*c2c66affSColin Finck * DdeReconnect (DDEML.37)
210*c2c66affSColin Finck * DdeReconnect (USER32.@)
211*c2c66affSColin Finck */
DdeReconnect(HCONV hConv)212*c2c66affSColin Finck HCONV WINAPI DdeReconnect(HCONV hConv)
213*c2c66affSColin Finck {
214*c2c66affSColin Finck WDML_CONV* pConv;
215*c2c66affSColin Finck WDML_CONV* pNewConv = NULL;
216*c2c66affSColin Finck ATOM aSrv = 0, aTpc = 0;
217*c2c66affSColin Finck
218*c2c66affSColin Finck TRACE("(%p)\n", hConv);
219*c2c66affSColin Finck
220*c2c66affSColin Finck pConv = WDML_GetConv(hConv, FALSE);
221*c2c66affSColin Finck if (pConv != NULL && (pConv->wStatus & ST_CLIENT))
222*c2c66affSColin Finck {
223*c2c66affSColin Finck BOOL ret;
224*c2c66affSColin Finck
225*c2c66affSColin Finck /* to reestablish a connection, we have to make sure that:
226*c2c66affSColin Finck * 1/ pConv is the conversation attached to the client window (it wouldn't be
227*c2c66affSColin Finck * if a call to DdeReconnect would have already been done...)
228*c2c66affSColin Finck * FIXME: is this really an error ???
229*c2c66affSColin Finck * 2/ the pConv conversation had really been deconnected
230*c2c66affSColin Finck */
231*c2c66affSColin Finck if (pConv == WDML_GetConvFromWnd(pConv->hwndClient) &&
232*c2c66affSColin Finck (pConv->wStatus & ST_TERMINATED) && !(pConv->wStatus & ST_CONNECTED))
233*c2c66affSColin Finck {
234*c2c66affSColin Finck HWND hwndClient = pConv->hwndClient;
235*c2c66affSColin Finck HWND hwndServer = pConv->hwndServer;
236*c2c66affSColin Finck
237*c2c66affSColin Finck SetWindowLongPtrW(pConv->hwndClient, GWL_WDML_CONVERSATION, 0);
238*c2c66affSColin Finck
239*c2c66affSColin Finck aSrv = WDML_MakeAtomFromHsz(pConv->hszService);
240*c2c66affSColin Finck aTpc = WDML_MakeAtomFromHsz(pConv->hszTopic);
241*c2c66affSColin Finck if (!aSrv || !aTpc) goto theEnd;
242*c2c66affSColin Finck
243*c2c66affSColin Finck /* note: sent messages shall not use packing */
244*c2c66affSColin Finck ret = SendMessageW(hwndServer, WM_DDE_INITIATE, (WPARAM)hwndClient,
245*c2c66affSColin Finck MAKELPARAM(aSrv, aTpc));
246*c2c66affSColin Finck
247*c2c66affSColin Finck pConv = WDML_GetConv(hConv, FALSE);
248*c2c66affSColin Finck if (pConv == NULL)
249*c2c66affSColin Finck {
250*c2c66affSColin Finck FIXME("Should fail reconnection\n");
251*c2c66affSColin Finck goto theEnd;
252*c2c66affSColin Finck }
253*c2c66affSColin Finck
254*c2c66affSColin Finck if (ret && (pNewConv = WDML_GetConvFromWnd(pConv->hwndClient)) != NULL)
255*c2c66affSColin Finck {
256*c2c66affSColin Finck /* re-establish all links... */
257*c2c66affSColin Finck WDML_LINK* pLink;
258*c2c66affSColin Finck
259*c2c66affSColin Finck for (pLink = pConv->instance->links[WDML_CLIENT_SIDE]; pLink; pLink = pLink->next)
260*c2c66affSColin Finck {
261*c2c66affSColin Finck if (pLink->hConv == hConv)
262*c2c66affSColin Finck {
263*c2c66affSColin Finck /* try to reestablish the links... */
264*c2c66affSColin Finck DdeClientTransaction(NULL, 0, (HCONV)pNewConv, pLink->hszItem, pLink->uFmt,
265*c2c66affSColin Finck pLink->transactionType, 1000, NULL);
266*c2c66affSColin Finck }
267*c2c66affSColin Finck }
268*c2c66affSColin Finck }
269*c2c66affSColin Finck else
270*c2c66affSColin Finck {
271*c2c66affSColin Finck /* reset the conversation as it was */
272*c2c66affSColin Finck SetWindowLongPtrW(pConv->hwndClient, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv);
273*c2c66affSColin Finck }
274*c2c66affSColin Finck }
275*c2c66affSColin Finck }
276*c2c66affSColin Finck
277*c2c66affSColin Finck theEnd:
278*c2c66affSColin Finck
279*c2c66affSColin Finck if (aSrv) GlobalDeleteAtom(aSrv);
280*c2c66affSColin Finck if (aTpc) GlobalDeleteAtom(aTpc);
281*c2c66affSColin Finck return (HCONV)pNewConv;
282*c2c66affSColin Finck }
283*c2c66affSColin Finck
284*c2c66affSColin Finck /******************************************************************
285*c2c66affSColin Finck * WDML_ClientQueueAdvise
286*c2c66affSColin Finck *
287*c2c66affSColin Finck * Creates and queue an WM_DDE_ADVISE transaction
288*c2c66affSColin Finck */
WDML_ClientQueueAdvise(WDML_CONV * pConv,UINT wType,UINT wFmt,HSZ hszItem)289*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueueAdvise(WDML_CONV* pConv, UINT wType, UINT wFmt, HSZ hszItem)
290*c2c66affSColin Finck {
291*c2c66affSColin Finck DDEADVISE* pDdeAdvise;
292*c2c66affSColin Finck WDML_XACT* pXAct;
293*c2c66affSColin Finck ATOM atom;
294*c2c66affSColin Finck
295*c2c66affSColin Finck TRACE("XTYP_ADVSTART (with%s data) transaction\n", (wType & XTYPF_NODATA) ? "out" : "");
296*c2c66affSColin Finck
297*c2c66affSColin Finck atom = WDML_MakeAtomFromHsz(hszItem);
298*c2c66affSColin Finck if (!atom) return NULL;
299*c2c66affSColin Finck
300*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, wFmt, hszItem);
301*c2c66affSColin Finck if (!pXAct)
302*c2c66affSColin Finck {
303*c2c66affSColin Finck GlobalDeleteAtom(atom);
304*c2c66affSColin Finck return NULL;
305*c2c66affSColin Finck }
306*c2c66affSColin Finck
307*c2c66affSColin Finck pXAct->wType = wType & ~0x0F;
308*c2c66affSColin Finck pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(DDEADVISE));
309*c2c66affSColin Finck /* FIXME: hMem is unfreed for now... should be deleted in server */
310*c2c66affSColin Finck
311*c2c66affSColin Finck /* pack DdeAdvise */
312*c2c66affSColin Finck pDdeAdvise = GlobalLock(pXAct->hMem);
313*c2c66affSColin Finck pDdeAdvise->fAckReq = (wType & XTYPF_ACKREQ) != 0;
314*c2c66affSColin Finck pDdeAdvise->fDeferUpd = (wType & XTYPF_NODATA) != 0;
315*c2c66affSColin Finck pDdeAdvise->cfFormat = wFmt;
316*c2c66affSColin Finck GlobalUnlock(pXAct->hMem);
317*c2c66affSColin Finck
318*c2c66affSColin Finck pXAct->lParam = PackDDElParam(WM_DDE_ADVISE, (UINT_PTR)pXAct->hMem, atom);
319*c2c66affSColin Finck
320*c2c66affSColin Finck return pXAct;
321*c2c66affSColin Finck }
322*c2c66affSColin Finck
323*c2c66affSColin Finck /******************************************************************
324*c2c66affSColin Finck * WDML_HandleAdviseReply
325*c2c66affSColin Finck *
326*c2c66affSColin Finck * handles the reply to an advise request
327*c2c66affSColin Finck */
WDML_HandleAdviseReply(WDML_CONV * pConv,MSG * msg,WDML_XACT * pXAct,DWORD * ack)328*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleAdviseReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct, DWORD *ack)
329*c2c66affSColin Finck {
330*c2c66affSColin Finck DDEACK ddeAck;
331*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
332*c2c66affSColin Finck HSZ hsz;
333*c2c66affSColin Finck
334*c2c66affSColin Finck if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
335*c2c66affSColin Finck {
336*c2c66affSColin Finck return WDML_QS_PASS;
337*c2c66affSColin Finck }
338*c2c66affSColin Finck
339*c2c66affSColin Finck UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
340*c2c66affSColin Finck hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
341*c2c66affSColin Finck
342*c2c66affSColin Finck if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
343*c2c66affSColin Finck return WDML_QS_PASS;
344*c2c66affSColin Finck
345*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
346*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
347*c2c66affSColin Finck
348*c2c66affSColin Finck if (ack) *ack = uiLo;
349*c2c66affSColin Finck WDML_ExtractAck(uiLo, &ddeAck);
350*c2c66affSColin Finck
351*c2c66affSColin Finck if (ddeAck.fAck)
352*c2c66affSColin Finck {
353*c2c66affSColin Finck WDML_LINK* pLink;
354*c2c66affSColin Finck
355*c2c66affSColin Finck /* billx: first to see if the link is already created. */
356*c2c66affSColin Finck pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
357*c2c66affSColin Finck pXAct->hszItem, TRUE, pXAct->wFmt);
358*c2c66affSColin Finck if (pLink != NULL)
359*c2c66affSColin Finck {
360*c2c66affSColin Finck /* we found a link, and only need to modify it in case it changes */
361*c2c66affSColin Finck pLink->transactionType = pXAct->wType;
362*c2c66affSColin Finck }
363*c2c66affSColin Finck else
364*c2c66affSColin Finck {
365*c2c66affSColin Finck WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
366*c2c66affSColin Finck pXAct->wType, pXAct->hszItem, pXAct->wFmt);
367*c2c66affSColin Finck }
368*c2c66affSColin Finck pXAct->hDdeData = (HDDEDATA)1;
369*c2c66affSColin Finck }
370*c2c66affSColin Finck else
371*c2c66affSColin Finck {
372*c2c66affSColin Finck TRACE("Returning FALSE on XTYP_ADVSTART - fAck was FALSE\n");
373*c2c66affSColin Finck GlobalFree(pXAct->hMem);
374*c2c66affSColin Finck pXAct->hDdeData = NULL;
375*c2c66affSColin Finck }
376*c2c66affSColin Finck
377*c2c66affSColin Finck return WDML_QS_HANDLED;
378*c2c66affSColin Finck }
379*c2c66affSColin Finck
380*c2c66affSColin Finck /******************************************************************
381*c2c66affSColin Finck * WDML_ClientQueueUnadvise
382*c2c66affSColin Finck *
383*c2c66affSColin Finck * queues an unadvise transaction
384*c2c66affSColin Finck */
WDML_ClientQueueUnadvise(WDML_CONV * pConv,UINT wFmt,HSZ hszItem)385*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueueUnadvise(WDML_CONV* pConv, UINT wFmt, HSZ hszItem)
386*c2c66affSColin Finck {
387*c2c66affSColin Finck WDML_XACT* pXAct;
388*c2c66affSColin Finck ATOM atom;
389*c2c66affSColin Finck
390*c2c66affSColin Finck TRACE("XTYP_ADVSTOP transaction\n");
391*c2c66affSColin Finck
392*c2c66affSColin Finck atom = WDML_MakeAtomFromHsz(hszItem);
393*c2c66affSColin Finck if (!atom) return NULL;
394*c2c66affSColin Finck
395*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_UNADVISE, wFmt, hszItem);
396*c2c66affSColin Finck if (!pXAct)
397*c2c66affSColin Finck {
398*c2c66affSColin Finck GlobalDeleteAtom(atom);
399*c2c66affSColin Finck return NULL;
400*c2c66affSColin Finck }
401*c2c66affSColin Finck
402*c2c66affSColin Finck /* end advise loop: post WM_DDE_UNADVISE to server to terminate link
403*c2c66affSColin Finck * on the specified item.
404*c2c66affSColin Finck */
405*c2c66affSColin Finck pXAct->lParam = PackDDElParam(WM_DDE_UNADVISE, wFmt, atom);
406*c2c66affSColin Finck return pXAct;
407*c2c66affSColin Finck }
408*c2c66affSColin Finck
409*c2c66affSColin Finck /******************************************************************
410*c2c66affSColin Finck * WDML_HandleUnadviseReply
411*c2c66affSColin Finck *
412*c2c66affSColin Finck *
413*c2c66affSColin Finck */
WDML_HandleUnadviseReply(WDML_CONV * pConv,MSG * msg,WDML_XACT * pXAct,DWORD * ack)414*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleUnadviseReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct, DWORD *ack)
415*c2c66affSColin Finck {
416*c2c66affSColin Finck DDEACK ddeAck;
417*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
418*c2c66affSColin Finck HSZ hsz;
419*c2c66affSColin Finck
420*c2c66affSColin Finck if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
421*c2c66affSColin Finck {
422*c2c66affSColin Finck return WDML_QS_PASS;
423*c2c66affSColin Finck }
424*c2c66affSColin Finck
425*c2c66affSColin Finck UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
426*c2c66affSColin Finck hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
427*c2c66affSColin Finck
428*c2c66affSColin Finck if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
429*c2c66affSColin Finck return WDML_QS_PASS;
430*c2c66affSColin Finck
431*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
432*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
433*c2c66affSColin Finck
434*c2c66affSColin Finck if (ack) *ack = uiLo;
435*c2c66affSColin Finck WDML_ExtractAck(uiLo, &ddeAck);
436*c2c66affSColin Finck
437*c2c66affSColin Finck TRACE("WM_DDE_ACK received while waiting for a timeout\n");
438*c2c66affSColin Finck
439*c2c66affSColin Finck if (!ddeAck.fAck)
440*c2c66affSColin Finck {
441*c2c66affSColin Finck TRACE("Returning FALSE on XTYP_ADVSTOP - fAck was FALSE\n");
442*c2c66affSColin Finck pXAct->hDdeData = NULL;
443*c2c66affSColin Finck }
444*c2c66affSColin Finck else
445*c2c66affSColin Finck {
446*c2c66affSColin Finck /* billx: remove the link */
447*c2c66affSColin Finck WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE,
448*c2c66affSColin Finck pXAct->hszItem, pXAct->wFmt);
449*c2c66affSColin Finck pXAct->hDdeData = (HDDEDATA)1;
450*c2c66affSColin Finck }
451*c2c66affSColin Finck return WDML_QS_HANDLED;
452*c2c66affSColin Finck }
453*c2c66affSColin Finck
454*c2c66affSColin Finck /******************************************************************
455*c2c66affSColin Finck * WDML_ClientQueueRequest
456*c2c66affSColin Finck *
457*c2c66affSColin Finck *
458*c2c66affSColin Finck */
WDML_ClientQueueRequest(WDML_CONV * pConv,UINT wFmt,HSZ hszItem)459*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueueRequest(WDML_CONV* pConv, UINT wFmt, HSZ hszItem)
460*c2c66affSColin Finck {
461*c2c66affSColin Finck WDML_XACT* pXAct;
462*c2c66affSColin Finck ATOM atom;
463*c2c66affSColin Finck
464*c2c66affSColin Finck TRACE("XTYP_REQUEST transaction\n");
465*c2c66affSColin Finck
466*c2c66affSColin Finck atom = WDML_MakeAtomFromHsz(hszItem);
467*c2c66affSColin Finck if (!atom) return NULL;
468*c2c66affSColin Finck
469*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_REQUEST, wFmt, hszItem);
470*c2c66affSColin Finck if (!pXAct)
471*c2c66affSColin Finck {
472*c2c66affSColin Finck GlobalDeleteAtom(atom);
473*c2c66affSColin Finck return NULL;
474*c2c66affSColin Finck }
475*c2c66affSColin Finck
476*c2c66affSColin Finck pXAct->lParam = PackDDElParam(WM_DDE_REQUEST, wFmt, atom);
477*c2c66affSColin Finck
478*c2c66affSColin Finck return pXAct;
479*c2c66affSColin Finck }
480*c2c66affSColin Finck
481*c2c66affSColin Finck /******************************************************************
482*c2c66affSColin Finck * WDML_HandleRequestReply
483*c2c66affSColin Finck *
484*c2c66affSColin Finck *
485*c2c66affSColin Finck */
WDML_HandleRequestReply(WDML_CONV * pConv,MSG * msg,WDML_XACT * pXAct,DWORD * ack)486*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct, DWORD *ack)
487*c2c66affSColin Finck {
488*c2c66affSColin Finck DDEACK ddeAck;
489*c2c66affSColin Finck WINE_DDEHEAD wdh;
490*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
491*c2c66affSColin Finck HSZ hsz;
492*c2c66affSColin Finck
493*c2c66affSColin Finck if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
494*c2c66affSColin Finck return WDML_QS_PASS;
495*c2c66affSColin Finck
496*c2c66affSColin Finck switch (msg->message)
497*c2c66affSColin Finck {
498*c2c66affSColin Finck case WM_DDE_ACK:
499*c2c66affSColin Finck UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
500*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
501*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
502*c2c66affSColin Finck if (ack) *ack = uiLo;
503*c2c66affSColin Finck WDML_ExtractAck(uiLo, &ddeAck);
504*c2c66affSColin Finck pXAct->hDdeData = 0;
505*c2c66affSColin Finck if (ddeAck.fAck)
506*c2c66affSColin Finck ERR("Positive answer should appear in NACK for a request, assuming negative\n");
507*c2c66affSColin Finck TRACE("Negative answer...\n");
508*c2c66affSColin Finck break;
509*c2c66affSColin Finck
510*c2c66affSColin Finck case WM_DDE_DATA:
511*c2c66affSColin Finck UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi);
512*c2c66affSColin Finck TRACE("Got the result (%08lx)\n", uiLo);
513*c2c66affSColin Finck
514*c2c66affSColin Finck hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
515*c2c66affSColin Finck
516*c2c66affSColin Finck if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
517*c2c66affSColin Finck return WDML_QS_PASS;
518*c2c66affSColin Finck
519*c2c66affSColin Finck pXAct->hDdeData = WDML_Global2DataHandle(pConv, (HGLOBAL)uiLo, &wdh);
520*c2c66affSColin Finck if (wdh.fRelease)
521*c2c66affSColin Finck {
522*c2c66affSColin Finck GlobalFree((HGLOBAL)uiLo);
523*c2c66affSColin Finck }
524*c2c66affSColin Finck if (wdh.fAckReq)
525*c2c66affSColin Finck {
526*c2c66affSColin Finck pConv->instance->lastError = DMLERR_MEMORY_ERROR;
527*c2c66affSColin Finck }
528*c2c66affSColin Finck else
529*c2c66affSColin Finck {
530*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
531*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
532*c2c66affSColin Finck }
533*c2c66affSColin Finck break;
534*c2c66affSColin Finck
535*c2c66affSColin Finck default:
536*c2c66affSColin Finck FreeDDElParam(msg->message, msg->lParam);
537*c2c66affSColin Finck return WDML_QS_PASS;
538*c2c66affSColin Finck }
539*c2c66affSColin Finck
540*c2c66affSColin Finck return WDML_QS_HANDLED;
541*c2c66affSColin Finck }
542*c2c66affSColin Finck
543*c2c66affSColin Finck /******************************************************************
544*c2c66affSColin Finck * WDML_BuildExecuteCommand
545*c2c66affSColin Finck *
546*c2c66affSColin Finck * Creates a DDE block suitable for sending in WM_DDE_COMMAND
547*c2c66affSColin Finck * It also takes care of string conversion between the two window procedures
548*c2c66affSColin Finck */
WDML_BuildExecuteCommand(WDML_CONV * pConv,LPCVOID pData,DWORD cbData)549*c2c66affSColin Finck static HGLOBAL WDML_BuildExecuteCommand(WDML_CONV* pConv, LPCVOID pData, DWORD cbData)
550*c2c66affSColin Finck {
551*c2c66affSColin Finck HGLOBAL hMem;
552*c2c66affSColin Finck BOOL clientUnicode, serverUnicode;
553*c2c66affSColin Finck DWORD memSize;
554*c2c66affSColin Finck
555*c2c66affSColin Finck clientUnicode = pConv->instance->unicode;
556*c2c66affSColin Finck TRACE("client %p uses unicode = %d\n", pConv->hwndClient, clientUnicode);
557*c2c66affSColin Finck /* FIXME: how exactly Windows determines what to use for the server side? */
558*c2c66affSColin Finck serverUnicode = IsWindowUnicode(pConv->hwndServer) && IsWindowUnicode(pConv->hwndClient);
559*c2c66affSColin Finck TRACE("server %p uses unicode = %d\n", pConv->hwndServer, serverUnicode);
560*c2c66affSColin Finck
561*c2c66affSColin Finck if (clientUnicode == serverUnicode)
562*c2c66affSColin Finck {
563*c2c66affSColin Finck memSize = cbData;
564*c2c66affSColin Finck }
565*c2c66affSColin Finck else
566*c2c66affSColin Finck {
567*c2c66affSColin Finck if (clientUnicode)
568*c2c66affSColin Finck {
569*c2c66affSColin Finck memSize = WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), NULL, 0, NULL, NULL);
570*c2c66affSColin Finck }
571*c2c66affSColin Finck else
572*c2c66affSColin Finck {
573*c2c66affSColin Finck memSize = MultiByteToWideChar( CP_ACP, 0, pData, cbData, NULL, 0) * sizeof(WCHAR);
574*c2c66affSColin Finck }
575*c2c66affSColin Finck }
576*c2c66affSColin Finck
577*c2c66affSColin Finck hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, memSize);
578*c2c66affSColin Finck
579*c2c66affSColin Finck if (hMem)
580*c2c66affSColin Finck {
581*c2c66affSColin Finck LPSTR pDst;
582*c2c66affSColin Finck
583*c2c66affSColin Finck pDst = GlobalLock(hMem);
584*c2c66affSColin Finck if (pDst)
585*c2c66affSColin Finck {
586*c2c66affSColin Finck if (clientUnicode == serverUnicode)
587*c2c66affSColin Finck {
588*c2c66affSColin Finck memcpy(pDst, pData, cbData);
589*c2c66affSColin Finck }
590*c2c66affSColin Finck else
591*c2c66affSColin Finck {
592*c2c66affSColin Finck if (clientUnicode)
593*c2c66affSColin Finck {
594*c2c66affSColin Finck WideCharToMultiByte( CP_ACP, 0, pData, cbData / sizeof(WCHAR), pDst, memSize, NULL, NULL);
595*c2c66affSColin Finck }
596*c2c66affSColin Finck else
597*c2c66affSColin Finck {
598*c2c66affSColin Finck MultiByteToWideChar( CP_ACP, 0, pData, cbData, (LPWSTR)pDst, memSize/sizeof(WCHAR));
599*c2c66affSColin Finck }
600*c2c66affSColin Finck }
601*c2c66affSColin Finck
602*c2c66affSColin Finck GlobalUnlock(hMem);
603*c2c66affSColin Finck }
604*c2c66affSColin Finck else
605*c2c66affSColin Finck {
606*c2c66affSColin Finck GlobalFree(hMem);
607*c2c66affSColin Finck hMem = 0;
608*c2c66affSColin Finck }
609*c2c66affSColin Finck }
610*c2c66affSColin Finck return hMem;
611*c2c66affSColin Finck }
612*c2c66affSColin Finck
613*c2c66affSColin Finck /******************************************************************
614*c2c66affSColin Finck * WDML_ClientQueueExecute
615*c2c66affSColin Finck *
616*c2c66affSColin Finck *
617*c2c66affSColin Finck */
WDML_ClientQueueExecute(WDML_CONV * pConv,LPVOID pData,DWORD cbData)618*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueueExecute(WDML_CONV* pConv, LPVOID pData, DWORD cbData)
619*c2c66affSColin Finck {
620*c2c66affSColin Finck WDML_XACT* pXAct;
621*c2c66affSColin Finck
622*c2c66affSColin Finck TRACE("XTYP_EXECUTE transaction\n");
623*c2c66affSColin Finck
624*c2c66affSColin Finck if (pData == NULL)
625*c2c66affSColin Finck {
626*c2c66affSColin Finck if (cbData == (DWORD)-1)
627*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
628*c2c66affSColin Finck else
629*c2c66affSColin Finck pConv->instance->lastError = DMLERR_MEMORY_ERROR;
630*c2c66affSColin Finck return NULL;
631*c2c66affSColin Finck }
632*c2c66affSColin Finck
633*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_EXECUTE, 0, 0);
634*c2c66affSColin Finck if (!pXAct)
635*c2c66affSColin Finck return NULL;
636*c2c66affSColin Finck
637*c2c66affSColin Finck if (cbData == (DWORD)-1)
638*c2c66affSColin Finck {
639*c2c66affSColin Finck HDDEDATA hDdeData = pData;
640*c2c66affSColin Finck
641*c2c66affSColin Finck pData = DdeAccessData(hDdeData, &cbData);
642*c2c66affSColin Finck if (pData)
643*c2c66affSColin Finck {
644*c2c66affSColin Finck pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData);
645*c2c66affSColin Finck DdeUnaccessData(hDdeData);
646*c2c66affSColin Finck }
647*c2c66affSColin Finck }
648*c2c66affSColin Finck else
649*c2c66affSColin Finck {
650*c2c66affSColin Finck pXAct->hMem = WDML_BuildExecuteCommand(pConv, pData, cbData);
651*c2c66affSColin Finck }
652*c2c66affSColin Finck
653*c2c66affSColin Finck pXAct->lParam = (LPARAM)pXAct->hMem;
654*c2c66affSColin Finck
655*c2c66affSColin Finck return pXAct;
656*c2c66affSColin Finck }
657*c2c66affSColin Finck
658*c2c66affSColin Finck /******************************************************************
659*c2c66affSColin Finck * WDML_HandleExecuteReply
660*c2c66affSColin Finck *
661*c2c66affSColin Finck *
662*c2c66affSColin Finck */
WDML_HandleExecuteReply(WDML_CONV * pConv,MSG * msg,WDML_XACT * pXAct,DWORD * ack)663*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleExecuteReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct, DWORD *ack)
664*c2c66affSColin Finck {
665*c2c66affSColin Finck DDEACK ddeAck;
666*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
667*c2c66affSColin Finck
668*c2c66affSColin Finck if (msg->message != WM_DDE_ACK || WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
669*c2c66affSColin Finck {
670*c2c66affSColin Finck return WDML_QS_PASS;
671*c2c66affSColin Finck }
672*c2c66affSColin Finck
673*c2c66affSColin Finck UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
674*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
675*c2c66affSColin Finck
676*c2c66affSColin Finck if ((HANDLE)uiHi != pXAct->hMem)
677*c2c66affSColin Finck {
678*c2c66affSColin Finck return WDML_QS_PASS;
679*c2c66affSColin Finck }
680*c2c66affSColin Finck
681*c2c66affSColin Finck if (ack) *ack = uiLo;
682*c2c66affSColin Finck WDML_ExtractAck(uiLo, &ddeAck);
683*c2c66affSColin Finck pXAct->hDdeData = (HDDEDATA)(UINT_PTR)ddeAck.fAck;
684*c2c66affSColin Finck
685*c2c66affSColin Finck TRACE("hDdeData = %p\n", pXAct->hDdeData);
686*c2c66affSColin Finck pConv->instance->lastError = (pXAct->hDdeData != 0) ? DMLERR_NO_ERROR : DMLERR_NOTPROCESSED;
687*c2c66affSColin Finck
688*c2c66affSColin Finck return WDML_QS_HANDLED;
689*c2c66affSColin Finck }
690*c2c66affSColin Finck
691*c2c66affSColin Finck /******************************************************************
692*c2c66affSColin Finck * WDML_ClientQueuePoke
693*c2c66affSColin Finck *
694*c2c66affSColin Finck *
695*c2c66affSColin Finck */
WDML_ClientQueuePoke(WDML_CONV * pConv,LPVOID pData,DWORD cbData,UINT wFmt,HSZ hszItem)696*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueuePoke(WDML_CONV* pConv, LPVOID pData, DWORD cbData,
697*c2c66affSColin Finck UINT wFmt, HSZ hszItem)
698*c2c66affSColin Finck {
699*c2c66affSColin Finck DDE_DATAHANDLE_HEAD *dh;
700*c2c66affSColin Finck WDML_XACT *pXAct;
701*c2c66affSColin Finck DDEPOKE *ddePoke;
702*c2c66affSColin Finck HGLOBAL hglobal;
703*c2c66affSColin Finck ATOM atom;
704*c2c66affSColin Finck
705*c2c66affSColin Finck TRACE("XTYP_POKE transaction\n");
706*c2c66affSColin Finck
707*c2c66affSColin Finck atom = WDML_MakeAtomFromHsz(hszItem);
708*c2c66affSColin Finck if (!atom) return NULL;
709*c2c66affSColin Finck
710*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_POKE, wFmt, hszItem);
711*c2c66affSColin Finck if (!pXAct)
712*c2c66affSColin Finck {
713*c2c66affSColin Finck GlobalDeleteAtom(atom);
714*c2c66affSColin Finck return NULL;
715*c2c66affSColin Finck }
716*c2c66affSColin Finck
717*c2c66affSColin Finck if (cbData == (DWORD)-1)
718*c2c66affSColin Finck {
719*c2c66affSColin Finck hglobal = pData;
720*c2c66affSColin Finck dh = GlobalLock(hglobal);
721*c2c66affSColin Finck cbData = GlobalSize(hglobal) - sizeof(DDE_DATAHANDLE_HEAD);
722*c2c66affSColin Finck pData = dh + 1;
723*c2c66affSColin Finck GlobalUnlock(hglobal);
724*c2c66affSColin Finck }
725*c2c66affSColin Finck
726*c2c66affSColin Finck pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, FIELD_OFFSET(DDEPOKE, Value[cbData]));
727*c2c66affSColin Finck ddePoke = GlobalLock(pXAct->hMem);
728*c2c66affSColin Finck if (!ddePoke)
729*c2c66affSColin Finck {
730*c2c66affSColin Finck pConv->instance->lastError = DMLERR_MEMORY_ERROR;
731*c2c66affSColin Finck return NULL;
732*c2c66affSColin Finck }
733*c2c66affSColin Finck
734*c2c66affSColin Finck ddePoke->unused = 0;
735*c2c66affSColin Finck ddePoke->fRelease = TRUE;
736*c2c66affSColin Finck ddePoke->cfFormat = wFmt;
737*c2c66affSColin Finck memcpy(ddePoke->Value, pData, cbData);
738*c2c66affSColin Finck GlobalUnlock(pXAct->hMem);
739*c2c66affSColin Finck
740*c2c66affSColin Finck pXAct->lParam = PackDDElParam(WM_DDE_POKE, (UINT_PTR)pXAct->hMem, atom);
741*c2c66affSColin Finck
742*c2c66affSColin Finck return pXAct;
743*c2c66affSColin Finck }
744*c2c66affSColin Finck
745*c2c66affSColin Finck /******************************************************************
746*c2c66affSColin Finck * WDML_HandlePokeReply
747*c2c66affSColin Finck *
748*c2c66affSColin Finck *
749*c2c66affSColin Finck */
WDML_HandlePokeReply(WDML_CONV * pConv,MSG * msg,WDML_XACT * pXAct,DWORD * ack)750*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandlePokeReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct, DWORD *ack)
751*c2c66affSColin Finck {
752*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
753*c2c66affSColin Finck HSZ hsz;
754*c2c66affSColin Finck
755*c2c66affSColin Finck if (msg->message != WM_DDE_ACK && WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
756*c2c66affSColin Finck {
757*c2c66affSColin Finck return WDML_QS_PASS;
758*c2c66affSColin Finck }
759*c2c66affSColin Finck
760*c2c66affSColin Finck UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi);
761*c2c66affSColin Finck hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
762*c2c66affSColin Finck if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0)
763*c2c66affSColin Finck {
764*c2c66affSColin Finck return WDML_QS_PASS;
765*c2c66affSColin Finck }
766*c2c66affSColin Finck FreeDDElParam(WM_DDE_ACK, msg->lParam);
767*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
768*c2c66affSColin Finck
769*c2c66affSColin Finck if (ack) *ack = uiLo;
770*c2c66affSColin Finck pXAct->hMem = GlobalFree(pXAct->hMem);
771*c2c66affSColin Finck
772*c2c66affSColin Finck pXAct->hDdeData = (HDDEDATA)TRUE;
773*c2c66affSColin Finck return TRUE;
774*c2c66affSColin Finck }
775*c2c66affSColin Finck
776*c2c66affSColin Finck /******************************************************************
777*c2c66affSColin Finck * WDML_ClientQueueTerminate
778*c2c66affSColin Finck *
779*c2c66affSColin Finck * Creates and queue an WM_DDE_TERMINATE transaction
780*c2c66affSColin Finck */
WDML_ClientQueueTerminate(WDML_CONV * pConv)781*c2c66affSColin Finck static WDML_XACT* WDML_ClientQueueTerminate(WDML_CONV* pConv)
782*c2c66affSColin Finck {
783*c2c66affSColin Finck WDML_XACT* pXAct;
784*c2c66affSColin Finck
785*c2c66affSColin Finck pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_TERMINATE, 0, 0);
786*c2c66affSColin Finck if (!pXAct)
787*c2c66affSColin Finck return NULL;
788*c2c66affSColin Finck
789*c2c66affSColin Finck pXAct->lParam = 0;
790*c2c66affSColin Finck pConv->wStatus &= ~ST_CONNECTED;
791*c2c66affSColin Finck
792*c2c66affSColin Finck return pXAct;
793*c2c66affSColin Finck }
794*c2c66affSColin Finck
795*c2c66affSColin Finck /******************************************************************
796*c2c66affSColin Finck * WDML_HandleTerminateReply
797*c2c66affSColin Finck *
798*c2c66affSColin Finck * handles the reply to a terminate request
799*c2c66affSColin Finck */
WDML_HandleTerminateReply(WDML_CONV * pConv,MSG * msg)800*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV* pConv, MSG* msg)
801*c2c66affSColin Finck {
802*c2c66affSColin Finck if (msg->message != WM_DDE_TERMINATE)
803*c2c66affSColin Finck {
804*c2c66affSColin Finck /* FIXME: should delete data passed here */
805*c2c66affSColin Finck return WDML_QS_SWALLOWED;
806*c2c66affSColin Finck }
807*c2c66affSColin Finck
808*c2c66affSColin Finck if (WIN_GetFullHandle((HWND)msg->wParam) != pConv->hwndServer)
809*c2c66affSColin Finck {
810*c2c66affSColin Finck FIXME("hmmm shouldn't happen\n");
811*c2c66affSColin Finck return WDML_QS_PASS;
812*c2c66affSColin Finck }
813*c2c66affSColin Finck if (!(pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS))
814*c2c66affSColin Finck {
815*c2c66affSColin Finck WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv,
816*c2c66affSColin Finck 0, 0, 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0);
817*c2c66affSColin Finck }
818*c2c66affSColin Finck WDML_RemoveConv(pConv, WDML_CLIENT_SIDE);
819*c2c66affSColin Finck return WDML_QS_HANDLED;
820*c2c66affSColin Finck }
821*c2c66affSColin Finck
822*c2c66affSColin Finck /******************************************************************
823*c2c66affSColin Finck * WDML_HandleIncomingData
824*c2c66affSColin Finck *
825*c2c66affSColin Finck *
826*c2c66affSColin Finck */
WDML_HandleIncomingData(WDML_CONV * pConv,MSG * msg,HDDEDATA * hdd)827*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleIncomingData(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd)
828*c2c66affSColin Finck {
829*c2c66affSColin Finck UINT_PTR uiLo, uiHi;
830*c2c66affSColin Finck HDDEDATA hDdeDataIn, hDdeDataOut;
831*c2c66affSColin Finck WDML_LINK* pLink;
832*c2c66affSColin Finck WINE_DDEHEAD wdh;
833*c2c66affSColin Finck HSZ hsz;
834*c2c66affSColin Finck
835*c2c66affSColin Finck TRACE("WM_DDE_DATA message received in the Client Proc!\n");
836*c2c66affSColin Finck /* wParam -- sending window handle */
837*c2c66affSColin Finck /* lParam -- hDdeData & item HSZ */
838*c2c66affSColin Finck
839*c2c66affSColin Finck UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi);
840*c2c66affSColin Finck hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi);
841*c2c66affSColin Finck
842*c2c66affSColin Finck hDdeDataIn = WDML_Global2DataHandle(pConv, (HGLOBAL)uiLo, &wdh);
843*c2c66affSColin Finck
844*c2c66affSColin Finck /* billx:
845*c2c66affSColin Finck * For hot link, data should be passed to its callback with
846*c2c66affSColin Finck * XTYP_ADVDATA and callback should return the proper status.
847*c2c66affSColin Finck */
848*c2c66affSColin Finck pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, hsz,
849*c2c66affSColin Finck uiLo != 0, wdh.cfFormat);
850*c2c66affSColin Finck if (!pLink)
851*c2c66affSColin Finck {
852*c2c66affSColin Finck WDML_DecHSZ(pConv->instance, hsz);
853*c2c66affSColin Finck DdeFreeDataHandle(hDdeDataIn);
854*c2c66affSColin Finck return WDML_QS_PASS;
855*c2c66affSColin Finck }
856*c2c66affSColin Finck
857*c2c66affSColin Finck if (hDdeDataIn != 0 && wdh.fAckReq)
858*c2c66affSColin Finck {
859*c2c66affSColin Finck WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA);
860*c2c66affSColin Finck if (msg->lParam)
861*c2c66affSColin Finck msg->lParam = 0;
862*c2c66affSColin Finck }
863*c2c66affSColin Finck else
864*c2c66affSColin Finck {
865*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
866*c2c66affSColin Finck }
867*c2c66affSColin Finck
868*c2c66affSColin Finck hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_ADVDATA, pLink->uFmt, pLink->hConv,
869*c2c66affSColin Finck pConv->hszTopic, pLink->hszItem, hDdeDataIn, 0, 0);
870*c2c66affSColin Finck
871*c2c66affSColin Finck if (hDdeDataOut != (HDDEDATA)DDE_FACK || wdh.fRelease)
872*c2c66affSColin Finck {
873*c2c66affSColin Finck if (uiLo) GlobalFree((HANDLE)uiLo);
874*c2c66affSColin Finck }
875*c2c66affSColin Finck
876*c2c66affSColin Finck DdeFreeDataHandle(hDdeDataIn);
877*c2c66affSColin Finck
878*c2c66affSColin Finck WDML_DecHSZ(pConv->instance, hsz);
879*c2c66affSColin Finck if (msg->lParam)
880*c2c66affSColin Finck FreeDDElParam(WM_DDE_DATA, msg->lParam);
881*c2c66affSColin Finck
882*c2c66affSColin Finck return WDML_QS_HANDLED;
883*c2c66affSColin Finck }
884*c2c66affSColin Finck
885*c2c66affSColin Finck /******************************************************************
886*c2c66affSColin Finck * WDML_HandleIncomingTerminate
887*c2c66affSColin Finck *
888*c2c66affSColin Finck *
889*c2c66affSColin Finck */
WDML_HandleIncomingTerminate(WDML_CONV * pConv,MSG * msg,HDDEDATA * hdd)890*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleIncomingTerminate(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd)
891*c2c66affSColin Finck {
892*c2c66affSColin Finck if (pConv->hwndServer != WIN_GetFullHandle((HWND)msg->wParam))
893*c2c66affSColin Finck return WDML_QS_PASS;
894*c2c66affSColin Finck
895*c2c66affSColin Finck pConv->wStatus |= ST_TERMINATED;
896*c2c66affSColin Finck if (pConv->wStatus & ST_CONNECTED)
897*c2c66affSColin Finck {
898*c2c66affSColin Finck /* don't care about result code (if server exists or not) */
899*c2c66affSColin Finck PostMessageW(pConv->hwndServer, WM_DDE_TERMINATE, (WPARAM)pConv->hwndClient, 0L);
900*c2c66affSColin Finck pConv->wStatus &= ~ST_CONNECTED;
901*c2c66affSColin Finck }
902*c2c66affSColin Finck /* have to keep connection around to allow reconnection */
903*c2c66affSColin Finck return WDML_QS_HANDLED;
904*c2c66affSColin Finck }
905*c2c66affSColin Finck
906*c2c66affSColin Finck /******************************************************************
907*c2c66affSColin Finck * WDML_HandleReply
908*c2c66affSColin Finck *
909*c2c66affSColin Finck * handles any incoming reply, and try to match to an already sent request
910*c2c66affSColin Finck */
WDML_HandleReply(WDML_CONV * pConv,MSG * msg,HDDEDATA * hdd,DWORD * ack)911*c2c66affSColin Finck static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* hdd, DWORD *ack)
912*c2c66affSColin Finck {
913*c2c66affSColin Finck WDML_XACT* pXAct = pConv->transactions;
914*c2c66affSColin Finck WDML_QUEUE_STATE qs;
915*c2c66affSColin Finck
916*c2c66affSColin Finck if (pConv->transactions)
917*c2c66affSColin Finck {
918*c2c66affSColin Finck if (ack) *ack = DDE_FNOTPROCESSED;
919*c2c66affSColin Finck /* first check message against a pending transaction, if any */
920*c2c66affSColin Finck switch (pXAct->ddeMsg)
921*c2c66affSColin Finck {
922*c2c66affSColin Finck case WM_DDE_ADVISE:
923*c2c66affSColin Finck qs = WDML_HandleAdviseReply(pConv, msg, pXAct, ack);
924*c2c66affSColin Finck break;
925*c2c66affSColin Finck case WM_DDE_UNADVISE:
926*c2c66affSColin Finck qs = WDML_HandleUnadviseReply(pConv, msg, pXAct, ack);
927*c2c66affSColin Finck break;
928*c2c66affSColin Finck case WM_DDE_EXECUTE:
929*c2c66affSColin Finck qs = WDML_HandleExecuteReply(pConv, msg, pXAct, ack);
930*c2c66affSColin Finck break;
931*c2c66affSColin Finck case WM_DDE_REQUEST:
932*c2c66affSColin Finck qs = WDML_HandleRequestReply(pConv, msg, pXAct, ack);
933*c2c66affSColin Finck break;
934*c2c66affSColin Finck case WM_DDE_POKE:
935*c2c66affSColin Finck qs = WDML_HandlePokeReply(pConv, msg, pXAct, ack);
936*c2c66affSColin Finck break;
937*c2c66affSColin Finck case WM_DDE_TERMINATE:
938*c2c66affSColin Finck qs = WDML_HandleTerminateReply(pConv, msg);
939*c2c66affSColin Finck break;
940*c2c66affSColin Finck default:
941*c2c66affSColin Finck qs = WDML_QS_ERROR;
942*c2c66affSColin Finck FIXME("oooch\n");
943*c2c66affSColin Finck }
944*c2c66affSColin Finck }
945*c2c66affSColin Finck else
946*c2c66affSColin Finck {
947*c2c66affSColin Finck qs = WDML_QS_PASS;
948*c2c66affSColin Finck }
949*c2c66affSColin Finck
950*c2c66affSColin Finck /* now check the results */
951*c2c66affSColin Finck switch (qs)
952*c2c66affSColin Finck {
953*c2c66affSColin Finck case WDML_QS_ERROR:
954*c2c66affSColin Finck case WDML_QS_SWALLOWED:
955*c2c66affSColin Finck *hdd = 0;
956*c2c66affSColin Finck break;
957*c2c66affSColin Finck case WDML_QS_HANDLED:
958*c2c66affSColin Finck /* ok, we have resolved a pending transaction
959*c2c66affSColin Finck * notify callback if asynchronous.
960*c2c66affSColin Finck */
961*c2c66affSColin Finck if (pXAct->dwTimeout == TIMEOUT_ASYNC && pXAct->ddeMsg != WM_DDE_TERMINATE)
962*c2c66affSColin Finck {
963*c2c66affSColin Finck WDML_InvokeCallback(pConv->instance, XTYP_XACT_COMPLETE, pXAct->wFmt,
964*c2c66affSColin Finck (HCONV)pConv, pConv->hszTopic, pXAct->hszItem,
965*c2c66affSColin Finck pXAct->hDdeData, MAKELONG(0, pXAct->xActID), 0 /* FIXME */);
966*c2c66affSColin Finck qs = WDML_QS_PASS;
967*c2c66affSColin Finck }
968*c2c66affSColin Finck else
969*c2c66affSColin Finck {
970*c2c66affSColin Finck *hdd = pXAct->hDdeData;
971*c2c66affSColin Finck }
972*c2c66affSColin Finck break;
973*c2c66affSColin Finck case WDML_QS_PASS:
974*c2c66affSColin Finck /* no pending transaction found, try a warm/hot link or a termination request */
975*c2c66affSColin Finck switch (msg->message)
976*c2c66affSColin Finck {
977*c2c66affSColin Finck case WM_DDE_DATA:
978*c2c66affSColin Finck qs = WDML_HandleIncomingData(pConv, msg, hdd);
979*c2c66affSColin Finck break;
980*c2c66affSColin Finck case WM_DDE_TERMINATE:
981*c2c66affSColin Finck qs = WDML_HandleIncomingTerminate(pConv, msg, hdd);
982*c2c66affSColin Finck break;
983*c2c66affSColin Finck case WM_DDE_ACK:
984*c2c66affSColin Finck /* This happens at end of DdeClientTransaction XTYP_EXECUTE
985*c2c66affSColin Finck * Without this assignment, DdeClientTransaction's return value is undefined
986*c2c66affSColin Finck */
987*c2c66affSColin Finck *hdd = (HDDEDATA)TRUE;
988*c2c66affSColin Finck if (ack)
989*c2c66affSColin Finck *ack = DDE_FACK;
990*c2c66affSColin Finck break;
991*c2c66affSColin Finck }
992*c2c66affSColin Finck break;
993*c2c66affSColin Finck case WDML_QS_BLOCK:
994*c2c66affSColin Finck FIXME("shouldn't be used on client side\n");
995*c2c66affSColin Finck break;
996*c2c66affSColin Finck }
997*c2c66affSColin Finck
998*c2c66affSColin Finck return qs;
999*c2c66affSColin Finck }
1000*c2c66affSColin Finck
1001*c2c66affSColin Finck /******************************************************************
1002*c2c66affSColin Finck * WDML_SyncWaitTransactionReply
1003*c2c66affSColin Finck *
1004*c2c66affSColin Finck * waits until an answer for a sent request is received
1005*c2c66affSColin Finck * time out is also handled. only used for synchronous transactions
1006*c2c66affSColin Finck */
WDML_SyncWaitTransactionReply(HCONV hConv,DWORD dwTimeout,const WDML_XACT * pXAct,DWORD * ack)1007*c2c66affSColin Finck static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, const WDML_XACT* pXAct, DWORD *ack)
1008*c2c66affSColin Finck {
1009*c2c66affSColin Finck DWORD start, elapsed;
1010*c2c66affSColin Finck DWORD err;
1011*c2c66affSColin Finck WDML_CONV* pConv;
1012*c2c66affSColin Finck
1013*c2c66affSColin Finck TRACE("Starting wait for a timeout of %d ms\n", dwTimeout);
1014*c2c66affSColin Finck
1015*c2c66affSColin Finck start = GetTickCount();
1016*c2c66affSColin Finck while ((elapsed = GetTickCount() - start) < dwTimeout)
1017*c2c66affSColin Finck {
1018*c2c66affSColin Finck /* we cannot be in the crit sect all the time because when client and server run in a
1019*c2c66affSColin Finck * single process they need to share the access to the internal data
1020*c2c66affSColin Finck */
1021*c2c66affSColin Finck if (MsgWaitForMultipleObjects(0, NULL, FALSE,
1022*c2c66affSColin Finck dwTimeout - elapsed, QS_POSTMESSAGE) == WAIT_OBJECT_0)
1023*c2c66affSColin Finck {
1024*c2c66affSColin Finck MSG msg;
1025*c2c66affSColin Finck
1026*c2c66affSColin Finck while (PeekMessageW(&msg, 0, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE))
1027*c2c66affSColin Finck {
1028*c2c66affSColin Finck HDDEDATA hdd = NULL;
1029*c2c66affSColin Finck
1030*c2c66affSColin Finck pConv = WDML_GetConv(hConv, FALSE);
1031*c2c66affSColin Finck if (pConv == NULL)
1032*c2c66affSColin Finck {
1033*c2c66affSColin Finck /* conversation no longer available... return failure */
1034*c2c66affSColin Finck return 0;
1035*c2c66affSColin Finck }
1036*c2c66affSColin Finck if (msg.hwnd == pConv->hwndClient)
1037*c2c66affSColin Finck {
1038*c2c66affSColin Finck /* check that either pXAct has been processed or no more xActions are pending */
1039*c2c66affSColin Finck BOOL ret = (pConv->transactions == pXAct);
1040*c2c66affSColin Finck if (WDML_HandleReply(pConv, &msg, &hdd, ack) == WDML_QS_HANDLED)
1041*c2c66affSColin Finck {
1042*c2c66affSColin Finck TRACE("WDML_HandleReply returned WDML_QS_HANDLED\n");
1043*c2c66affSColin Finck ret = TRUE;
1044*c2c66affSColin Finck }
1045*c2c66affSColin Finck else
1046*c2c66affSColin Finck ret = (pConv->transactions == NULL || ret);
1047*c2c66affSColin Finck
1048*c2c66affSColin Finck if (ret)
1049*c2c66affSColin Finck {
1050*c2c66affSColin Finck pConv->instance->lastError = hdd ? DMLERR_NO_ERROR : DMLERR_NOTPROCESSED;
1051*c2c66affSColin Finck return hdd;
1052*c2c66affSColin Finck }
1053*c2c66affSColin Finck }
1054*c2c66affSColin Finck else
1055*c2c66affSColin Finck {
1056*c2c66affSColin Finck DispatchMessageW(&msg);
1057*c2c66affSColin Finck }
1058*c2c66affSColin Finck }
1059*c2c66affSColin Finck }
1060*c2c66affSColin Finck }
1061*c2c66affSColin Finck
1062*c2c66affSColin Finck TRACE("Timeout !!\n");
1063*c2c66affSColin Finck
1064*c2c66affSColin Finck pConv = WDML_GetConv(hConv, FALSE);
1065*c2c66affSColin Finck if (pConv != NULL)
1066*c2c66affSColin Finck {
1067*c2c66affSColin Finck if (pConv->transactions)
1068*c2c66affSColin Finck {
1069*c2c66affSColin Finck switch (pConv->transactions->ddeMsg)
1070*c2c66affSColin Finck {
1071*c2c66affSColin Finck case WM_DDE_ADVISE: err = DMLERR_ADVACKTIMEOUT; break;
1072*c2c66affSColin Finck case WM_DDE_REQUEST: err = DMLERR_DATAACKTIMEOUT; break;
1073*c2c66affSColin Finck case WM_DDE_EXECUTE: err = DMLERR_EXECACKTIMEOUT; break;
1074*c2c66affSColin Finck case WM_DDE_POKE: err = DMLERR_POKEACKTIMEOUT; break;
1075*c2c66affSColin Finck case WM_DDE_UNADVISE: err = DMLERR_UNADVACKTIMEOUT; break;
1076*c2c66affSColin Finck default: err = DMLERR_INVALIDPARAMETER; break;
1077*c2c66affSColin Finck }
1078*c2c66affSColin Finck
1079*c2c66affSColin Finck pConv->instance->lastError = err;
1080*c2c66affSColin Finck }
1081*c2c66affSColin Finck }
1082*c2c66affSColin Finck
1083*c2c66affSColin Finck return 0;
1084*c2c66affSColin Finck }
1085*c2c66affSColin Finck
1086*c2c66affSColin Finck
1087*c2c66affSColin Finck /*****************************************************************
1088*c2c66affSColin Finck * WDML_ClientHandle
1089*c2c66affSColin Finck */
WDML_ClientHandle(WDML_CONV * pConv,WDML_XACT * pXAct,DWORD dwTimeout,LPDWORD pdwResult)1090*c2c66affSColin Finck HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult)
1091*c2c66affSColin Finck {
1092*c2c66affSColin Finck HDDEDATA hDdeData;
1093*c2c66affSColin Finck
1094*c2c66affSColin Finck if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam))
1095*c2c66affSColin Finck {
1096*c2c66affSColin Finck WARN("Failed posting message %x to %p (error=0x%x)\n",
1097*c2c66affSColin Finck pXAct->ddeMsg, pConv->hwndServer, GetLastError());
1098*c2c66affSColin Finck pConv->wStatus &= ~ST_CONNECTED;
1099*c2c66affSColin Finck pConv->instance->lastError = DMLERR_POSTMSG_FAILED;
1100*c2c66affSColin Finck return 0;
1101*c2c66affSColin Finck }
1102*c2c66affSColin Finck pXAct->dwTimeout = dwTimeout;
1103*c2c66affSColin Finck /* FIXME: should set the app bits on *pdwResult */
1104*c2c66affSColin Finck
1105*c2c66affSColin Finck if (dwTimeout == TIMEOUT_ASYNC)
1106*c2c66affSColin Finck {
1107*c2c66affSColin Finck if (pdwResult)
1108*c2c66affSColin Finck *pdwResult = MAKELONG(0, pXAct->xActID);
1109*c2c66affSColin Finck
1110*c2c66affSColin Finck hDdeData = (HDDEDATA)1;
1111*c2c66affSColin Finck }
1112*c2c66affSColin Finck else
1113*c2c66affSColin Finck hDdeData = WDML_SyncWaitTransactionReply((HCONV)pConv, dwTimeout, pXAct, pdwResult);
1114*c2c66affSColin Finck
1115*c2c66affSColin Finck return hDdeData;
1116*c2c66affSColin Finck }
1117*c2c66affSColin Finck
1118*c2c66affSColin Finck
1119*c2c66affSColin Finck /*****************************************************************
1120*c2c66affSColin Finck * DdeClientTransaction (USER32.@)
1121*c2c66affSColin Finck */
DdeClientTransaction(LPBYTE pData,DWORD cbData,HCONV hConv,HSZ hszItem,UINT wFmt,UINT wType,DWORD dwTimeout,LPDWORD pdwResult)1122*c2c66affSColin Finck HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HSZ hszItem, UINT wFmt,
1123*c2c66affSColin Finck UINT wType, DWORD dwTimeout, LPDWORD pdwResult)
1124*c2c66affSColin Finck {
1125*c2c66affSColin Finck WDML_CONV* pConv;
1126*c2c66affSColin Finck WDML_XACT* pXAct;
1127*c2c66affSColin Finck HDDEDATA hDdeData;
1128*c2c66affSColin Finck
1129*c2c66affSColin Finck TRACE("(%p,%d,%p,%p,%x,%x,%d,%p)\n",
1130*c2c66affSColin Finck pData, cbData, hConv, hszItem, wFmt, wType, dwTimeout, pdwResult);
1131*c2c66affSColin Finck
1132*c2c66affSColin Finck if (hConv == 0)
1133*c2c66affSColin Finck {
1134*c2c66affSColin Finck WARN("Invalid conversation handle NULL\n");
1135*c2c66affSColin Finck return 0;
1136*c2c66affSColin Finck }
1137*c2c66affSColin Finck
1138*c2c66affSColin Finck pConv = WDML_GetConv(hConv, TRUE);
1139*c2c66affSColin Finck if (pConv == NULL)
1140*c2c66affSColin Finck {
1141*c2c66affSColin Finck /* cannot set error... cannot get back to DDE instance */
1142*c2c66affSColin Finck return 0;
1143*c2c66affSColin Finck }
1144*c2c66affSColin Finck
1145*c2c66affSColin Finck switch (wType)
1146*c2c66affSColin Finck {
1147*c2c66affSColin Finck case XTYP_EXECUTE:
1148*c2c66affSColin Finck /* Windows simply ignores hszItem and wFmt in this case */
1149*c2c66affSColin Finck pXAct = WDML_ClientQueueExecute(pConv, pData, cbData);
1150*c2c66affSColin Finck if (pXAct == NULL)
1151*c2c66affSColin Finck return 0;
1152*c2c66affSColin Finck break;
1153*c2c66affSColin Finck case XTYP_POKE:
1154*c2c66affSColin Finck if (!hszItem)
1155*c2c66affSColin Finck {
1156*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1157*c2c66affSColin Finck return 0;
1158*c2c66affSColin Finck }
1159*c2c66affSColin Finck pXAct = WDML_ClientQueuePoke(pConv, pData, cbData, wFmt, hszItem);
1160*c2c66affSColin Finck break;
1161*c2c66affSColin Finck case XTYP_ADVSTART|XTYPF_NODATA:
1162*c2c66affSColin Finck case XTYP_ADVSTART|XTYPF_NODATA|XTYPF_ACKREQ:
1163*c2c66affSColin Finck case XTYP_ADVSTART:
1164*c2c66affSColin Finck case XTYP_ADVSTART|XTYPF_ACKREQ:
1165*c2c66affSColin Finck if (pData)
1166*c2c66affSColin Finck {
1167*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1168*c2c66affSColin Finck return 0;
1169*c2c66affSColin Finck }
1170*c2c66affSColin Finck pXAct = WDML_ClientQueueAdvise(pConv, wType, wFmt, hszItem);
1171*c2c66affSColin Finck break;
1172*c2c66affSColin Finck case XTYP_ADVSTOP:
1173*c2c66affSColin Finck if (pData)
1174*c2c66affSColin Finck {
1175*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1176*c2c66affSColin Finck return 0;
1177*c2c66affSColin Finck }
1178*c2c66affSColin Finck pXAct = WDML_ClientQueueUnadvise(pConv, wFmt, hszItem);
1179*c2c66affSColin Finck break;
1180*c2c66affSColin Finck case XTYP_REQUEST:
1181*c2c66affSColin Finck if (pData || !hszItem)
1182*c2c66affSColin Finck {
1183*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1184*c2c66affSColin Finck return 0;
1185*c2c66affSColin Finck }
1186*c2c66affSColin Finck pXAct = WDML_ClientQueueRequest(pConv, wFmt, hszItem);
1187*c2c66affSColin Finck break;
1188*c2c66affSColin Finck default:
1189*c2c66affSColin Finck FIXME("Unknown transaction type %04x\n", wType);
1190*c2c66affSColin Finck /* unknown transaction type */
1191*c2c66affSColin Finck pConv->instance->lastError = DMLERR_INVALIDPARAMETER;
1192*c2c66affSColin Finck return 0;
1193*c2c66affSColin Finck }
1194*c2c66affSColin Finck
1195*c2c66affSColin Finck if (pXAct == NULL)
1196*c2c66affSColin Finck {
1197*c2c66affSColin Finck pConv->instance->lastError = DMLERR_MEMORY_ERROR;
1198*c2c66affSColin Finck return 0;
1199*c2c66affSColin Finck }
1200*c2c66affSColin Finck
1201*c2c66affSColin Finck WDML_QueueTransaction(pConv, pXAct);
1202*c2c66affSColin Finck
1203*c2c66affSColin Finck TRACE("pConv->wStatus %04x\n", pConv->wStatus);
1204*c2c66affSColin Finck
1205*c2c66affSColin Finck if (pConv->wStatus & ST_BLOCKED)
1206*c2c66affSColin Finck {
1207*c2c66affSColin Finck TRACE("Transactions are blocked, add to the queue and exit\n");
1208*c2c66affSColin Finck return (HDDEDATA)1;
1209*c2c66affSColin Finck }
1210*c2c66affSColin Finck
1211*c2c66affSColin Finck hDdeData = WDML_ClientHandle(pConv, pXAct, dwTimeout, pdwResult);
1212*c2c66affSColin Finck if (dwTimeout != TIMEOUT_ASYNC)
1213*c2c66affSColin Finck {
1214*c2c66affSColin Finck WDML_UnQueueTransaction(pConv, pXAct);
1215*c2c66affSColin Finck WDML_FreeTransaction(pConv->instance, pXAct, TRUE);
1216*c2c66affSColin Finck }
1217*c2c66affSColin Finck
1218*c2c66affSColin Finck return hDdeData;
1219*c2c66affSColin Finck }
1220*c2c66affSColin Finck
1221*c2c66affSColin Finck /*****************************************************************
1222*c2c66affSColin Finck * DdeAbandonTransaction (USER32.@)
1223*c2c66affSColin Finck */
DdeAbandonTransaction(DWORD idInst,HCONV hConv,DWORD idTransaction)1224*c2c66affSColin Finck BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction)
1225*c2c66affSColin Finck {
1226*c2c66affSColin Finck WDML_INSTANCE* pInstance;
1227*c2c66affSColin Finck WDML_CONV* pConv;
1228*c2c66affSColin Finck WDML_XACT* pXAct;
1229*c2c66affSColin Finck
1230*c2c66affSColin Finck if ((pInstance = WDML_GetInstance(idInst)))
1231*c2c66affSColin Finck {
1232*c2c66affSColin Finck if (hConv)
1233*c2c66affSColin Finck {
1234*c2c66affSColin Finck if ((pConv = WDML_GetConv(hConv, TRUE)) && pConv->instance == pInstance)
1235*c2c66affSColin Finck {
1236*c2c66affSColin Finck
1237*c2c66affSColin Finck pXAct = pConv->transactions;
1238*c2c66affSColin Finck while (pXAct) {
1239*c2c66affSColin Finck WDML_XACT *nextXAct = pXAct->next;
1240*c2c66affSColin Finck
1241*c2c66affSColin Finck if (pXAct->dwTimeout == TIMEOUT_ASYNC &&
1242*c2c66affSColin Finck (idTransaction == 0 || pXAct->xActID == idTransaction))
1243*c2c66affSColin Finck {
1244*c2c66affSColin Finck WDML_UnQueueTransaction(pConv, pXAct);
1245*c2c66affSColin Finck WDML_FreeTransaction(pInstance, pXAct, TRUE);
1246*c2c66affSColin Finck }
1247*c2c66affSColin Finck pXAct = nextXAct;
1248*c2c66affSColin Finck }
1249*c2c66affSColin Finck }
1250*c2c66affSColin Finck }
1251*c2c66affSColin Finck else
1252*c2c66affSColin Finck {
1253*c2c66affSColin Finck for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv; pConv = pConv->next)
1254*c2c66affSColin Finck {
1255*c2c66affSColin Finck if (!(pConv->wStatus & ST_CONNECTED)) continue;
1256*c2c66affSColin Finck pXAct = pConv->transactions;
1257*c2c66affSColin Finck while (pXAct) {
1258*c2c66affSColin Finck WDML_XACT *nextXAct = pXAct->next;
1259*c2c66affSColin Finck
1260*c2c66affSColin Finck if (pXAct->dwTimeout == TIMEOUT_ASYNC)
1261*c2c66affSColin Finck {
1262*c2c66affSColin Finck WDML_UnQueueTransaction(pConv, pXAct);
1263*c2c66affSColin Finck WDML_FreeTransaction(pInstance, pXAct, TRUE);
1264*c2c66affSColin Finck }
1265*c2c66affSColin Finck pXAct = nextXAct;
1266*c2c66affSColin Finck }
1267*c2c66affSColin Finck }
1268*c2c66affSColin Finck }
1269*c2c66affSColin Finck }
1270*c2c66affSColin Finck
1271*c2c66affSColin Finck return TRUE;
1272*c2c66affSColin Finck }
1273*c2c66affSColin Finck
1274*c2c66affSColin Finck /******************************************************************
1275*c2c66affSColin Finck * WDML_ClientProc
1276*c2c66affSColin Finck *
1277*c2c66affSColin Finck * Window Proc created on client side for each conversation
1278*c2c66affSColin Finck */
WDML_ClientProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)1279*c2c66affSColin Finck static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
1280*c2c66affSColin Finck {
1281*c2c66affSColin Finck UINT uiLo, uiHi;
1282*c2c66affSColin Finck WDML_CONV* pConv = NULL;
1283*c2c66affSColin Finck HSZ hszSrv, hszTpc;
1284*c2c66affSColin Finck
1285*c2c66affSColin Finck TRACE("%p %04x %08lx %08lx\n", hwnd, iMsg, wParam , lParam);
1286*c2c66affSColin Finck
1287*c2c66affSColin Finck if (iMsg == WM_DDE_ACK &&
1288*c2c66affSColin Finck /* in the initial WM_INITIATE sendmessage */
1289*c2c66affSColin Finck ((pConv = WDML_GetConvFromWnd(hwnd)) == NULL || pConv->wStatus == XST_INIT1))
1290*c2c66affSColin Finck {
1291*c2c66affSColin Finck /* In response to WM_DDE_INITIATE, save server window */
1292*c2c66affSColin Finck char buf[256];
1293*c2c66affSColin Finck WDML_INSTANCE* pInstance;
1294*c2c66affSColin Finck
1295*c2c66affSColin Finck /* note: sent messages do not need packing */
1296*c2c66affSColin Finck uiLo = LOWORD(lParam);
1297*c2c66affSColin Finck uiHi = HIWORD(lParam);
1298*c2c66affSColin Finck
1299*c2c66affSColin Finck /* FIXME: convlist should be handled here */
1300*c2c66affSColin Finck if (pConv)
1301*c2c66affSColin Finck {
1302*c2c66affSColin Finck /* we already have started the conv with a server, drop other replies */
1303*c2c66affSColin Finck GlobalDeleteAtom(uiLo);
1304*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
1305*c2c66affSColin Finck PostMessageW((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, 0);
1306*c2c66affSColin Finck return 0;
1307*c2c66affSColin Finck }
1308*c2c66affSColin Finck
1309*c2c66affSColin Finck pInstance = WDML_GetInstanceFromWnd(hwnd);
1310*c2c66affSColin Finck
1311*c2c66affSColin Finck hszSrv = WDML_MakeHszFromAtom(pInstance, uiLo);
1312*c2c66affSColin Finck hszTpc = WDML_MakeHszFromAtom(pInstance, uiHi);
1313*c2c66affSColin Finck
1314*c2c66affSColin Finck pConv = WDML_AddConv(pInstance, WDML_CLIENT_SIDE, hszSrv, hszTpc, hwnd, (HWND)wParam);
1315*c2c66affSColin Finck
1316*c2c66affSColin Finck SetWindowLongPtrW(hwnd, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv);
1317*c2c66affSColin Finck pConv->wStatus |= ST_CONNECTED;
1318*c2c66affSColin Finck pConv->wConvst = XST_INIT1;
1319*c2c66affSColin Finck
1320*c2c66affSColin Finck /* check if server is handled by DDEML */
1321*c2c66affSColin Finck if ((GetClassNameA((HWND)wParam, buf, sizeof(buf)) &&
1322*c2c66affSColin Finck lstrcmpiA(buf, WDML_szServerConvClassA) == 0) ||
1323*c2c66affSColin Finck (GetClassNameW((HWND)wParam, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) &&
1324*c2c66affSColin Finck lstrcmpiW((LPWSTR)buf, WDML_szServerConvClassW) == 0))
1325*c2c66affSColin Finck {
1326*c2c66affSColin Finck pConv->wStatus |= ST_ISLOCAL;
1327*c2c66affSColin Finck }
1328*c2c66affSColin Finck
1329*c2c66affSColin Finck GlobalDeleteAtom(uiLo);
1330*c2c66affSColin Finck GlobalDeleteAtom(uiHi);
1331*c2c66affSColin Finck
1332*c2c66affSColin Finck /* accept conversation */
1333*c2c66affSColin Finck return 1;
1334*c2c66affSColin Finck }
1335*c2c66affSColin Finck
1336*c2c66affSColin Finck if (iMsg >= WM_DDE_FIRST && iMsg <= WM_DDE_LAST)
1337*c2c66affSColin Finck {
1338*c2c66affSColin Finck pConv = WDML_GetConvFromWnd(hwnd);
1339*c2c66affSColin Finck
1340*c2c66affSColin Finck if (pConv)
1341*c2c66affSColin Finck {
1342*c2c66affSColin Finck MSG msg;
1343*c2c66affSColin Finck HDDEDATA hdd;
1344*c2c66affSColin Finck
1345*c2c66affSColin Finck msg.hwnd = hwnd;
1346*c2c66affSColin Finck msg.message = iMsg;
1347*c2c66affSColin Finck msg.wParam = wParam;
1348*c2c66affSColin Finck msg.lParam = lParam;
1349*c2c66affSColin Finck
1350*c2c66affSColin Finck WDML_HandleReply(pConv, &msg, &hdd, NULL);
1351*c2c66affSColin Finck }
1352*c2c66affSColin Finck
1353*c2c66affSColin Finck return 0;
1354*c2c66affSColin Finck }
1355*c2c66affSColin Finck
1356*c2c66affSColin Finck return IsWindowUnicode(hwnd) ? DefWindowProcW(hwnd, iMsg, wParam, lParam) :
1357*c2c66affSColin Finck DefWindowProcA(hwnd, iMsg, wParam, lParam);
1358*c2c66affSColin Finck }
1359*c2c66affSColin Finck
1360*c2c66affSColin Finck /*****************************************************************
1361*c2c66affSColin Finck * DdeDisconnect (USER32.@)
1362*c2c66affSColin Finck */
DdeDisconnect(HCONV hConv)1363*c2c66affSColin Finck BOOL WINAPI DdeDisconnect(HCONV hConv)
1364*c2c66affSColin Finck {
1365*c2c66affSColin Finck WDML_CONV* pConv;
1366*c2c66affSColin Finck WDML_XACT* pXAct;
1367*c2c66affSColin Finck BOOL ret = FALSE;
1368*c2c66affSColin Finck
1369*c2c66affSColin Finck TRACE("(%p)\n", hConv);
1370*c2c66affSColin Finck
1371*c2c66affSColin Finck if (hConv == 0)
1372*c2c66affSColin Finck {
1373*c2c66affSColin Finck WARN("DdeDisconnect(): hConv = 0\n");
1374*c2c66affSColin Finck return FALSE;
1375*c2c66affSColin Finck }
1376*c2c66affSColin Finck
1377*c2c66affSColin Finck pConv = WDML_GetConv(hConv, TRUE);
1378*c2c66affSColin Finck if (pConv != NULL)
1379*c2c66affSColin Finck {
1380*c2c66affSColin Finck if (pConv->wStatus & ST_CLIENT)
1381*c2c66affSColin Finck {
1382*c2c66affSColin Finck /* FIXME: should abandon all pending transactions */
1383*c2c66affSColin Finck pXAct = WDML_ClientQueueTerminate(pConv);
1384*c2c66affSColin Finck if (pXAct != NULL)
1385*c2c66affSColin Finck {
1386*c2c66affSColin Finck if (PostMessageW(pConv->hwndServer, pXAct->ddeMsg,
1387*c2c66affSColin Finck (WPARAM)pConv->hwndClient, pXAct->lParam))
1388*c2c66affSColin Finck {
1389*c2c66affSColin Finck WDML_SyncWaitTransactionReply(hConv, 10000, pXAct, NULL);
1390*c2c66affSColin Finck ret = TRUE;
1391*c2c66affSColin Finck }
1392*c2c66affSColin Finck else
1393*c2c66affSColin Finck pConv->instance->lastError = DMLERR_POSTMSG_FAILED;
1394*c2c66affSColin Finck
1395*c2c66affSColin Finck WDML_FreeTransaction(pConv->instance, pXAct, TRUE);
1396*c2c66affSColin Finck /* still have to destroy data associated with conversation */
1397*c2c66affSColin Finck WDML_RemoveConv(pConv, WDML_CLIENT_SIDE);
1398*c2c66affSColin Finck }
1399*c2c66affSColin Finck else
1400*c2c66affSColin Finck {
1401*c2c66affSColin Finck FIXME("Not implemented yet for a server side conversation\n");
1402*c2c66affSColin Finck }
1403*c2c66affSColin Finck }
1404*c2c66affSColin Finck }
1405*c2c66affSColin Finck
1406*c2c66affSColin Finck return ret;
1407*c2c66affSColin Finck }
1408*c2c66affSColin Finck
1409*c2c66affSColin Finck /*****************************************************************
1410*c2c66affSColin Finck * DdeImpersonateClient (USER32.@)
1411*c2c66affSColin Finck */
DdeImpersonateClient(HCONV hConv)1412*c2c66affSColin Finck BOOL WINAPI DdeImpersonateClient(HCONV hConv)
1413*c2c66affSColin Finck {
1414*c2c66affSColin Finck WDML_CONV* pConv;
1415*c2c66affSColin Finck BOOL ret = FALSE;
1416*c2c66affSColin Finck
1417*c2c66affSColin Finck TRACE("(%p)\n", hConv);
1418*c2c66affSColin Finck
1419*c2c66affSColin Finck pConv = WDML_GetConv(hConv, TRUE);
1420*c2c66affSColin Finck if (pConv)
1421*c2c66affSColin Finck {
1422*c2c66affSColin Finck ret = ImpersonateDdeClientWindow(pConv->hwndClient, pConv->hwndServer);
1423*c2c66affSColin Finck }
1424*c2c66affSColin Finck return ret;
1425*c2c66affSColin Finck }
1426