following the raw DDE patch, this patch fixes a few things because of raw DDE implementation, fixes lots of memory issues (leaks, even if some remain), and adds a few new pieces (CreateDdeDataHandle now supports bitmaps handle, transaction abandon is implemented) A+ -- --------------- Eric Pouech (http://perso.wanadoo.fr/eric.pouech/) "The future will be better tomorrow", Vice President Dan Quayle
Name: ddeml ChangeLog: fixed initialisation messages for raw DDE fixed DdeCreateDataHandle for non NULL or CF_TEXT formats various fixes (cosmetics, better error checking) GenDate: 2002/01/12 14:32:24 UTC ModifiedFiles: dlls/user/dde/dde_private.h dlls/user/dde/client.c dlls/user/dde/misc.c dlls/user/dde/server.c AddedFiles: =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/user/dde/dde_private.h,v retrieving revision 1.3 diff -u -u -r1.3 dde_private.h --- dlls/user/dde/dde_private.h 18 Aug 2001 16:11:28 -0000 1.3 +++ dlls/user/dde/dde_private.h 6 Jan 2002 21:23:44 -0000 @@ -132,7 +132,6 @@ UINT transactionType;/* 0 for no link */ HSZ hszItem; /* item targetted for (hot/warm) link */ UINT uFmt; /* format for data */ - HDDEDATA hDdeData; /* data them selves */ } WDML_LINK; typedef struct tagWDML_INSTANCE @@ -161,6 +160,7 @@ typedef struct tagDDE_DATAHANDLE_HEAD { short cfFormat; + WORD bAppOwned; } DDE_DATAHANDLE_HEAD; typedef enum tagWDML_SIDE @@ -191,12 +191,12 @@ extern WDML_CONV* WDML_GetConvFromWnd(HWND hWnd); extern WDML_CONV* WDML_FindConv(WDML_INSTANCE* pInstance, WDML_SIDE side, HSZ hszService, HSZ hszTopic); -extern LPARAM WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, - BOOL fBusy, BOOL fAck, ATOM atom, LPARAM lParam, UINT oldMsg); +extern BOOL WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, + BOOL fBusy, BOOL fAck, UINT pmt, LPARAM lParam, UINT oldMsg); extern void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, UINT wType, HSZ hszItem, UINT wFmt); extern WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, - HSZ hszItem, UINT uFmt); + HSZ hszItem, BOOL use_fmt, UINT uFmt); extern void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, HSZ hszItem, UINT wFmt); extern void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE side); @@ -215,6 +215,7 @@ extern HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease, BOOL fDeferUpd, BOOL dAckReq); extern HDDEDATA WDML_Global2DataHandle(HGLOBAL hMem, WINE_DDEHEAD* da); +extern BOOL WDML_IsAppOwned(HDDEDATA hDdeData); extern WDML_INSTANCE* WDML_GetInstance(DWORD InstId); extern WDML_INSTANCE* WDML_GetInstanceFromWnd(HWND hWnd); /* broadcasting to DDE windows */ Index: dlls/user/dde/client.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/user/dde/client.c,v retrieving revision 1.4 diff -u -u -r1.4 client.c --- dlls/user/dde/client.c 14 Sep 2001 00:24:40 -0000 1.4 +++ dlls/user/dde/client.c 6 Jan 2002 22:03:02 -0000 @@ -46,8 +46,7 @@ HCONVLIST WINAPI DdeConnectList(DWORD idInst, HSZ hszService, HSZ hszTopic, HCONVLIST hConvList, LPCONVCONTEXT pCC) { - FIXME("(%ld,%d,%d,%d,%p): stub\n", idInst, hszService, hszTopic, - hConvList, pCC); + FIXME("(%ld,%d,%d,%d,%p): stub\n", idInst, hszService, hszTopic, hConvList, pCC); return (HCONVLIST)1; } @@ -84,7 +83,6 @@ LPCONVCONTEXT pCC) { HWND hwndClient; - LPARAM lParam = 0; WDML_INSTANCE* pInstance; WDML_CONV* pConv = NULL; ATOM aSrv = 0, aTpc = 0; @@ -168,9 +166,8 @@ LeaveCriticalSection(&WDML_CritSect); - lParam = PackDDElParam(WM_DDE_INITIATE, aSrv, aTpc); - SendMessageA(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hwndClient, lParam); - FreeDDElParam(WM_DDE_INITIATE, lParam); + /* note: sent messages shall not use packing */ + SendMessageA(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hwndClient, MAKELPARAM(aSrv, aTpc)); EnterCriticalSection(&WDML_CritSect); @@ -180,17 +177,17 @@ goto theEnd; } - TRACE("WM_DDE_INITIATE was processed\n"); /* At this point, Client WM_DDE_ACK should have saved hwndServer for this instance id and hwndClient if server responds. So get HCONV and return it. And add it to conv list */ pConv = WDML_GetConvFromWnd(hwndClient); if (pConv == NULL || pConv->hwndServer == 0) { - ERR(".. but no Server window available\n"); + ERR("Done with INITIATE, but no Server window available\n"); pConv = NULL; goto theEnd; } + TRACE("Connected to Server window (%x)\n", pConv->hwndServer); pConv->wConvst = XST_CONNECTED; /* finish init of pConv */ @@ -227,7 +224,6 @@ pConv = WDML_GetConv(hConv, FALSE); if (pConv != NULL && (pConv->wStatus & ST_CLIENT)) { - LPARAM lParam; BOOL ret; /* to reestablist a connection, we have to make sure that: @@ -251,9 +247,9 @@ LeaveCriticalSection(&WDML_CritSect); - lParam = PackDDElParam(WM_DDE_INITIATE, aSrv, aTpc); - ret = SendMessageA(hwndServer, WM_DDE_INITIATE, (WPARAM)hwndClient, lParam); - FreeDDElParam(WM_DDE_INITIATE, lParam); + /* note: sent messages shall not use packing */ + ret = SendMessageA(hwndServer, WM_DDE_INITIATE, (WPARAM)hwndClient, + MAKELPARAM(aSrv, aTpc)); EnterCriticalSection(&WDML_CritSect); @@ -320,7 +316,8 @@ pXAct->wType = wType & ~0x0F; pXAct->hMem = GlobalAlloc(GHND | GMEM_DDESHARE, sizeof(DDEADVISE)); - + /* FIXME: hMem is unfreed for now... should be deleted in server */ + /* pack DdeAdvise */ pDdeAdvise = (DDEADVISE*)GlobalLock(pXAct->hMem); pDdeAdvise->fAckReq = (wType & XTYPF_ACKREQ) ? TRUE : FALSE; @@ -366,7 +363,7 @@ /* billx: first to see if the link is already created. */ pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, - pXAct->hszItem, pXAct->wFmt); + pXAct->hszItem, TRUE, pXAct->wFmt); if (pLink != NULL) { /* we found a link, and only need to modify it in case it changes */ @@ -377,14 +374,15 @@ WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, pXAct->wType, pXAct->hszItem, pXAct->wFmt); } + pXAct->hDdeData = (HDDEDATA)1; } else { - TRACE("Returning TRUE on XTYP_ADVSTART - fAck was FALSE\n"); + TRACE("Returning FALSE on XTYP_ADVSTART - fAck was FALSE\n"); GlobalFree(pXAct->hMem); + pXAct->hDdeData = (HDDEDATA)0; } - pXAct->hDdeData = (HDDEDATA)1; return WDML_QS_HANDLED; } @@ -448,15 +446,16 @@ if (!ddeAck.fAck) { - TRACE("Returning TRUE on XTYP_ADVSTOP - fAck was FALSE\n"); + TRACE("Returning FALSE on XTYP_ADVSTOP - fAck was FALSE\n"); + pXAct->hDdeData = (HDDEDATA)0; } else { /* billx: remove the link */ WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, pXAct->hszItem, pXAct->wFmt); + pXAct->hDdeData = (HDDEDATA)1; } - pXAct->hDdeData = (HDDEDATA)1; return WDML_QS_HANDLED; } @@ -501,11 +500,12 @@ if (WIN_GetFullHandle(msg->wParam) != pConv->hwndServer) return WDML_QS_PASS; - UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi); switch (msg->message) { case WM_DDE_ACK: + UnpackDDElParam(WM_DDE_ACK, msg->lParam, &uiLo, &uiHi); + FreeDDElParam(WM_DDE_ACK, msg->lParam); GlobalDeleteAtom(uiHi); WDML_ExtractAck(uiLo, &ddeAck); pXAct->hDdeData = 0; @@ -515,6 +515,7 @@ break; case WM_DDE_DATA: + UnpackDDElParam(WM_DDE_DATA, msg->lParam, &uiLo, &uiHi); TRACE("Got the result (%08lx)\n", (DWORD)uiLo); hsz = WDML_MakeHszFromAtom(pConv->instance, uiHi); @@ -522,7 +523,6 @@ if (DdeCmpStringHandles(hsz, pXAct->hszItem) != 0) return WDML_QS_PASS; - /* FIXME: memory clean up ? */ pXAct->hDdeData = WDML_Global2DataHandle((HGLOBAL)uiLo, &wdh); if (wdh.fRelease) { @@ -530,16 +530,17 @@ } if (wdh.fAckReq) { - WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, (HSZ)uiHi, msg->lParam, - WM_DDE_DATA); + WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA); } else { GlobalDeleteAtom(uiHi); + FreeDDElParam(WM_DDE_ACK, msg->lParam); } break; default: + FreeDDElParam(msg->message, msg->lParam); return WDML_QS_PASS; } @@ -669,15 +670,12 @@ if (uiHi != pXAct->hMem) { - return WDML_QS_PASS; + return WDML_QS_PASS; } WDML_ExtractAck(uiLo, &ddeAck); - if (!ddeAck.fAck) - { - GlobalFree(pXAct->hMem); - } - pXAct->hDdeData = (HDDEDATA)1; + pXAct->hDdeData = (HDDEDATA)ddeAck.fAck; + return WDML_QS_HANDLED; } @@ -832,17 +830,18 @@ * For hot link, data should be passed to its callback with * XTYP_ADVDATA and callback should return the proper status. */ - pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, hsz, wdh.cfFormat); + pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_CLIENT_SIDE, hsz, + uiLo ? TRUE : FALSE, wdh.cfFormat); if (!pLink) { WDML_DecHSZ(pConv->instance, hsz); + DdeFreeDataHandle(hDdeDataIn); return WDML_QS_PASS; } if (hDdeDataIn != 0 && wdh.fAckReq) { - WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, - msg->lParam, WM_DDE_DATA); + WDML_PostAck(pConv, WDML_CLIENT_SIDE, 0, FALSE, TRUE, uiHi, msg->lParam, WM_DDE_DATA); if (msg->lParam) msg->lParam = 0; } @@ -853,14 +852,16 @@ hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_ADVDATA, pLink->uFmt, pLink->hConv, pConv->hszTopic, pLink->hszItem, hDdeDataIn, 0, 0); - if (hDdeDataOut == (HDDEDATA)DDE_FACK) - { - pLink->hDdeData = hDdeDataIn; - } - if (wdh.fRelease) + + if (hDdeDataOut != (HDDEDATA)DDE_FACK || wdh.fRelease) { - DdeFreeDataHandle(hDdeDataIn); + if (uiLo) + { + GlobalFree(uiLo); + } } + + DdeFreeDataHandle(hDdeDataIn); WDML_DecHSZ(pConv->instance, hsz); if (msg->lParam) @@ -961,10 +962,10 @@ { *hdd = pXAct->hDdeData; } - WDML_FreeTransaction(pConv->instance, pXAct, FALSE); /* FIXME: should we free intermediate pmts ? */ + WDML_FreeTransaction(pConv->instance, pXAct, TRUE); break; case WDML_QS_PASS: - /* no pending transaction found, try a warm link or a termination request */ + /* no pending transaction found, try a warm/hot link or a termination request */ switch (msg->message) { case WM_DDE_DATA: @@ -1006,7 +1007,7 @@ * single process they need to share the access to the internal data */ if (MsgWaitForMultipleObjects(0, NULL, FALSE, - dwTime - dwTimeout, QS_POSTMESSAGE) == WAIT_OBJECT_0) + dwTimeout - dwTime, QS_POSTMESSAGE) == WAIT_OBJECT_0) { BOOL ret = FALSE; MSG msg; @@ -1156,7 +1157,6 @@ WDML_UnQueueTransaction(pConv, pXAct); WDML_FreeTransaction(pConv->instance, pXAct, TRUE); goto theError; - } pXAct->dwTimeout = dwTimeout; /* FIXME: should set the app bits on *pdwResult */ @@ -1192,6 +1192,56 @@ return 0; } +/***************************************************************** + * DdeAbandonTransaction (USER32.@) + */ +BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction) +{ + WDML_INSTANCE* pInstance; + WDML_CONV* pConv; + WDML_XACT* pXAct; + + TRACE("(%08lx,%08lx,%08ld);\n", idInst, (DWORD)hConv, idTransaction); + + EnterCriticalSection(&WDML_CritSect); + if ((pInstance = WDML_GetInstance(idInst))) + { + if (hConv) + { + if ((pConv = WDML_GetConv(hConv, TRUE)) && pConv->instance == pInstance) + { + for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next) + { + if (pXAct->dwTimeout == TIMEOUT_ASYNC && + (idTransaction == 0 || pXAct->xActID == idTransaction)) + { + WDML_UnQueueTransaction(pConv, pXAct); + WDML_FreeTransaction(pInstance, pXAct, TRUE); + } + } + } + } + else + { + for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv; pConv = pConv->next) + { + if (!pConv->wStatus & ST_CONNECTED) continue; + for (pXAct = pConv->transactions; pXAct; pXAct = pXAct->next) + { + if (pXAct->dwTimeout == TIMEOUT_ASYNC) + { + WDML_UnQueueTransaction(pConv, pXAct); + WDML_FreeTransaction(pInstance, pXAct, TRUE); + } + } + } + } + } + LeaveCriticalSection(&WDML_CritSect); + + return TRUE; +} + /****************************************************************** * WDML_ClientProc * @@ -1204,7 +1254,6 @@ HSZ hszSrv, hszTpc; if (iMsg == WM_DDE_ACK && - UnpackDDElParam(WM_DDE_ACK, lParam, &uiLo, &uiHi) && /* in the initial WM_INITIATE sendmessage */ ((pConv = WDML_GetConvFromWnd(hwnd)) == NULL || pConv->wStatus == XST_INIT1)) { @@ -1212,7 +1261,9 @@ char buf[256]; WDML_INSTANCE* pInstance; - FreeDDElParam(WM_DDE_ACK, lParam); + /* note: sent messages do not need packing */ + uiLo = LOWORD(lParam); + uiHi = HIWORD(lParam); /* FIXME: convlist should be handled here */ if (pConv) @@ -1220,6 +1271,7 @@ /* we already have started the conv with a server, drop other replies */ GlobalDeleteAtom(uiLo); GlobalDeleteAtom(uiHi); + PostMessageA((HWND)wParam, WM_DDE_TERMINATE, (WPARAM)hwnd, 0); return 0; } @@ -1228,8 +1280,7 @@ hszSrv = WDML_MakeHszFromAtom(pInstance, uiLo); hszTpc = WDML_MakeHszFromAtom(pInstance, uiHi); - pConv = WDML_AddConv(pInstance, WDML_CLIENT_SIDE, hszSrv, hszTpc, - hwnd, (HWND)wParam); + pConv = WDML_AddConv(pInstance, WDML_CLIENT_SIDE, hszSrv, hszTpc, hwnd, (HWND)wParam); SetWindowLongA(hwnd, GWL_WDML_CONVERSATION, (DWORD)pConv); pConv->wStatus |= ST_CONNECTED; @@ -1281,15 +1332,6 @@ } /***************************************************************** - * DdeAbandonTransaction (USER32.@) - */ -BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction) -{ - FIXME("empty stub\n"); - return TRUE; -} - -/***************************************************************** * DdeDisconnect (USER32.@) */ BOOL WINAPI DdeDisconnect(HCONV hConv) @@ -1308,33 +1350,33 @@ } EnterCriticalSection(&WDML_CritSect); - pConv = WDML_GetConv(hConv, FALSE); + pConv = WDML_GetConv(hConv, TRUE); if (pConv != NULL) { - if (pConv->wStatus & ST_CONNECTED) - { - if (pConv->wStatus & ST_CLIENT) - { - /* FIXME: should abandon all pending transactions */ - pXAct = WDML_ClientQueueTerminate(pConv); - if (pXAct != NULL) - { - count = WDML_CritSect.RecursionCount; - for (i = 0; i < count; i++) - LeaveCriticalSection(&WDML_CritSect); - WDML_SyncWaitTransactionReply(hConv, 10000, pXAct); - for (i = 0; i < count; i++) - EnterCriticalSection(&WDML_CritSect); - ret = TRUE; - } - else - { - FIXME("Not implemented yet for a server side conversation\n"); - } - } - } - /* still have to destroy data assosiated with conversation */ - WDML_RemoveConv(pConv, WDML_CLIENT_SIDE); + if (pConv->wStatus & ST_CLIENT) + { + /* FIXME: should abandon all pending transactions */ + pXAct = WDML_ClientQueueTerminate(pConv); + if (pXAct != NULL) + { + count = WDML_CritSect.RecursionCount; + for (i = 0; i < count; i++) + LeaveCriticalSection(&WDML_CritSect); + if (PostMessageA(pConv->hwndServer, pXAct->ddeMsg, + (WPARAM)pConv->hwndClient, pXAct->lParam)) + WDML_SyncWaitTransactionReply(hConv, 10000, pXAct); + for (i = 0; i < count; i++) + EnterCriticalSection(&WDML_CritSect); + ret = TRUE; + WDML_FreeTransaction(pConv->instance, pXAct, TRUE); + /* still have to destroy data assosiated with conversation */ + WDML_RemoveConv(pConv, WDML_CLIENT_SIDE); + } + else + { + FIXME("Not implemented yet for a server side conversation\n"); + } + } } LeaveCriticalSection(&WDML_CritSect); Index: dlls/user/dde/misc.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/user/dde/misc.c,v retrieving revision 1.6 diff -u -u -r1.6 misc.c --- dlls/user/dde/misc.c 14 Sep 2001 00:24:40 -0000 1.6 +++ dlls/user/dde/misc.c 6 Jan 2002 22:02:40 -0000 @@ -86,7 +86,7 @@ params = GlobalLock(hMem); if (params == NULL) { - ERR("GlobalLock failed\n"); + ERR("GlobalLock failed (%x)\n", hMem); return 0; } @@ -130,7 +130,7 @@ params = GlobalLock(hMem); if (params == NULL) { - ERR("GlobalLock failed\n"); + ERR("GlobalLock failed (%x)\n", hMem); return FALSE; } @@ -383,9 +383,7 @@ if (!pInstance->clientOnly) { - /* Check for other way of setting Client-only !! */ - pInstance->clientOnly = (pInstance->CBFflags & CBF_FAIL_ALLSVRXACTIONS) == CBF_FAIL_ALLSVRXACTIONS; } @@ -622,7 +620,6 @@ /* Stage one - check if we have a handle for this instance */ WDML_INSTANCE* pInstance; - WDML_INSTANCE* reference_inst; WDML_CONV* pConv; WDML_CONV* pConvNext; @@ -665,20 +662,16 @@ if (WDML_InstanceList == pInstance) { - /* special case - the first/only entry - */ + /* special case - the first/only entry */ WDML_InstanceList = pInstance->next; } else { - /* general case - */ - reference_inst = WDML_InstanceList; - while (reference_inst->next != pInstance) - { - reference_inst = pInstance->next; - } - reference_inst->next = pInstance->next; + /* general case, remove entry */ + WDML_INSTANCE* inst; + + for (inst = WDML_InstanceList; inst->next != pInstance; inst = inst->next); + inst->next = pInstance->next; } /* leave crit sect and release the heap entry */ @@ -849,7 +842,7 @@ if (GetAtomNameW((ATOM)hsz, nameBuffer, MAX_BUFFER_LEN)) return GlobalAddAtomW(nameBuffer); - WARN("HSZ 0x%xnot found\n", hsz); + WARN("HSZ 0x%x not found\n", hsz); return 0; } @@ -864,8 +857,15 @@ { WCHAR nameBuffer[MAX_BUFFER_LEN]; - GlobalGetAtomNameW(atom, nameBuffer, MAX_BUFFER_LEN); - return DdeCreateStringHandleW(pInstance->instanceID, nameBuffer, CP_WINUNICODE); + if (!atom) return (HSZ)0; + + if (GlobalGetAtomNameW(atom, nameBuffer, MAX_BUFFER_LEN)) + { + TRACE("%x => %s\n", atom, debugstr_w(nameBuffer)); + return DdeCreateStringHandleW(pInstance->instanceID, nameBuffer, CP_WINUNICODE); + } + WARN("ATOM 0x%x not found\n", atom); + return 0; } /****************************************************************** @@ -914,12 +914,12 @@ pPrev->next = pCurrent->next; } HeapFree(GetProcessHeap(), 0, pCurrent); - DeleteAtom(hsz); + DeleteAtom((ATOM)hsz); } return TRUE; } } - WARN("HSZ 0x%xnot found\n", hsz); + WARN("HSZ 0x%x not found\n", hsz); return FALSE; } @@ -989,10 +989,10 @@ switch (codepage) { case CP_WINANSI: - ret = GetAtomNameA(hsz, ptr, cchMax); + ret = GetAtomNameA((ATOM)hsz, ptr, cchMax); break; case CP_WINUNICODE: - ret = GetAtomNameW(hsz, ptr, cchMax); + ret = GetAtomNameW((ATOM)hsz, ptr, cchMax); default: ERR("Unknown code page %d\n", codepage); ret = 0; @@ -1035,8 +1035,7 @@ DWORD ret = 0; WDML_INSTANCE* pInstance; - TRACE("(%ld, 0x%x, %p, %ld, %d)\n", - idInst, hsz, psz, cchMax, iCodePage); + TRACE("(%ld, 0x%x, %p, %ld, %d)\n", idInst, hsz, psz, cchMax, iCodePage); EnterCriticalSection(&WDML_CritSect); @@ -1066,11 +1065,11 @@ switch (codepage) { case CP_WINANSI: - hsz = AddAtomA(ptr); + hsz = (HSZ)AddAtomA(ptr); TRACE("added atom %s with HSZ 0x%x, \n", debugstr_a(ptr), hsz); break; case CP_WINUNICODE: - hsz = AddAtomW(ptr); + hsz = (HSZ)AddAtomW(ptr); TRACE("added atom %s with HSZ 0x%x, \n", debugstr_w(ptr), hsz); break; default: @@ -1208,8 +1207,8 @@ int ret = 0; int ret1, ret2; - ret1 = GetAtomNameW(hsz1, psz1, MAX_BUFFER_LEN); - ret2 = GetAtomNameW(hsz2, psz2, MAX_BUFFER_LEN); + ret1 = GetAtomNameW((ATOM)hsz1, psz1, MAX_BUFFER_LEN); + ret2 = GetAtomNameW((ATOM)hsz2, psz2, MAX_BUFFER_LEN); TRACE("(%x<%s> %x<%s>);\n", hsz1, debugstr_w(psz1), hsz2, debugstr_w(psz2)); @@ -1260,22 +1259,23 @@ /***************************************************************** * DdeCreateDataHandle (USER32.@) */ -HDDEDATA WINAPI DdeCreateDataHandle(DWORD idInst, LPBYTE pSrc, DWORD cb, - DWORD cbOff, HSZ hszItem, UINT wFmt, - UINT afCmd) -{ - /* - For now, we ignore idInst, hszItem, wFmt, and afCmd. - The purpose of these arguments still need to be investigated. - */ +HDDEDATA WINAPI DdeCreateDataHandle(DWORD idInst, LPBYTE pSrc, DWORD cb, DWORD cbOff, + HSZ hszItem, UINT wFmt, UINT afCmd) +{ + /* For now, we ignore idInst, hszItem. + * The purpose of these arguments still need to be investigated. + */ HGLOBAL hMem; LPBYTE pByte; DDE_DATAHANDLE_HEAD* pDdh; - TRACE("(%ld,%p,%ld,%ld,0x%lx,%d,%d): semi-stub\n", - idInst,pSrc,cb,cbOff,(DWORD)hszItem,wFmt,afCmd); + TRACE("(%ld,%p,%ld,%ld,0x%lx,%d,%d)\n", + idInst, pSrc, cb, cbOff, (DWORD)hszItem, wFmt, afCmd); + if (afCmd != 0 && afCmd != HDATA_APPOWNED) + return 0; + /* we use the first 4 bytes to store the size */ if (!(hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, cb + sizeof(DDE_DATAHANDLE_HEAD)))) { @@ -1284,8 +1284,15 @@ } pDdh = (DDE_DATAHANDLE_HEAD*)GlobalLock(hMem); + if (!pDdh) + { + GlobalFree(hMem); + return 0; + } + pDdh->cfFormat = wFmt; - + pDdh->bAppOwned = (afCmd == HDATA_APPOWNED); + pByte = (LPBYTE)(pDdh + 1); if (pSrc) { @@ -1420,6 +1427,25 @@ return GlobalFree((HGLOBAL)hData) == 0; } +/****************************************************************** + * WDML_IsAppOwned + * + * + */ +BOOL WDML_IsAppOwned(HDDEDATA hData) +{ + DDE_DATAHANDLE_HEAD* pDdh; + BOOL ret = FALSE; + + pDdh = (DDE_DATAHANDLE_HEAD*)GlobalLock((HGLOBAL)hData); + if (pDdh != NULL) + { + ret = pDdh->bAppOwned; + GlobalUnlock((HGLOBAL)hData); + } + return ret; +} + /* ================================================================ * * Global <=> Data handle management @@ -1437,17 +1463,51 @@ { DDEDATA* pDd; HDDEDATA ret = 0; + DWORD size; if (hMem) { pDd = GlobalLock(hMem); + size = GlobalSize(hMem) - sizeof(WINE_DDEHEAD); if (pDd) { if (p) memcpy(p, pDd, sizeof(WINE_DDEHEAD)); - ret = DdeCreateDataHandle(0, pDd->Value, - GlobalSize(hMem) - sizeof(WINE_DDEHEAD), - 0, 0, pDd->cfFormat, 0); - GlobalUnlock(hMem); + switch (pDd->cfFormat) + { + default: + FIXME("Unsupported format (%d) for data... assuming raw information\n", + pDd->cfFormat); + /* fall thru */ + case 0: + case CF_TEXT: + ret = DdeCreateDataHandle(0, pDd->Value, size, 0, 0, pDd->cfFormat, 0); + break; + case CF_BITMAP: + if (size >= sizeof(BITMAP)) + { + BITMAP* bmp = (BITMAP*)pDd->Value; + int count = bmp->bmWidthBytes * bmp->bmHeight * bmp->bmPlanes; + if (size >= sizeof(BITMAP) + count) + { + HBITMAP hbmp; + + if ((hbmp = CreateBitmap(bmp->bmWidth, bmp->bmHeight, + bmp->bmPlanes, bmp->bmBitsPixel, + pDd->Value + sizeof(BITMAP)))) + { + ret = DdeCreateDataHandle(0, (LPBYTE)&hbmp, sizeof(hbmp), + 0, 0, CF_BITMAP, 0); + } + else ERR("Can't create bmp\n"); + } + else + { + ERR("Wrong count: %lu / %d\n", size, sizeof(BITMAP) + count); + } + } else ERR("No bitmap header\n"); + break; + } + GlobalUnlock(hMem); } } return ret; @@ -1465,28 +1525,56 @@ DWORD dwSize; HGLOBAL hMem = 0; - dwSize = GlobalSize(hDdeData) - sizeof(DDE_DATAHANDLE_HEAD); - pDdh = (DDE_DATAHANDLE_HEAD*)GlobalLock(hDdeData); + dwSize = GlobalSize((HGLOBAL)hDdeData) - sizeof(DDE_DATAHANDLE_HEAD); + pDdh = (DDE_DATAHANDLE_HEAD*)GlobalLock((HGLOBAL)hDdeData); if (dwSize && pDdh) { - hMem = GlobalAlloc(sizeof(WINE_DDEHEAD) + dwSize, GMEM_MOVEABLE | GMEM_DDESHARE); - if (hMem) - { - WINE_DDEHEAD* wdh; + WINE_DDEHEAD* wdh = NULL; - wdh = GlobalLock(hMem); - if (wdh) + switch (pDdh->cfFormat) + { + default: + FIXME("Unsupported format (%d) for data... passing raw information\n", pDdh->cfFormat); + /* fall thru */ + case 0: + case CF_TEXT: + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(WINE_DDEHEAD) + dwSize); + if (hMem && (wdh = GlobalLock(hMem))) { - wdh->fResponse = fResponse; - wdh->fRelease = fRelease; - wdh->fDeferUpd = fDeferUpd; - wdh->fAckReq = fAckReq; - wdh->cfFormat = pDdh->cfFormat; memcpy(wdh + 1, pDdh + 1, dwSize); - GlobalUnlock(hMem); } + break; + case CF_BITMAP: + if (dwSize >= sizeof(HBITMAP)) + { + BITMAP bmp; + DWORD count; + HBITMAP hbmp = *(HBITMAP*)(pDdh + 1); + + if (GetObjectA(hbmp, sizeof(bmp), &bmp)) + { + count = bmp.bmWidthBytes * bmp.bmHeight; + hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, + sizeof(WINE_DDEHEAD) + sizeof(bmp) + count); + if (hMem && (wdh = GlobalLock(hMem))) + { + memcpy(wdh + 1, &bmp, sizeof(bmp)); + GetBitmapBits(hbmp, count, ((char*)(wdh + 1)) + sizeof(bmp)); + } + } + } + break; } - GlobalUnlock(hDdeData); + if (wdh) + { + wdh->fResponse = fResponse; + wdh->fRelease = fRelease; + wdh->fDeferUpd = fDeferUpd; + wdh->fAckReq = fAckReq; + wdh->cfFormat = pDdh->cfFormat; + GlobalUnlock(hMem); + } + GlobalUnlock((HGLOBAL)hDdeData); } return hMem; @@ -1779,8 +1867,8 @@ * * */ -LPARAM WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, - BOOL fBusy, BOOL fAck, ATOM atom, LPARAM lParam, UINT oldMsg) +BOOL WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode, + BOOL fBusy, BOOL fAck, UINT pmt, LPARAM lParam, UINT oldMsg) { DDEACK ddeAck; HWND from, to; @@ -1803,16 +1891,15 @@ TRACE("Posting a %s ack\n", ddeAck.fAck ? "positive" : "negative"); - if (lParam) { - PostMessageA(to, WM_DDE_ACK, (WPARAM)from, - ReuseDDElParam(lParam, oldMsg, WM_DDE_ACK, *(WORD*)&ddeAck, atom)); + lParam = (lParam) ? ReuseDDElParam(lParam, oldMsg, WM_DDE_ACK, *(WORD*)&ddeAck, pmt) : + PackDDElParam(WM_DDE_ACK, *(WORD*)&ddeAck, pmt); + if (!PostMessageA(to, WM_DDE_ACK, (WPARAM)from, lParam)) + { + pConv->wStatus &= ~ST_CONNECTED; + FreeDDElParam(WM_DDE_ACK, lParam); + return FALSE; } - else - { - lParam = PackDDElParam(WM_DDE_ACK, *(WORD*)&ddeAck, atom); - PostMessageA(to, WM_DDE_ACK, (WPARAM)from, lParam); - } - return lParam; + return TRUE; } /***************************************************************** @@ -1949,9 +2036,9 @@ { ret = 0; } - else if (hConv & 1) + else if ((DWORD)hConv & 1) { - pConv = WDML_GetConv(hConv & ~1, FALSE); + pConv = WDML_GetConv((DWORD)hConv & ~1, FALSE); if (pConv != NULL) { FIXME("Request on remote conversation information is not implemented yet\n"); @@ -1960,7 +2047,7 @@ } LeaveCriticalSection(&WDML_CritSect); if (ret != 0) - memcpy(lpConvInfo, &ci, min(lpConvInfo->cb, sizeof(ci))); + memcpy(lpConvInfo, &ci, min((size_t)lpConvInfo->cb, sizeof(ci))); return ret; } @@ -1991,7 +2078,6 @@ pLink->transactionType = wType; WDML_IncHSZ(pInstance, pLink->hszItem = hszItem); pLink->uFmt = wFmt; - pLink->hDdeData = 0; pLink->next = pInstance->links[side]; pInstance->links[side] = pLink; } @@ -2024,11 +2110,6 @@ pPrev->next = pCurrent->next; } - if (pCurrent->hDdeData) - { - DdeFreeDataHandle(pCurrent->hDdeData); - } - WDML_DecHSZ(pInstance, pCurrent->hszItem); HeapFree(GetProcessHeap(), 0, pCurrent); break; @@ -2071,10 +2152,6 @@ pNext = pCurrent->next; } - if (pCurrent->hDdeData) - { - DdeFreeDataHandle(pCurrent->hDdeData); - } WDML_DecHSZ(pInstance, pCurrent->hszItem); HeapFree(GetProcessHeap(), 0, pCurrent); @@ -2099,7 +2176,7 @@ * */ WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side, - HSZ hszItem, UINT uFmt) + HSZ hszItem, BOOL use_fmt, UINT uFmt) { WDML_LINK* pCurrent = NULL; @@ -2109,7 +2186,7 @@ if (pCurrent->hConv == hConv && DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 && - pCurrent->uFmt == uFmt) + (!use_fmt || pCurrent->uFmt == uFmt)) { break; } @@ -2150,7 +2227,7 @@ pXAct->next = NULL; pXAct->wType = 0; pXAct->wFmt = wFmt; - WDML_IncHSZ(pInstance, pXAct->hszItem = hszItem); + if ((pXAct->hszItem = hszItem)) WDML_IncHSZ(pInstance, pXAct->hszItem); pXAct->atom = 0; pXAct->hMem = 0; pXAct->lParam = 0; @@ -2199,10 +2276,12 @@ */ void WDML_FreeTransaction(WDML_INSTANCE* pInstance, WDML_XACT* pXAct, BOOL doFreePmt) { - /* free pmt(s) in pXAct too */ - if (doFreePmt && pXAct->hMem) + /* free pmt(s) in pXAct too. check against one for not deleting TRUE return values */ + if (doFreePmt && (DWORD)pXAct->hMem > 1) + { GlobalFree(pXAct->hMem); - WDML_DecHSZ(pInstance, pXAct->hszItem); + } + if (pXAct->hszItem) WDML_DecHSZ(pInstance, pXAct->hszItem); HeapFree(GetProcessHeap(), 0, pXAct); } Index: dlls/user/dde/server.c =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/user/dde/server.c,v retrieving revision 1.5 diff -u -u -r1.5 server.c --- dlls/user/dde/server.c 14 Sep 2001 00:24:40 -0000 1.5 +++ dlls/user/dde/server.c 6 Jan 2002 22:02:26 -0000 @@ -47,7 +47,8 @@ { WDML_INSTANCE* pInstance = NULL; WDML_LINK* pLink = NULL; - HDDEDATA hDdeData = 0, hItemData = 0; + HDDEDATA hDdeData = 0; + HGLOBAL hItemData = 0; WDML_CONV* pConv = NULL; ATOM atom = 0; UINT count; @@ -88,7 +89,7 @@ hDdeData = WDML_InvokeCallback(pInstance, XTYP_ADVREQ, pLink->uFmt, pLink->hConv, hszTopic, hszItem, 0, count--, 0); - if (hDdeData == CBR_BLOCK) + if (hDdeData == (HDDEDATA)CBR_BLOCK) { /* MS doc is not consistent here */ FIXME("CBR_BLOCK returned for ADVREQ\n"); @@ -112,8 +113,7 @@ if (pConv == NULL) { - /* FIXME: wrong if app owned... */ - DdeFreeDataHandle(hDdeData); + if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); goto theError; } @@ -121,11 +121,12 @@ PackDDElParam(WM_DDE_DATA, (UINT)hItemData, atom))) { ERR("post message failed\n"); - /* FIXME: wrong if app owned... */ - DdeFreeDataHandle(hDdeData); + pConv->wStatus &= ~ST_CONNECTED; + if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); GlobalFree(hItemData); goto theError; - } + } + if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); } } } @@ -352,10 +353,9 @@ SetWindowLongA(hwndServerConv, GWL_WDML_CONVERSATION, (DWORD)pConv); /* this should be the only place using SendMessage for WM_DDE_ACK */ + /* note: sent messages shall not use packing */ SendMessageA(hwndClient, WM_DDE_ACK, (WPARAM)hwndServerConv, - PackDDElParam(WM_DDE_ACK, - WDML_MakeAtomFromHsz(hszApp), - WDML_MakeAtomFromHsz(hszTopic))); + MAKELPARAM(WDML_MakeAtomFromHsz(hszApp), WDML_MakeAtomFromHsz(hszTopic))); /* we assume we're connected since we've sent an answer... * I'm not sure what we can do... it doesn't look like the return value * of SendMessage is used... sigh... @@ -457,7 +457,7 @@ hDdeData = WDML_InvokeCallback(pInstance, XTYP_WILDCONNECT, 0, 0, hszTop, hszApp, 0, (DWORD)pcc, self); - if (hDdeData == CBR_BLOCK) + if (hDdeData == (HDDEDATA)CBR_BLOCK) { /* MS doc is not consistent here */ FIXME("CBR_BLOCK returned for WILDCONNECT\n"); @@ -478,13 +478,10 @@ } DdeUnaccessData(hDdeData); } + if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); } } } - /* - billx: make a conv and add it to the server list - - this can be delayed when link is created for the conv. NO NEED !!! - */ return 0; @@ -548,11 +545,11 @@ pConv->hszTopic, pXAct->hszItem, 0, 0, 0); } - switch (hDdeData) + switch ((DWORD)hDdeData) { case 0: - WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, FALSE, pXAct->hszItem, - pXAct->lParam, WM_DDE_REQUEST); + WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, FALSE, pXAct->atom, + pXAct->lParam, WM_DDE_REQUEST); break; case CBR_BLOCK: ret = WDML_QS_BLOCK; @@ -587,7 +584,8 @@ /* XTYP_ADVSTART transaction: establish link and save link info to InstanceInfoTable */ - UnpackDDElParam(WM_DDE_ADVISE, lParam, &uiLo, &uiHi); + if (!UnpackDDElParam(WM_DDE_ADVISE, lParam, &uiLo, &uiHi)) + return NULL; pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, 0, WDML_MakeHszFromAtom(pConv->instance, uiHi)); @@ -633,7 +631,7 @@ /* billx: first to see if the link is already created. */ pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, - pXAct->hszItem, pDdeAdvise->cfFormat); + pXAct->hszItem, TRUE, pDdeAdvise->cfFormat); if (pLink != NULL) { @@ -643,7 +641,6 @@ else { TRACE("Adding Link with hConv=0x%lx\n", (DWORD)pConv); - WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, uType, pXAct->hszItem, pDdeAdvise->cfFormat); } @@ -656,7 +653,10 @@ GlobalUnlock(pXAct->hMem); if (fAck) + { GlobalFree(pXAct->hMem); + } + pXAct->hMem = 0; WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_ADVISE); @@ -699,7 +699,7 @@ } pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, - pXAct->hszItem, pXAct->wFmt); + pXAct->hszItem, TRUE, pXAct->wFmt); if (pLink == NULL) { ERR("Couln'd find link for %08lx, dropping request\n", (DWORD)pXAct->hszItem); @@ -718,7 +718,7 @@ /* send back ack */ WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, TRUE, pXAct->atom, - pXAct->lParam, WM_DDE_UNADVISE); + pXAct->lParam, WM_DDE_UNADVISE); WDML_DecHSZ(pConv->instance, pXAct->hszItem); @@ -856,8 +856,9 @@ GlobalUnlock(pXAct->hMem); if (!fAck) + { GlobalFree(pXAct->hMem); - + } WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, fBusy, fAck, pXAct->atom, pXAct->lParam, WM_DDE_POKE); WDML_DecHSZ(pConv->instance, pXAct->hszItem); @@ -893,7 +894,6 @@ WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv, 0, 0, 0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0); } - PostMessageA(pConv->hwndClient, WM_DDE_TERMINATE, (WPARAM)pConv->hwndServer, 0); WDML_RemoveConv(pConv, WDML_SERVER_SIDE);