user32: Add support for DdeEnableCallback(EC_DISABLE) command

Dmitry Timoshkov dmitry at codeweavers.com
Tue Nov 21 00:43:48 CST 2006


Hello,

this is almost an year-old patch updated for the current tree.

Changelog:
    user32: Add support for DdeEnableCallback(EC_DISABLE) command.

---
 dlls/user32/dde_client.c  |   70 ++++++++++++++++++++++++++++++---------------
 dlls/user32/dde_misc.c    |   61 +++++++++++++++++++++++++++++++++++----
 dlls/user32/dde_private.h |    3 ++
 dlls/user32/dde_server.c  |    7 ++++-
 4 files changed, 109 insertions(+), 32 deletions(-)

diff --git a/dlls/user32/dde_client.c b/dlls/user32/dde_client.c
index 2d345f0..1441e71 100644
--- a/dlls/user32/dde_client.c
+++ b/dlls/user32/dde_client.c
@@ -792,7 +792,7 @@ static WDML_XACT*	WDML_ClientQueueTermin
  *
  * 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_HandleTermi
 }
 
 /******************************************************************
- *		WDML_HandleReplyData
+ *		WDML_HandleIncomingData
  *
  *
  */
@@ -934,7 +934,7 @@ static WDML_QUEUE_STATE WDML_HandleReply
 	    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
 	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
 	{
 	    *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_SyncWaitTransaction
     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(LPB
 
     WDML_QueueTransaction(pConv, pXAct);
 
-    if (!PostMessageW(pConv->hwndServer, pXAct->ddeMsg, (WPARAM)pConv->hwndClient, pXAct->lParam))
+    TRACE("pConv->wStatus %04x\n", pConv->wStatus);
+
+    if (pConv->wStatus & ST_BLOCKED)
     {
-	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;
+        TRACE("Transactions are blocked, add to the queue and exit\n");
+        return (HDDEDATA)1;
     }
-    pXAct->dwTimeout = dwTimeout;
-    /* FIXME: should set the app bits on *pdwResult */
 
-    if (dwTimeout == TIMEOUT_ASYNC)
+    hDdeData = WDML_ClientHandle(pConv, pXAct, dwTimeout, pdwResult);
+    if (dwTimeout != TIMEOUT_ASYNC)
     {
-	if (pdwResult)
-	{
-	    *pdwResult = MAKELONG(0, pXAct->xActID);
-	}
-	hDdeData = (HDDEDATA)1;
+        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 0afb2ed..bcb4cea 100644
--- a/dlls/user32/dde_misc.c
+++ b/dlls/user32/dde_misc.c
@@ -382,6 +382,7 @@ UINT WDML_Initialize(LPDWORD pidInst, PF
     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* p
     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* p
     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_CON
 {
     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_CON
         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 idIn
 
     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);
+    }
+    else
+    {
+        WDML_INSTANCE *pInstance = WDML_GetInstance(idInst);
 
-    if (pConv && pConv->instance->instanceID == idInst)
-        ret = WDML_EnableCallback(pConv, wCmd);
+        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 f784938..00882e4 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_INST
 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 545b80e..2789450 100644
--- a/dlls/user32/dde_server.c
+++ b/dlls/user32/dde_server.c
@@ -1051,13 +1051,16 @@ static LRESULT CALLBACK WDML_ServerConvP
 
     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_ServerConvP
 	    WDML_FreeTransaction(pInstance, pXAct, TRUE);
 	}
     }
+    else
+        pConv->instance->lastError = DMLERR_MEMORY_ERROR;
 
     return 0;
 }
-- 
1.4.2






More information about the wine-patches mailing list