Fixed initialisation messages for raw DDE.
Fixed DdeCreateDataHandle for non NULL or CF_TEXT formats.
Various fixes (cosmetics, better error checking).
diff --git a/dlls/user/dde/client.c b/dlls/user/dde/client.c
index dd45595..2bf99a5 100644
--- a/dlls/user/dde/client.c
+++ b/dlls/user/dde/client.c
@@ -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)
+
+ if (hDdeDataOut != (HDDEDATA)DDE_FACK || wdh.fRelease)
{
- pLink->hDdeData = hDdeDataIn;
+ if (uiLo)
+ {
+ GlobalFree(uiLo);
+ }
}
- if (wdh.fRelease)
- {
- DdeFreeDataHandle(hDdeDataIn);
- }
+
+ 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);
diff --git a/dlls/user/dde/dde_private.h b/dlls/user/dde/dde_private.h
index af7a679..ff397d8 100644
--- a/dlls/user/dde/dde_private.h
+++ b/dlls/user/dde/dde_private.h
@@ -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 */
diff --git a/dlls/user/dde/misc.c b/dlls/user/dde/misc.c
index 532f005..d930cb6 100644
--- a/dlls/user/dde/misc.c
+++ b/dlls/user/dde/misc.c
@@ -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)
+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.
- */
+ /* 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));
- }
- else
+ 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))
{
- lParam = PackDDElParam(WM_DDE_ACK, *(WORD*)&ddeAck, atom);
- PostMessageA(to, WM_DDE_ACK, (WPARAM)from, lParam);
+ pConv->wStatus &= ~ST_CONNECTED;
+ FreeDDElParam(WM_DDE_ACK, lParam);
+ return FALSE;
}
- 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);
}
diff --git a/dlls/user/dde/server.c b/dlls/user/dde/server.c
index 301c244..7a18dc6 100644
--- a/dlls/user/dde/server.c
+++ b/dlls/user/dde/server.c
@@ -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);