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