From 3a7bd674795daca2dbf159fce2eb14c44754a68f Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Tue, 21 Nov 2006 14:43:48 +0800 Subject: [PATCH] user32: Add support for DdeEnableCallback(EC_DISABLE) command. --- dlls/user32/dde_client.c | 74 +++++++++++++++++++++++++-------------- dlls/user32/dde_misc.c | 61 ++++++++++++++++++++++++++++---- dlls/user32/dde_private.h | 3 ++ dlls/user32/dde_server.c | 7 +++- 4 files changed, 111 insertions(+), 34 deletions(-) diff --git a/dlls/user32/dde_client.c b/dlls/user32/dde_client.c index 2d345f005c3..1441e715c9c 100644 --- a/dlls/user32/dde_client.c +++ b/dlls/user32/dde_client.c @@ -792,7 +792,7 @@ static WDML_XACT* WDML_ClientQueueTerminate(WDML_CONV* pConv) * * handles the reply to a terminate request */ -static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV* pConv, MSG* msg, WDML_XACT* pXAct) +static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV* pConv, MSG* msg) { if (msg->message != WM_DDE_TERMINATE) { @@ -815,7 +815,7 @@ static WDML_QUEUE_STATE WDML_HandleTerminateReply(WDML_CONV* pConv, MSG* msg, WD } /****************************************************************** - * WDML_HandleReplyData + * WDML_HandleIncomingData * * */ @@ -934,7 +934,7 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h qs = WDML_HandlePokeReply(pConv, msg, pXAct, ack); break; case WM_DDE_TERMINATE: - qs = WDML_HandleTerminateReply(pConv, msg, pXAct); + qs = WDML_HandleTerminateReply(pConv, msg); break; default: qs = WDML_QS_ERROR; @@ -955,9 +955,8 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h break; case WDML_QS_HANDLED: /* ok, we have resolved a pending transaction - * notify callback if asynchronous, and remove it in any case + * notify callback if asynchronous. */ - WDML_UnQueueTransaction(pConv, pXAct); if (pXAct->dwTimeout == TIMEOUT_ASYNC && pXAct->ddeMsg != WM_DDE_TERMINATE) { WDML_InvokeCallback(pConv->instance, XTYP_XACT_COMPLETE, pXAct->wFmt, @@ -969,7 +968,6 @@ static WDML_QUEUE_STATE WDML_HandleReply(WDML_CONV* pConv, MSG* msg, HDDEDATA* h { *hdd = pXAct->hDdeData; } - WDML_FreeTransaction(pConv->instance, pXAct, TRUE); break; case WDML_QS_PASS: /* no pending transaction found, try a warm/hot link or a termination request */ @@ -1078,6 +1076,39 @@ static HDDEDATA WDML_SyncWaitTransactionReply(HCONV hConv, DWORD dwTimeout, WDML return 0; } + +/***************************************************************** + * WDML_ClientHandle + */ +HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult) +{ + HDDEDATA hDdeData; + + if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam)) + { + WARN("Failed posting message %x to %p (error=0x%x)\n", + pXAct->ddeMsg, pConv->hwndServer, GetLastError()); + pConv->wStatus &= ~ST_CONNECTED; + pConv->instance->lastError = DMLERR_POSTMSG_FAILED; + return 0; + } + pXAct->dwTimeout = dwTimeout; + /* FIXME: should set the app bits on *pdwResult */ + + if (dwTimeout == TIMEOUT_ASYNC) + { + if (pdwResult) + *pdwResult = MAKELONG(0, pXAct->xActID); + + hDdeData = (HDDEDATA)1; + } + else + hDdeData = WDML_SyncWaitTransactionReply((HCONV)pConv, dwTimeout, pXAct, pdwResult); + + return hDdeData; +} + + /***************************************************************** * DdeClientTransaction (USER32.@) */ @@ -1155,29 +1186,20 @@ HDDEDATA WINAPI DdeClientTransaction(LPBYTE pData, DWORD cbData, HCONV hConv, HS WDML_QueueTransaction(pConv, pXAct); - if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam)) - { - WARN("Failed posting message %x to %p (error=0x%x)\n", - pXAct->ddeMsg, pConv->hwndServer, GetLastError()); - pConv->wStatus &= ~ST_CONNECTED; - WDML_UnQueueTransaction(pConv, pXAct); - WDML_FreeTransaction(pConv->instance, pXAct, TRUE); - pConv->instance->lastError = DMLERR_POSTMSG_FAILED; - return 0; - } - pXAct->dwTimeout = dwTimeout; - /* FIXME: should set the app bits on *pdwResult */ + TRACE("pConv->wStatus %04x\n", pConv->wStatus); - if (dwTimeout == TIMEOUT_ASYNC) + if (pConv->wStatus & ST_BLOCKED) { - if (pdwResult) - { - *pdwResult = MAKELONG(0, pXAct->xActID); - } - hDdeData = (HDDEDATA)1; + TRACE("Transactions are blocked, add to the queue and exit\n"); + return (HDDEDATA)1; + } + + hDdeData = WDML_ClientHandle(pConv, pXAct, dwTimeout, pdwResult); + if (dwTimeout != TIMEOUT_ASYNC) + { + WDML_UnQueueTransaction(pConv, pXAct); + WDML_FreeTransaction(pConv->instance, pXAct, TRUE); } - else - hDdeData = WDML_SyncWaitTransactionReply(hConv, dwTimeout, pXAct, pdwResult); return hDdeData; } diff --git a/dlls/user32/dde_misc.c b/dlls/user32/dde_misc.c index 0afb2edac50..bcb4cea7fdd 100644 --- a/dlls/user32/dde_misc.c +++ b/dlls/user32/dde_misc.c @@ -382,6 +382,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback, pInstance->win16 = b16; pInstance->nodeList = NULL; /* node will be added later */ pInstance->monitorFlags = afCmd & MF_MASK; + pInstance->wStatus = 0; pInstance->servers = NULL; pInstance->convs[0] = NULL; pInstance->convs[1] = NULL; @@ -1740,6 +1741,7 @@ WDML_CONV* WDML_AddConv(WDML_INSTANCE* pInstance, WDML_SIDE side, pConv->transactions = NULL; pConv->hUser = 0; pConv->wStatus = (side == WDML_CLIENT_SIDE) ? ST_CLIENT : 0L; + pConv->wStatus |= pInstance->wStatus; /* check if both side of the conversation are of the same instance */ if (GetWindowThreadProcessId(hwndClient, NULL) == GetWindowThreadProcessId(hwndServer, NULL) && WDML_GetInstanceFromWnd(hwndClient) == WDML_GetInstanceFromWnd(hwndServer)) @@ -1751,6 +1753,8 @@ WDML_CONV* WDML_AddConv(WDML_INSTANCE* pInstance, WDML_SIDE side, pConv->next = pInstance->convs[side]; pInstance->convs[side] = pConv; + TRACE("pConv->wStatus %04x\n", pConv->wStatus); + return pConv; } @@ -1842,7 +1846,8 @@ static BOOL WDML_EnableCallback(WDML_CONV *pConv, UINT wCmd) { if (wCmd == EC_DISABLE) { - FIXME("EC_DISABLE is not implemented\n"); + pConv->wStatus |= ST_BLOCKED; + TRACE("EC_DISABLE: conv %p status flags %04x\n", pConv, pConv->wStatus); return TRUE; } @@ -1855,18 +1860,28 @@ static BOOL WDML_EnableCallback(WDML_CONV *pConv, UINT wCmd) return FALSE; } + if (wCmd == EC_ENABLEALL) + { + pConv->wStatus &= ~ST_BLOCKED; + TRACE("EC_ENABLEALL: conv %p status flags %04x\n", pConv, pConv->wStatus); + } + while (pConv->transactions) { WDML_XACT *pXAct = pConv->transactions; - WDML_UnQueueTransaction(pConv, pXAct); if (pConv->wStatus & ST_CLIENT) { - /*WDML_ClientHandle(pConv, pXAct);*/ - FIXME("Client delayed transaction queue handling is not supported\n"); + /* transaction should be in the queue until handled */ + WDML_ClientHandle(pConv, pXAct, 0, NULL); + WDML_UnQueueTransaction(pConv, pXAct); } else + { + /* transaction should be removed from the queue before handling */ + WDML_UnQueueTransaction(pConv, pXAct); WDML_ServerHandle(pConv, pXAct); + } WDML_FreeTransaction(pConv->instance, pXAct, TRUE); @@ -1885,10 +1900,42 @@ BOOL WINAPI DdeEnableCallback(DWORD idInst, HCONV hConv, UINT wCmd) TRACE("(%d, %p, %04x)\n", idInst, hConv, wCmd); - pConv = WDML_GetConv(hConv, TRUE); + if (hConv) + { + pConv = WDML_GetConv(hConv, TRUE); - if (pConv && pConv->instance->instanceID == idInst) - ret = WDML_EnableCallback(pConv, wCmd); + if (pConv && pConv->instance->instanceID == idInst) + ret = WDML_EnableCallback(pConv, wCmd); + } + else + { + WDML_INSTANCE *pInstance = WDML_GetInstance(idInst); + + if (!pInstance) + return FALSE; + + TRACE("adding flags %04x to instance %p\n", wCmd, pInstance); + pInstance->wStatus |= wCmd; + + if (wCmd == EC_DISABLE) + { + pInstance->wStatus |= ST_BLOCKED; + TRACE("EC_DISABLE: inst %p status flags %04x\n", pInstance, pInstance->wStatus); + } + else if (wCmd == EC_ENABLEALL) + { + pInstance->wStatus &= ~ST_BLOCKED; + TRACE("EC_ENABLEALL: inst %p status flags %04x\n", pInstance, pInstance->wStatus); + } + + ret = TRUE; + + for (pConv = pInstance->convs[WDML_CLIENT_SIDE]; pConv != NULL; pConv = pConv->next) + { + ret = WDML_EnableCallback(pConv, wCmd); + if (ret && wCmd == EC_QUERYWAITING) break; + } + } return ret; } diff --git a/dlls/user32/dde_private.h b/dlls/user32/dde_private.h index f784938d2ff..00882e4987e 100644 --- a/dlls/user32/dde_private.h +++ b/dlls/user32/dde_private.h @@ -164,6 +164,7 @@ typedef struct tagWDML_INSTANCE DWORD monitorFlags; DWORD lastError; HWND hwndEvent; + DWORD wStatus; /* global instance status */ WDML_SERVER* servers; /* list of registered servers */ WDML_CONV* convs[2]; /* active conversations for this instance (client and server) */ WDML_LINK* links[2]; /* active links for this instance (client and server) */ @@ -196,6 +197,8 @@ extern void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hsz extern WDML_SERVER* WDML_FindServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic); /* transaction handler on the server side */ extern WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV* pConv, WDML_XACT* pXAct); +/* transaction handler on the client side */ +HDDEDATA WDML_ClientHandle(WDML_CONV *pConv, WDML_XACT *pXAct, DWORD dwTimeout, LPDWORD pdwResult); /* called both in DdeClientTransaction and server side. */ extern UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes, BOOL bUnicode, BOOL b16); diff --git a/dlls/user32/dde_server.c b/dlls/user32/dde_server.c index 545b80e2e81..2789450e37c 100644 --- a/dlls/user32/dde_server.c +++ b/dlls/user32/dde_server.c @@ -1051,13 +1051,16 @@ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM w default: FIXME("Unsupported message %x\n", iMsg); + break; } if (pXAct) { pXAct->lParam = lParam; - if (WDML_ServerHandle(pConv, pXAct) == WDML_QS_BLOCK) + + if ((pConv->wStatus & ST_BLOCKED) || WDML_ServerHandle(pConv, pXAct) == WDML_QS_BLOCK) { + TRACE("Transactions are blocked, add to the queue and exit\n"); WDML_QueueTransaction(pConv, pXAct); } else @@ -1065,6 +1068,8 @@ static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM w WDML_FreeTransaction(pInstance, pXAct, TRUE); } } + else + pConv->instance->lastError = DMLERR_MEMORY_ERROR; return 0; }