Fixed initialisation messages for raw DDE.

Fixed DdeCreateDataHandle for non NULL or CF_TEXT formats.
Various fixes (cosmetics, better error checking).
This commit is contained in:
Eric Pouech 2002-01-18 19:30:15 +00:00 committed by Alexandre Julliard
parent 0faceb05fc
commit 01ff68943d
4 changed files with 316 additions and 194 deletions

View File

@ -46,8 +46,7 @@ const WCHAR WDML_szClientConvClassW[] = {'D','d','e','C','l','i','e','n','t','U'
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 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
LPCONVCONTEXT pCC)
{
HWND hwndClient;
LPARAM lParam = 0;
WDML_INSTANCE* pInstance;
WDML_CONV* pConv = NULL;
ATOM aSrv = 0, aTpc = 0;
@ -168,9 +166,8 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
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 @@ HCONV WINAPI DdeConnect(DWORD idInst, HSZ hszService, HSZ hszTopic,
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 @@ HCONV WINAPI DdeReconnect(HCONV hConv)
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 @@ HCONV WINAPI DdeReconnect(HCONV hConv)
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,6 +316,7 @@ static WDML_XACT* WDML_ClientQueueAdvise(WDML_CONV* pConv, UINT wType, UINT wFmt
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);
@ -366,7 +363,7 @@ static WDML_QUEUE_STATE WDML_HandleAdviseReply(WDML_CONV* pConv, MSG* msg, WDML_
/* 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 @@ static WDML_QUEUE_STATE WDML_HandleAdviseReply(WDML_CONV* pConv, MSG* msg, WDML_
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 @@ static WDML_QUEUE_STATE WDML_HandleUnadviseReply(WDML_CONV* pConv, MSG* msg, WDM
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;
}
return WDML_QS_HANDLED;
}
@ -501,11 +500,12 @@ static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML
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 @@ static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML
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 @@ static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML
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 @@ static WDML_QUEUE_STATE WDML_HandleRequestReply(WDML_CONV* pConv, MSG* msg, WDML
}
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;
}
@ -673,11 +674,8 @@ static WDML_QUEUE_STATE WDML_HandleExecuteReply(WDML_CONV* pConv, MSG* msg, WDML
}
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 @@ static WDML_QUEUE_STATE WDML_HandleIncomingData(WDML_CONV* pConv, MSG* msg, HDDE
* 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 @@ static WDML_QUEUE_STATE WDML_HandleIncomingData(WDML_CONV* pConv, MSG* msg, HDDE
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);
}
WDML_DecHSZ(pConv->instance, hsz);
if (msg->lParam)
@ -961,10 +962,10 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h
{
*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 @@ static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, WDML
* 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 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS
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 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS
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 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
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 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
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 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
/* 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 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
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;
@ -1280,15 +1331,6 @@ static LRESULT CALLBACK WDML_ClientProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPA
DefWindowProcA(hwnd, iMsg, wParam, lParam) : DefWindowProcW(hwnd, iMsg, wParam, lParam);
}
/*****************************************************************
* DdeAbandonTransaction (USER32.@)
*/
BOOL WINAPI DdeAbandonTransaction(DWORD idInst, HCONV hConv, DWORD idTransaction)
{
FIXME("empty stub\n");
return TRUE;
}
/*****************************************************************
* DdeDisconnect (USER32.@)
*/
@ -1308,10 +1350,8 @@ BOOL WINAPI DdeDisconnect(HCONV hConv)
}
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)
{
@ -1322,10 +1362,15 @@ BOOL WINAPI DdeDisconnect(HCONV hConv)
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
{
@ -1333,9 +1378,6 @@ BOOL WINAPI DdeDisconnect(HCONV hConv)
}
}
}
/* still have to destroy data assosiated with conversation */
WDML_RemoveConv(pConv, WDML_CLIENT_SIDE);
}
LeaveCriticalSection(&WDML_CritSect);
return ret;

View File

@ -132,7 +132,6 @@ typedef struct tagWDML_LINK {
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 @@ extern CRITICAL_SECTION WDML_CritSect; /* protection for instance list */
typedef struct tagDDE_DATAHANDLE_HEAD
{
short cfFormat;
WORD bAppOwned;
} DDE_DATAHANDLE_HEAD;
typedef enum tagWDML_SIDE
@ -191,12 +191,12 @@ extern WDML_CONV* WDML_GetConv(HCONV hConv, BOOL checkConnected);
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 WDML_XACT* WDML_FindTransaction(WDML_CONV* pConv, DWORD tid);
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 */

View File

@ -86,7 +86,7 @@ LPARAM WINAPI PackDDElParam(UINT msg, UINT uiLo, UINT uiHi)
params = GlobalLock(hMem);
if (params == NULL)
{
ERR("GlobalLock failed\n");
ERR("GlobalLock failed (%x)\n", hMem);
return 0;
}
@ -130,7 +130,7 @@ BOOL WINAPI UnpackDDElParam(UINT msg, LPARAM lParam,
params = GlobalLock(hMem);
if (params == NULL)
{
ERR("GlobalLock failed\n");
ERR("GlobalLock failed (%x)\n", hMem);
return FALSE;
}
@ -383,9 +383,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,
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 @@ BOOL WINAPI DdeUninitialize(DWORD idInst)
/* 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 @@ BOOL WINAPI DdeUninitialize(DWORD idInst)
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
*/
@ -864,9 +857,16 @@ HSZ WDML_MakeHszFromAtom(WDML_INSTANCE* pInstance, ATOM atom)
{
WCHAR nameBuffer[MAX_BUFFER_LEN];
GlobalGetAtomNameW(atom, nameBuffer, MAX_BUFFER_LEN);
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;
}
/******************************************************************
* WDML_IncHSZ
@ -914,7 +914,7 @@ BOOL WDML_DecHSZ(WDML_INSTANCE* pInstance, HSZ hsz)
pPrev->next = pCurrent->next;
}
HeapFree(GetProcessHeap(), 0, pCurrent);
DeleteAtom(hsz);
DeleteAtom((ATOM)hsz);
}
return TRUE;
}
@ -989,10 +989,10 @@ static int WDML_QueryString(WDML_INSTANCE* pInstance, HSZ hsz, LPVOID ptr, DWORD
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 WINAPI DdeQueryStringW(DWORD idInst, HSZ hsz, LPWSTR psz, DWORD cchMax, IN
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 @@ static HSZ WDML_CreateString(WDML_INSTANCE* pInstance, LPCVOID ptr, int codepage
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 WINAPI DdeCmpStringHandles(HSZ hsz1, HSZ hsz2)
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 @@ INT WINAPI DdeCmpStringHandles(HSZ hsz1, HSZ hsz2)
/*****************************************************************
* 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",
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,7 +1284,14 @@ HDDEDATA WINAPI DdeCreateDataHandle(DWORD idInst, LPBYTE pSrc, DWORD cb,
}
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 @@ BOOL WINAPI DdeFreeDataHandle(HDDEDATA hData)
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,16 +1463,50 @@ HDDEDATA WDML_Global2DataHandle(HGLOBAL hMem, WINE_DDEHEAD* p)
{
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);
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);
}
}
@ -1465,16 +1525,46 @@ HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease,
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);
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)))
{
memcpy(wdh + 1, pDdh + 1, dwSize);
}
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;
}
if (wdh)
{
wdh->fResponse = fResponse;
@ -1482,11 +1572,9 @@ HGLOBAL WDML_DataHandle2Global(HDDEDATA hDdeData, BOOL fResponse, BOOL fRelease,
wdh->fDeferUpd = fDeferUpd;
wdh->fAckReq = fAckReq;
wdh->cfFormat = pDdh->cfFormat;
memcpy(wdh + 1, pDdh + 1, dwSize);
GlobalUnlock(hMem);
}
}
GlobalUnlock(hDdeData);
GlobalUnlock((HGLOBAL)hDdeData);
}
return hMem;
@ -1779,8 +1867,8 @@ WDML_CONV* WDML_GetConvFromWnd(HWND hWnd)
*
*
*/
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 @@ LPARAM WDML_PostAck(WDML_CONV* pConv, WDML_SIDE side, WORD appRetCode,
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 @@ UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, LPCONVINFO lpConvInfo)
{
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 @@ UINT WINAPI DdeQueryConvInfo(HCONV hConv, DWORD id, LPCONVINFO lpConvInfo)
}
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 @@ void WDML_AddLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
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 @@ void WDML_RemoveLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
pPrev->next = pCurrent->next;
}
if (pCurrent->hDdeData)
{
DdeFreeDataHandle(pCurrent->hDdeData);
}
WDML_DecHSZ(pInstance, pCurrent->hszItem);
HeapFree(GetProcessHeap(), 0, pCurrent);
break;
@ -2071,10 +2152,6 @@ void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE s
pNext = pCurrent->next;
}
if (pCurrent->hDdeData)
{
DdeFreeDataHandle(pCurrent->hDdeData);
}
WDML_DecHSZ(pInstance, pCurrent->hszItem);
HeapFree(GetProcessHeap(), 0, pCurrent);
@ -2099,7 +2176,7 @@ void WDML_RemoveAllLinks(WDML_INSTANCE* pInstance, WDML_CONV* pConv, WDML_SIDE s
*
*/
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 @@ WDML_LINK* WDML_FindLink(WDML_INSTANCE* pInstance, HCONV hConv, WDML_SIDE side,
if (pCurrent->hConv == hConv &&
DdeCmpStringHandles(pCurrent->hszItem, hszItem) == 0 &&
pCurrent->uFmt == uFmt)
(!use_fmt || pCurrent->uFmt == uFmt))
{
break;
}
@ -2150,7 +2227,7 @@ WDML_XACT* WDML_AllocTransaction(WDML_INSTANCE* pInstance, UINT ddeMsg,
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 @@ BOOL WDML_UnQueueTransaction(WDML_CONV* pConv, WDML_XACT* pXAct)
*/
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);
}

View File

@ -47,7 +47,8 @@ BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem)
{
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 @@ BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem)
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 @@ BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem)
if (pConv == NULL)
{
/* FIXME: wrong if app owned... */
DdeFreeDataHandle(hDdeData);
if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData);
goto theError;
}
@ -121,11 +121,12 @@ BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem)
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 @@ static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClien
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 @@ static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM w
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 @@ static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM w
}
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,10 +545,10 @@ static WDML_QUEUE_STATE WDML_ServerHandleRequest(WDML_CONV* pConv, WDML_XACT* pX
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,
WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, FALSE, pXAct->atom,
pXAct->lParam, WM_DDE_REQUEST);
break;
case CBR_BLOCK:
@ -587,7 +584,8 @@ static WDML_XACT* WDML_ServerQueueAdvise(WDML_CONV* pConv, LPARAM lParam)
/* 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 @@ static WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXA
/* 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 @@ static WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXA
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 @@ static WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXA
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 @@ static WDML_QUEUE_STATE WDML_ServerHandleUnadvise(WDML_CONV* pConv, WDML_XACT* p
}
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);
@ -856,8 +856,9 @@ static WDML_QUEUE_STATE WDML_ServerHandlePoke(WDML_CONV* pConv, WDML_XACT* pXAct
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 @@ static WDML_QUEUE_STATE WDML_ServerHandleTerminate(WDML_CONV* pConv, WDML_XACT*
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);