xref: /reactos/win32ss/user/user32/misc/ddeclient.c (revision 3d93998d)
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