| /* | 
 |  * DDEML library | 
 |  * | 
 |  * Copyright 1997 Alexandre Julliard | 
 |  * Copyright 1997 Len White | 
 |  * Copyright 1999 Keith Matthews | 
 |  * Copyright 2000 Corel | 
 |  * Copyright 2001 Eric Pouech | 
 |  * Copyright 2003, 2004, 2005 Dmitry Timoshkov | 
 |  * | 
 |  * This library is free software; you can redistribute it and/or | 
 |  * modify it under the terms of the GNU Lesser General Public | 
 |  * License as published by the Free Software Foundation; either | 
 |  * version 2.1 of the License, or (at your option) any later version. | 
 |  * | 
 |  * This library is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
 |  * Lesser General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU Lesser General Public | 
 |  * License along with this library; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
 |  */ | 
 |  | 
 | #include <stdarg.h> | 
 | #include <string.h> | 
 | #include "windef.h" | 
 | #include "winbase.h" | 
 | #include "wingdi.h" | 
 | #include "winuser.h" | 
 | #include "dde.h" | 
 | #include "ddeml.h" | 
 | #include "win.h" | 
 | #include "wine/debug.h" | 
 | #include "dde_private.h" | 
 |  | 
 | WINE_DEFAULT_DEBUG_CHANNEL(ddeml); | 
 |  | 
 | static const WCHAR szServerNameClass[] = {'W','i','n','e','D','d','e','S','e','r','v','e','r','N','a','m','e',0}; | 
 | const char WDML_szServerConvClassA[] = "WineDdeServerConvA"; | 
 | const WCHAR WDML_szServerConvClassW[] = {'W','i','n','e','D','d','e','S','e','r','v','e','r','C','o','n','v','W',0}; | 
 |  | 
 | static LRESULT CALLBACK WDML_ServerNameProc(HWND, UINT, WPARAM, LPARAM); | 
 | static LRESULT CALLBACK WDML_ServerConvProc(HWND, UINT, WPARAM, LPARAM); | 
 |  | 
 | /****************************************************************************** | 
 |  * DdePostAdvise [USER32.@]  Send transaction to DDE callback function. | 
 |  * | 
 |  * PARAMS | 
 |  *	idInst	  [I] Instance identifier | 
 |  *	hszTopic  [I] Handle to topic name string | 
 |  *	hszItem	  [I] Handle to item name string | 
 |  * | 
 |  * RETURNS | 
 |  *    Success: TRUE | 
 |  *    Failure: FALSE | 
 |  */ | 
 | BOOL WINAPI DdePostAdvise(DWORD idInst, HSZ hszTopic, HSZ hszItem) | 
 | { | 
 |     WDML_INSTANCE*	pInstance = NULL; | 
 |     WDML_LINK*		pLink = NULL; | 
 |     HDDEDATA		hDdeData = 0; | 
 |     HGLOBAL             hItemData = 0; | 
 |     WDML_CONV*		pConv = NULL; | 
 |     ATOM		atom = 0; | 
 |     UINT		count; | 
 |  | 
 |     TRACE("(%d,%p,%p)\n", idInst, hszTopic, hszItem); | 
 |  | 
 |     pInstance = WDML_GetInstance(idInst); | 
 |  | 
 |     if (pInstance == NULL || pInstance->links == NULL) | 
 |         return FALSE; | 
 |  | 
 |     atom = WDML_MakeAtomFromHsz(hszItem); | 
 |     if (!atom) return FALSE; | 
 |  | 
 |     /* first compute the number of links which will trigger a message */ | 
 |     count = 0; | 
 |     for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) | 
 |     { | 
 | 	if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) | 
 | 	{ | 
 | 	    count++; | 
 | 	} | 
 |     } | 
 |     if (count >= CADV_LATEACK) | 
 |     { | 
 | 	FIXME("too high value for count\n"); | 
 | 	count &= 0xFFFF; | 
 |     } | 
 |  | 
 |     for (pLink = pInstance->links[WDML_SERVER_SIDE]; pLink != NULL; pLink = pLink->next) | 
 |     { | 
 | 	if (DdeCmpStringHandles(hszItem, pLink->hszItem) == 0) | 
 | 	{ | 
 | 	    hDdeData = WDML_InvokeCallback(pInstance, XTYP_ADVREQ, pLink->uFmt, pLink->hConv, | 
 | 					   hszTopic, hszItem, 0, --count, 0); | 
 |  | 
 | 	    if (hDdeData == (HDDEDATA)CBR_BLOCK) | 
 | 	    { | 
 | 		/* MS doc is not consistent here */ | 
 | 		FIXME("CBR_BLOCK returned for ADVREQ\n"); | 
 | 		continue; | 
 | 	    } | 
 | 	    if (hDdeData) | 
 | 	    { | 
 | 		if (pLink->transactionType & XTYPF_NODATA) | 
 | 		{ | 
 | 		    TRACE("no data\n"); | 
 | 		    hItemData = 0; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 		    TRACE("with data\n"); | 
 |  | 
 | 		    hItemData = WDML_DataHandle2Global(hDdeData, FALSE, FALSE, FALSE, FALSE); | 
 | 		} | 
 |  | 
 | 		pConv = WDML_GetConv(pLink->hConv, TRUE); | 
 |  | 
 | 		if (pConv == NULL) | 
 | 		{ | 
 | 		    if (!WDML_IsAppOwned(hDdeData))  DdeFreeDataHandle(hDdeData); | 
 | 		    goto theError; | 
 | 		} | 
 |  | 
 | 		if (!PostMessageW(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, | 
 | 				  PackDDElParam(WM_DDE_DATA, (UINT_PTR)hItemData, atom))) | 
 | 		{ | 
 | 		    ERR("post message failed\n"); | 
 |                     pConv->wStatus &= ~ST_CONNECTED; | 
 |                     pConv->instance->lastError = DMLERR_POSTMSG_FAILED; | 
 | 		    if (!WDML_IsAppOwned(hDdeData))  DdeFreeDataHandle(hDdeData); | 
 | 		    GlobalFree(hItemData); | 
 | 		    goto theError; | 
 | 		} | 
 |                 if (!WDML_IsAppOwned(hDdeData))  DdeFreeDataHandle(hDdeData); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |     return TRUE; | 
 |  | 
 |  theError: | 
 |     if (atom) GlobalDeleteAtom(atom); | 
 |     return FALSE; | 
 | } | 
 |  | 
 |  | 
 | /****************************************************************************** | 
 |  * DdeNameService [USER32.@]  {Un}registers service name of DDE server | 
 |  * | 
 |  * PARAMS | 
 |  *    idInst [I] Instance identifier | 
 |  *    hsz1   [I] Handle to service name string | 
 |  *    hsz2   [I] Reserved | 
 |  *    afCmd  [I] Service name flags | 
 |  * | 
 |  * RETURNS | 
 |  *    Success: Non-zero | 
 |  *    Failure: 0 | 
 |  */ | 
 | HDDEDATA WINAPI DdeNameService(DWORD idInst, HSZ hsz1, HSZ hsz2, UINT afCmd) | 
 | { | 
 |     WDML_SERVER*	pServer; | 
 |     WDML_INSTANCE*	pInstance; | 
 |     HDDEDATA 		hDdeData; | 
 |     HWND 		hwndServer; | 
 |     WNDCLASSEXW  	wndclass; | 
 |  | 
 |     hDdeData = NULL; | 
 |  | 
 |     TRACE("(%d,%p,%p,%x)\n", idInst, hsz1, hsz2, afCmd); | 
 |  | 
 |     /*  First check instance | 
 |      */ | 
 |     pInstance = WDML_GetInstance(idInst); | 
 |     if  (pInstance == NULL) | 
 |     { | 
 | 	TRACE("Instance not found as initialised\n"); | 
 | 	/*  Nothing has been initialised - exit now ! can return TRUE since effect is the same */ | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     if (hsz2 != 0L) | 
 |     { | 
 | 	/*	Illegal, reserved parameter | 
 | 	 */ | 
 | 	pInstance->lastError = DMLERR_INVALIDPARAMETER; | 
 | 	WARN("Reserved parameter no-zero !!\n"); | 
 |         return NULL; | 
 |     } | 
 |     if (hsz1 == 0 && !(afCmd & DNS_UNREGISTER)) | 
 |     { | 
 | 	/*	don't know if we should check this but it makes sense | 
 | 	 *	why supply REGISTER or filter flags if de-registering all | 
 | 	 */ | 
 | 	TRACE("General unregister unexpected flags\n"); | 
 | 	pInstance->lastError = DMLERR_INVALIDPARAMETER; | 
 |         return NULL; | 
 |     } | 
 |  | 
 |     switch (afCmd & (DNS_REGISTER | DNS_UNREGISTER)) | 
 |     { | 
 |     case DNS_REGISTER: | 
 | 	pServer = WDML_FindServer(pInstance, hsz1, 0); | 
 | 	if (pServer) | 
 | 	{ | 
 | 	    ERR("Trying to register already registered service!\n"); | 
 | 	    pInstance->lastError = DMLERR_DLL_USAGE; | 
 |             return NULL; | 
 | 	} | 
 |  | 
 | 	TRACE("Adding service name\n"); | 
 |  | 
 | 	WDML_IncHSZ(pInstance, hsz1); | 
 |  | 
 | 	pServer = WDML_AddServer(pInstance, hsz1, 0); | 
 |  | 
 | 	WDML_BroadcastDDEWindows(WDML_szEventClass, WM_WDML_REGISTER, | 
 | 				 pServer->atomService, pServer->atomServiceSpec); | 
 |  | 
 | 	wndclass.cbSize        = sizeof(wndclass); | 
 | 	wndclass.style         = 0; | 
 | 	wndclass.lpfnWndProc   = WDML_ServerNameProc; | 
 | 	wndclass.cbClsExtra    = 0; | 
 | 	wndclass.cbWndExtra    = 2 * sizeof(ULONG_PTR); | 
 | 	wndclass.hInstance     = 0; | 
 | 	wndclass.hIcon         = 0; | 
 | 	wndclass.hCursor       = 0; | 
 | 	wndclass.hbrBackground = 0; | 
 | 	wndclass.lpszMenuName  = NULL; | 
 | 	wndclass.lpszClassName = szServerNameClass; | 
 | 	wndclass.hIconSm       = 0; | 
 |  | 
 | 	RegisterClassExW(&wndclass); | 
 |  | 
 | 	hwndServer = CreateWindowW(szServerNameClass, NULL, | 
 | 				   WS_POPUP, 0, 0, 0, 0, | 
 | 				   0, 0, 0, 0); | 
 |  | 
 | 	SetWindowLongPtrW(hwndServer, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance); | 
 | 	SetWindowLongPtrW(hwndServer, GWL_WDML_SERVER, (ULONG_PTR)pServer); | 
 | 	TRACE("Created nameServer=%p for instance=%08x\n", hwndServer, idInst); | 
 |  | 
 | 	pServer->hwndServer = hwndServer; | 
 | 	break; | 
 |  | 
 |     case DNS_UNREGISTER: | 
 | 	if (hsz1 == 0L) | 
 | 	{ | 
 | 	    /* General unregister situation | 
 | 	     * terminate all server side pending conversations | 
 | 	     */ | 
 | 	    while (pInstance->servers) | 
 | 		WDML_RemoveServer(pInstance, pInstance->servers->hszService, 0); | 
 | 	    pInstance->servers = NULL; | 
 | 	    TRACE("General de-register - finished\n"); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    WDML_RemoveServer(pInstance, hsz1, 0L); | 
 | 	} | 
 | 	break; | 
 |     } | 
 |  | 
 |     if (afCmd & (DNS_FILTERON | DNS_FILTEROFF)) | 
 |     { | 
 | 	/*	Set filter flags on to hold notifications of connection | 
 | 	 */ | 
 | 	pServer = WDML_FindServer(pInstance, hsz1, 0); | 
 | 	if (!pServer) | 
 | 	{ | 
 | 	    /*  trying to filter where no service names !! | 
 | 	     */ | 
 | 	    pInstance->lastError = DMLERR_DLL_USAGE; | 
 |             return NULL; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    pServer->filterOn = (afCmd & DNS_FILTERON) != 0; | 
 | 	} | 
 |     } | 
 |     return (HDDEDATA)TRUE; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_CreateServerConv | 
 |  * | 
 |  * | 
 |  */ | 
 | static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClient, | 
 | 					HWND hwndServerName, HSZ hszApp, HSZ hszTopic) | 
 | { | 
 |     HWND	hwndServerConv; | 
 |     WDML_CONV*	pConv; | 
 |  | 
 |     if (pInstance->unicode) | 
 |     { | 
 |         WNDCLASSEXW wndclass; | 
 |  | 
 |         wndclass.cbSize        = sizeof(wndclass); | 
 |         wndclass.style         = 0; | 
 |         wndclass.lpfnWndProc   = WDML_ServerConvProc; | 
 |         wndclass.cbClsExtra    = 0; | 
 |         wndclass.cbWndExtra    = 2 * sizeof(ULONG_PTR); | 
 |         wndclass.hInstance     = 0; | 
 |         wndclass.hIcon         = 0; | 
 |         wndclass.hCursor       = 0; | 
 |         wndclass.hbrBackground = 0; | 
 |         wndclass.lpszMenuName  = NULL; | 
 |         wndclass.lpszClassName = WDML_szServerConvClassW; | 
 |         wndclass.hIconSm       = 0; | 
 |  | 
 |         RegisterClassExW(&wndclass); | 
 |  | 
 |         hwndServerConv = CreateWindowW(WDML_szServerConvClassW, 0, | 
 | 				       WS_CHILD, 0, 0, 0, 0, | 
 | 				       hwndServerName, 0, 0, 0); | 
 |     } | 
 |     else | 
 |     { | 
 |         WNDCLASSEXA wndclass; | 
 |  | 
 |         wndclass.cbSize        = sizeof(wndclass); | 
 |         wndclass.style         = 0; | 
 |         wndclass.lpfnWndProc   = WDML_ServerConvProc; | 
 |         wndclass.cbClsExtra    = 0; | 
 |         wndclass.cbWndExtra    = 2 * sizeof(ULONG_PTR); | 
 |         wndclass.hInstance     = 0; | 
 |         wndclass.hIcon         = 0; | 
 |         wndclass.hCursor       = 0; | 
 |         wndclass.hbrBackground = 0; | 
 |         wndclass.lpszMenuName  = NULL; | 
 |         wndclass.lpszClassName = WDML_szServerConvClassA; | 
 |         wndclass.hIconSm       = 0; | 
 |  | 
 |         RegisterClassExA(&wndclass); | 
 |  | 
 |         hwndServerConv = CreateWindowA(WDML_szServerConvClassA, 0, | 
 |                                       WS_CHILD, 0, 0, 0, 0, | 
 |                                       hwndServerName, 0, 0, 0); | 
 |     } | 
 |  | 
 |     TRACE("Created convServer=%p (nameServer=%p) for instance=%08x\n", | 
 | 	  hwndServerConv, hwndServerName, pInstance->instanceID); | 
 |  | 
 |     pConv = WDML_AddConv(pInstance, WDML_SERVER_SIDE, hszApp, hszTopic, | 
 | 			 hwndClient, hwndServerConv); | 
 |     if (pConv) | 
 |     { | 
 | 	SetWindowLongPtrW(hwndServerConv, GWL_WDML_INSTANCE, (ULONG_PTR)pInstance); | 
 | 	SetWindowLongPtrW(hwndServerConv, GWL_WDML_CONVERSATION, (ULONG_PTR)pConv); | 
 |  | 
 | 	/* this should be the only place using SendMessage for WM_DDE_ACK */ | 
 |         /* note: sent messages shall not use packing */ | 
 | 	SendMessageW(hwndClient, WM_DDE_ACK, (WPARAM)hwndServerConv, | 
 | 		     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... | 
 | 	 */ | 
 | 	pConv->wStatus |= ST_CONNECTED; | 
 |     } | 
 |     else | 
 |     { | 
 | 	DestroyWindow(hwndServerConv); | 
 |     } | 
 |     return pConv; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerNameProc | 
 |  * | 
 |  * | 
 |  */ | 
 | static LRESULT CALLBACK WDML_ServerNameProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |     HWND		hwndClient; | 
 |     HSZ			hszApp, hszTop; | 
 |     HDDEDATA		hDdeData = 0; | 
 |     WDML_INSTANCE*	pInstance; | 
 |     UINT_PTR		uiLo, uiHi; | 
 |  | 
 |     switch (iMsg) | 
 |     { | 
 |     case WM_DDE_INITIATE: | 
 |  | 
 | 	/* wParam         -- sending window handle | 
 | 	   LOWORD(lParam) -- application atom | 
 | 	   HIWORD(lParam) -- topic atom */ | 
 |  | 
 | 	TRACE("WM_DDE_INITIATE message received!\n"); | 
 | 	hwndClient = (HWND)wParam; | 
 |  | 
 | 	pInstance = WDML_GetInstanceFromWnd(hwndServer); | 
 | 	TRACE("idInst=%d, threadID=0x%x\n", pInstance->instanceID, GetCurrentThreadId()); | 
 | 	if (!pInstance) return 0; | 
 |  | 
 | 	/* don't free DDEParams, since this is a broadcast */ | 
 | 	UnpackDDElParam(WM_DDE_INITIATE, lParam, &uiLo, &uiHi); | 
 |  | 
 | 	hszApp = WDML_MakeHszFromAtom(pInstance, uiLo); | 
 | 	hszTop = WDML_MakeHszFromAtom(pInstance, uiHi); | 
 |  | 
 | 	if (!(pInstance->CBFflags & CBF_FAIL_CONNECTIONS)) | 
 | 	{ | 
 | 	    BOOL 		self = FALSE; | 
 | 	    CONVCONTEXT		cc; | 
 | 	    CONVCONTEXT*	pcc = NULL; | 
 | 	    WDML_CONV*		pConv; | 
 | 	    char		buf[256]; | 
 |  | 
 | 	    if (GetWindowThreadProcessId(hwndClient, NULL) == GetWindowThreadProcessId(hwndServer, NULL) && | 
 | 		WDML_GetInstanceFromWnd(hwndClient) == WDML_GetInstanceFromWnd(hwndServer)) | 
 | 	    { | 
 | 		self = TRUE; | 
 | 	    } | 
 | 	    /* FIXME: so far, we don't grab distant convcontext, so only check if remote is | 
 | 	     * handled under DDEML, and if so build a default context | 
 | 	     */ | 
 |            if ((GetClassNameA(hwndClient, buf, sizeof(buf)) && | 
 |                 lstrcmpiA(buf, WDML_szClientConvClassA) == 0) || | 
 |                (GetClassNameW(hwndClient, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) && | 
 |                 lstrcmpiW((LPWSTR)buf, WDML_szClientConvClassW) == 0)) | 
 | 	    { | 
 | 		pcc = &cc; | 
 | 		memset(pcc, 0, sizeof(*pcc)); | 
 | 		pcc->cb = sizeof(*pcc); | 
 | 		pcc->iCodePage = IsWindowUnicode(hwndClient) ? CP_WINUNICODE : CP_WINANSI; | 
 | 	    } | 
 | 	    if ((pInstance->CBFflags & CBF_FAIL_SELFCONNECTIONS) && self) | 
 | 	    { | 
 | 		TRACE("Don't do self connection as requested\n"); | 
 | 	    } | 
 | 	    else if (hszApp && hszTop) | 
 | 	    { | 
 | 		WDML_SERVER*	pServer = (WDML_SERVER*)GetWindowLongPtrW(hwndServer, GWL_WDML_SERVER); | 
 |  | 
 | 		/* check filters for name service */ | 
 | 		if (!pServer->filterOn || DdeCmpStringHandles(pServer->hszService, hszApp) == 0) | 
 | 		{ | 
 | 		    /* pass on to the callback  */ | 
 | 		    hDdeData = WDML_InvokeCallback(pInstance, XTYP_CONNECT, | 
 | 						   0, 0, hszTop, hszApp, 0, (ULONG_PTR)pcc, self); | 
 | 		    if ((ULONG_PTR)hDdeData) | 
 | 		    { | 
 | 			pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, | 
 | 						      hszApp, hszTop); | 
 |                         if (pConv) | 
 |                         { | 
 |                             if (pcc) pConv->wStatus |= ST_ISLOCAL; | 
 |                             WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv, | 
 |                                                 hszTop, hszApp, 0, (ULONG_PTR)pcc, self); | 
 |                         } | 
 | 		    } | 
 | 		} | 
 | 	    } | 
 | 	    else if (pInstance->servers) | 
 | 	    { | 
 | 		/* pass on to the callback  */ | 
 | 		hDdeData = WDML_InvokeCallback(pInstance, XTYP_WILDCONNECT, | 
 | 					       0, 0, hszTop, hszApp, 0, (ULONG_PTR)pcc, self); | 
 |  | 
 | 		if (hDdeData == (HDDEDATA)CBR_BLOCK) | 
 | 		{ | 
 | 		    /* MS doc is not consistent here */ | 
 | 		    FIXME("CBR_BLOCK returned for WILDCONNECT\n"); | 
 | 		} | 
 | 		else if ((ULONG_PTR)hDdeData != 0) | 
 | 		{ | 
 | 		    HSZPAIR*	hszp; | 
 |  | 
 | 		    hszp = (HSZPAIR*)DdeAccessData(hDdeData, NULL); | 
 | 		    if (hszp) | 
 | 		    { | 
 | 			int	i; | 
 | 			for (i = 0; hszp[i].hszSvc && hszp[i].hszTopic; i++) | 
 | 			{ | 
 | 			    pConv = WDML_CreateServerConv(pInstance, hwndClient, hwndServer, | 
 | 							  hszp[i].hszSvc, hszp[i].hszTopic); | 
 |                             if (pConv) | 
 |                             { | 
 |                                 if (pcc) pConv->wStatus |= ST_ISLOCAL; | 
 |                                 WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv, | 
 |                                                     hszp[i].hszTopic, hszp[i].hszSvc, 0, (ULONG_PTR)pcc, self); | 
 |                             } | 
 | 			} | 
 | 			DdeUnaccessData(hDdeData); | 
 | 		    } | 
 |                     if (!WDML_IsAppOwned(hDdeData)) DdeFreeDataHandle(hDdeData); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |  | 
 | 	return 0; | 
 |  | 
 |     case WM_DDE_REQUEST: | 
 | 	FIXME("WM_DDE_REQUEST message received!\n"); | 
 | 	return 0; | 
 |     case WM_DDE_ADVISE: | 
 | 	FIXME("WM_DDE_ADVISE message received!\n"); | 
 | 	return 0; | 
 |     case WM_DDE_UNADVISE: | 
 | 	FIXME("WM_DDE_UNADVISE message received!\n"); | 
 | 	return 0; | 
 |     case WM_DDE_EXECUTE: | 
 | 	FIXME("WM_DDE_EXECUTE message received!\n"); | 
 | 	return 0; | 
 |     case WM_DDE_POKE: | 
 | 	FIXME("WM_DDE_POKE message received!\n"); | 
 | 	return 0; | 
 |     case WM_DDE_TERMINATE: | 
 | 	FIXME("WM_DDE_TERMINATE message received!\n"); | 
 | 	return 0; | 
 |     default: | 
 | 	break; | 
 |     } | 
 |  | 
 |     return DefWindowProcW(hwndServer, iMsg, wParam, lParam); | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerQueueRequest | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT*	WDML_ServerQueueRequest(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     UINT_PTR		uiLo, uiHi; | 
 |     WDML_XACT*		pXAct; | 
 |  | 
 |     UnpackDDElParam(WM_DDE_REQUEST, lParam, &uiLo, &uiHi); | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_REQUEST, | 
 | 				  uiLo, WDML_MakeHszFromAtom(pConv->instance, uiHi)); | 
 |     if (pXAct) pXAct->atom = uiHi; | 
 |     return pXAct; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandleRequest | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandleRequest(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     HDDEDATA		hDdeData = 0; | 
 |     BOOL		fAck = TRUE; | 
 |  | 
 |     if (!(pConv->instance->CBFflags & CBF_FAIL_REQUESTS)) | 
 |     { | 
 |  | 
 | 	hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_REQUEST, pXAct->wFmt, (HCONV)pConv, | 
 | 				       pConv->hszTopic, pXAct->hszItem, 0, 0, 0); | 
 |     } | 
 |  | 
 |     switch ((ULONG_PTR)hDdeData) | 
 |     { | 
 |     case 0: | 
 | 	TRACE("No data returned from the Callback\n"); | 
 | 	fAck = FALSE; | 
 | 	break; | 
 |  | 
 |     case (ULONG_PTR)CBR_BLOCK: | 
 | 	return WDML_QS_BLOCK; | 
 |  | 
 |     default: | 
 |         { | 
 | 	    HGLOBAL	hMem = WDML_DataHandle2Global(hDdeData, TRUE, FALSE, FALSE, FALSE); | 
 | 	    if (!PostMessageW(pConv->hwndClient, WM_DDE_DATA, (WPARAM)pConv->hwndServer, | 
 | 			      ReuseDDElParam(pXAct->lParam, WM_DDE_REQUEST, WM_DDE_DATA, | 
 | 					     (UINT_PTR)hMem, (UINT_PTR)pXAct->atom))) | 
 | 	    { | 
 |                 pConv->instance->lastError = DMLERR_POSTMSG_FAILED; | 
 | 		DdeFreeDataHandle(hDdeData); | 
 | 		GlobalFree(hMem); | 
 | 		fAck = FALSE; | 
 | 	    } | 
 | 	} | 
 | 	break; | 
 |     } | 
 |  | 
 |     WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, fAck, pXAct->atom, pXAct->lParam, WM_DDE_REQUEST); | 
 |  | 
 |     WDML_DecHSZ(pConv->instance, pXAct->hszItem); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerQueueAdvise | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT*	WDML_ServerQueueAdvise(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     UINT_PTR		uiLo, uiHi; | 
 |     WDML_XACT*		pXAct; | 
 |  | 
 |     /* XTYP_ADVSTART transaction: | 
 |        establish link and save link info to InstanceInfoTable */ | 
 |  | 
 |     if (!UnpackDDElParam(WM_DDE_ADVISE, lParam, &uiLo, &uiHi)) | 
 | 	return NULL; | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_ADVISE, | 
 | 				  0, WDML_MakeHszFromAtom(pConv->instance, uiHi)); | 
 |     if (pXAct) | 
 |     { | 
 | 	pXAct->hMem = (HGLOBAL)uiLo; | 
 | 	pXAct->atom = uiHi; | 
 |     } | 
 |     return pXAct; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandleAdvise | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandleAdvise(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     UINT		uType; | 
 |     WDML_LINK*		pLink; | 
 |     DDEADVISE*		pDdeAdvise; | 
 |     HDDEDATA		hDdeData = 0; | 
 |     BOOL		fAck = TRUE; | 
 |  | 
 |     pDdeAdvise = (DDEADVISE*)GlobalLock(pXAct->hMem); | 
 |     uType = XTYP_ADVSTART | | 
 | 	    (pDdeAdvise->fDeferUpd ? XTYPF_NODATA : 0) | | 
 | 	    (pDdeAdvise->fAckReq ? XTYPF_ACKREQ : 0); | 
 |  | 
 |     if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) | 
 |     { | 
 | 	hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_ADVSTART, pDdeAdvise->cfFormat, | 
 | 				       (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, 0, 0, 0); | 
 |     } | 
 |  | 
 |     switch ((ULONG_PTR)hDdeData) | 
 |     { | 
 |     case 0: | 
 | 	TRACE("No data returned from the Callback\n"); | 
 | 	fAck = FALSE; | 
 | 	break; | 
 |  | 
 |     case (ULONG_PTR)CBR_BLOCK: | 
 | 	return WDML_QS_BLOCK; | 
 |  | 
 |     default: | 
 | 	/* billx: first to see if the link is already created. */ | 
 | 	pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, | 
 | 			      pXAct->hszItem, TRUE, pDdeAdvise->cfFormat); | 
 |  | 
 | 	if (pLink != NULL) | 
 | 	{ | 
 | 	    /* we found a link, and only need to modify it in case it changes */ | 
 | 	    pLink->transactionType = uType; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 	    TRACE("Adding Link with hConv %p\n", pConv); | 
 | 	    WDML_AddLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, | 
 | 			 uType, pXAct->hszItem, pDdeAdvise->cfFormat); | 
 | 	} | 
 | 	break; | 
 |     } | 
 |  | 
 |     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); | 
 |  | 
 |     WDML_DecHSZ(pConv->instance, pXAct->hszItem); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerQueueUnadvise | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT* WDML_ServerQueueUnadvise(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     UINT_PTR		uiLo, uiHi; | 
 |     WDML_XACT*		pXAct; | 
 |  | 
 |     UnpackDDElParam(WM_DDE_UNADVISE, lParam, &uiLo, &uiHi); | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_UNADVISE, | 
 | 				  uiLo, WDML_MakeHszFromAtom(pConv->instance, uiHi)); | 
 |     if (pXAct) pXAct->atom = uiHi; | 
 |     return pXAct; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandleUnadvise | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandleUnadvise(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     WDML_LINK*	pLink; | 
 |  | 
 |     if (pXAct->hszItem == NULL || pXAct->wFmt == 0) | 
 |     { | 
 | 	ERR("Unsupported yet options (null item or clipboard format)\n"); | 
 | 	return WDML_QS_ERROR; | 
 |     } | 
 |  | 
 |     pLink = WDML_FindLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, | 
 | 			  pXAct->hszItem, TRUE, pXAct->wFmt); | 
 |     if (pLink == NULL) | 
 |     { | 
 | 	ERR("Couln'd find link for %p, dropping request\n", pXAct->hszItem); | 
 | 	FreeDDElParam(WM_DDE_UNADVISE, pXAct->lParam); | 
 | 	return WDML_QS_ERROR; | 
 |     } | 
 |  | 
 |     if (!(pConv->instance->CBFflags & CBF_FAIL_ADVISES)) | 
 |     { | 
 | 	WDML_InvokeCallback(pConv->instance, XTYP_ADVSTOP, pXAct->wFmt, (HCONV)pConv, | 
 | 			    pConv->hszTopic, pXAct->hszItem, 0, 0, 0); | 
 |     } | 
 |  | 
 |     WDML_RemoveLink(pConv->instance, (HCONV)pConv, WDML_SERVER_SIDE, | 
 | 		    pXAct->hszItem, pXAct->wFmt); | 
 |  | 
 |     /* send back ack */ | 
 |     WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, FALSE, TRUE, pXAct->atom, | 
 |                  pXAct->lParam, WM_DDE_UNADVISE); | 
 |  | 
 |     WDML_DecHSZ(pConv->instance, pXAct->hszItem); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_QueueExecute | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT* WDML_ServerQueueExecute(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     WDML_XACT*	pXAct; | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_EXECUTE, 0, 0); | 
 |     if (pXAct) | 
 |     { | 
 | 	pXAct->hMem    = (HGLOBAL)lParam; | 
 |     } | 
 |     return pXAct; | 
 | } | 
 |  | 
 |  /****************************************************************** | 
 |  *		WDML_ServerHandleExecute | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandleExecute(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     HDDEDATA	hDdeData = DDE_FNOTPROCESSED; | 
 |     BOOL	fAck = FALSE, fBusy = FALSE; | 
 |  | 
 |     if (!(pConv->instance->CBFflags & CBF_FAIL_EXECUTES)) | 
 |     { | 
 | 	LPVOID	ptr = GlobalLock(pXAct->hMem); | 
 |  | 
 | 	if (ptr) | 
 | 	{ | 
 | 	    hDdeData = DdeCreateDataHandle(0, ptr, GlobalSize(pXAct->hMem), | 
 | 					   0, 0, CF_TEXT, 0); | 
 | 	    GlobalUnlock(pXAct->hMem); | 
 | 	} | 
 | 	hDdeData = WDML_InvokeCallback(pConv->instance, XTYP_EXECUTE, 0, (HCONV)pConv, | 
 | 				       pConv->hszTopic, 0, hDdeData, 0L, 0L); | 
 |     } | 
 |  | 
 |     switch ((ULONG_PTR)hDdeData) | 
 |     { | 
 |     case (ULONG_PTR)CBR_BLOCK: | 
 | 	return WDML_QS_BLOCK; | 
 |  | 
 |     case DDE_FACK: | 
 | 	fAck = TRUE; | 
 | 	break; | 
 |     case DDE_FBUSY: | 
 | 	fBusy = TRUE; | 
 | 	break; | 
 |     default: | 
 | 	FIXME("Unsupported returned value %p\n", hDdeData); | 
 | 	/* fall through */ | 
 |     case DDE_FNOTPROCESSED: | 
 | 	break; | 
 |     } | 
 |     WDML_PostAck(pConv, WDML_SERVER_SIDE, 0, fBusy, fAck, (UINT)pXAct->hMem, 0, 0); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerQueuePoke | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT* WDML_ServerQueuePoke(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     UINT_PTR		uiLo, uiHi; | 
 |     WDML_XACT*		pXAct; | 
 |  | 
 |     UnpackDDElParam(WM_DDE_POKE, lParam, &uiLo, &uiHi); | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_POKE, | 
 | 				  0, WDML_MakeHszFromAtom(pConv->instance, uiHi)); | 
 |     if (pXAct) | 
 |     { | 
 | 	pXAct->atom = uiHi; | 
 | 	pXAct->hMem = (HGLOBAL)uiLo; | 
 |     } | 
 |     return pXAct; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandlePoke | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandlePoke(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     DDEPOKE*		pDdePoke; | 
 |     HDDEDATA		hDdeData; | 
 |     BOOL		fBusy = FALSE, fAck = FALSE; | 
 |  | 
 |     pDdePoke = (DDEPOKE*)GlobalLock(pXAct->hMem); | 
 |     if (!pDdePoke) | 
 |     { | 
 | 	return WDML_QS_ERROR; | 
 |     } | 
 |  | 
 |     if (!(pConv->instance->CBFflags & CBF_FAIL_POKES)) | 
 |     { | 
 | 	hDdeData = DdeCreateDataHandle(pConv->instance->instanceID, pDdePoke->Value, | 
 | 				       GlobalSize(pXAct->hMem) - sizeof(DDEPOKE) + 1, | 
 | 				       0, 0, pDdePoke->cfFormat, 0); | 
 | 	if (hDdeData) | 
 | 	{ | 
 | 	    HDDEDATA	hDdeDataOut; | 
 |  | 
 | 	    hDdeDataOut = WDML_InvokeCallback(pConv->instance, XTYP_POKE, pDdePoke->cfFormat, | 
 | 					      (HCONV)pConv, pConv->hszTopic, pXAct->hszItem, | 
 | 					      hDdeData, 0, 0); | 
 | 	    switch ((ULONG_PTR)hDdeDataOut) | 
 | 	    { | 
 | 	    case DDE_FACK: | 
 | 		fAck = TRUE; | 
 | 		break; | 
 | 	    case DDE_FBUSY: | 
 | 		fBusy = TRUE; | 
 | 		break; | 
 | 	    default: | 
 | 		FIXME("Unsupported returned value %p\n", hDdeDataOut); | 
 | 		/* fal through */ | 
 | 	    case DDE_FNOTPROCESSED: | 
 | 		break; | 
 | 	    } | 
 | 	    DdeFreeDataHandle(hDdeData); | 
 | 	} | 
 |     } | 
 |     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); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerQueueTerminate | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_XACT*	WDML_ServerQueueTerminate(WDML_CONV* pConv, LPARAM lParam) | 
 | { | 
 |     WDML_XACT*	pXAct; | 
 |  | 
 |     pXAct = WDML_AllocTransaction(pConv->instance, WM_DDE_TERMINATE, 0, 0); | 
 |     return pXAct; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandleTerminate | 
 |  * | 
 |  * | 
 |  */ | 
 | static	WDML_QUEUE_STATE WDML_ServerHandleTerminate(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     /* billx: two things to remove: the conv, and associated links. | 
 |      * Respond with another WM_DDE_TERMINATE iMsg. | 
 |      */ | 
 |     if (!(pConv->instance->CBFflags & CBF_SKIP_DISCONNECTS)) | 
 |     { | 
 | 	WDML_InvokeCallback(pConv->instance, XTYP_DISCONNECT, 0, (HCONV)pConv, 0, 0, | 
 | 			    0, 0, (pConv->wStatus & ST_ISSELF) ? 1 : 0); | 
 |     } | 
 |     PostMessageW(pConv->hwndClient, WM_DDE_TERMINATE, (WPARAM)pConv->hwndServer, 0); | 
 |     WDML_RemoveConv(pConv, WDML_SERVER_SIDE); | 
 |  | 
 |     return WDML_QS_HANDLED; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerHandle | 
 |  * | 
 |  * | 
 |  */ | 
 | WDML_QUEUE_STATE WDML_ServerHandle(WDML_CONV* pConv, WDML_XACT* pXAct) | 
 | { | 
 |     WDML_QUEUE_STATE	qs = WDML_QS_ERROR; | 
 |  | 
 |     switch (pXAct->ddeMsg) | 
 |     { | 
 |     case WM_DDE_INITIATE: | 
 | 	FIXME("WM_DDE_INITIATE shouldn't be there!\n"); | 
 | 	break; | 
 |     case WM_DDE_REQUEST: | 
 | 	qs = WDML_ServerHandleRequest(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_ADVISE: | 
 | 	qs = WDML_ServerHandleAdvise(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_UNADVISE: | 
 | 	qs = WDML_ServerHandleUnadvise(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_EXECUTE: | 
 | 	qs = WDML_ServerHandleExecute(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_POKE: | 
 | 	qs = WDML_ServerHandlePoke(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_TERMINATE: | 
 | 	qs = WDML_ServerHandleTerminate(pConv, pXAct); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_ACK: | 
 | 	WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); | 
 | 	break; | 
 |  | 
 |     default: | 
 | 	FIXME("Unsupported message %d\n", pXAct->ddeMsg); | 
 |     } | 
 |     return qs; | 
 | } | 
 |  | 
 | /****************************************************************** | 
 |  *		WDML_ServerConvProc | 
 |  * | 
 |  * | 
 |  */ | 
 | static LRESULT CALLBACK WDML_ServerConvProc(HWND hwndServer, UINT iMsg, WPARAM wParam, LPARAM lParam) | 
 | { | 
 |     WDML_INSTANCE*	pInstance; | 
 |     WDML_CONV*		pConv; | 
 |     WDML_XACT*		pXAct = NULL; | 
 |  | 
 |     TRACE("%p %04x %08x %08lx\n", hwndServer, iMsg, wParam , lParam); | 
 |  | 
 |     if (iMsg == WM_DESTROY) | 
 |     { | 
 | 	pConv = WDML_GetConvFromWnd(hwndServer); | 
 | 	if (pConv && !(pConv->wStatus & ST_TERMINATED)) | 
 | 	{ | 
 | 	    WDML_ServerHandleTerminate(pConv, NULL); | 
 | 	} | 
 |     } | 
 |     if (iMsg < WM_DDE_FIRST || iMsg > WM_DDE_LAST) | 
 |     { | 
 |         return IsWindowUnicode(hwndServer) ? DefWindowProcW(hwndServer, iMsg, wParam, lParam) : | 
 |                                              DefWindowProcA(hwndServer, iMsg, wParam, lParam); | 
 |     } | 
 |  | 
 |     pInstance = WDML_GetInstanceFromWnd(hwndServer); | 
 |     pConv = WDML_GetConvFromWnd(hwndServer); | 
 |  | 
 |     if (!pConv) | 
 |     { | 
 | 	ERR("Got a message (%x) on a not known conversation, dropping request\n", iMsg); | 
 |         return 0; | 
 |     } | 
 |     if (pConv->hwndClient != WIN_GetFullHandle( (HWND)wParam ) || pConv->hwndServer != hwndServer) | 
 |     { | 
 | 	ERR("mismatch between C/S windows and converstation\n"); | 
 |         return 0; | 
 |     } | 
 |     if (pConv->instance != pInstance || pConv->instance == NULL) | 
 |     { | 
 | 	ERR("mismatch in instances\n"); | 
 |         return 0; | 
 |     } | 
 |  | 
 |     switch (iMsg) | 
 |     { | 
 |     case WM_DDE_INITIATE: | 
 | 	FIXME("WM_DDE_INITIATE message received!\n"); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_REQUEST: | 
 | 	pXAct = WDML_ServerQueueRequest(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_ADVISE: | 
 | 	pXAct = WDML_ServerQueueAdvise(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_UNADVISE: | 
 | 	pXAct = WDML_ServerQueueUnadvise(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_EXECUTE: | 
 | 	pXAct = WDML_ServerQueueExecute(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_POKE: | 
 | 	pXAct = WDML_ServerQueuePoke(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_TERMINATE: | 
 | 	pXAct = WDML_ServerQueueTerminate(pConv, lParam); | 
 | 	break; | 
 |  | 
 |     case WM_DDE_ACK: | 
 | 	WARN("Shouldn't receive a ACK message (never requests them). Ignoring it\n"); | 
 | 	break; | 
 |  | 
 |     default: | 
 | 	FIXME("Unsupported message %x\n", iMsg); | 
 |         break; | 
 |     } | 
 |  | 
 |     if (pXAct) | 
 |     { | 
 | 	pXAct->lParam = lParam; | 
 |  | 
 | 	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 | 
 | 	{ | 
 | 	    WDML_FreeTransaction(pInstance, pXAct, TRUE); | 
 | 	} | 
 |     } | 
 |     else | 
 |         pConv->instance->lastError = DMLERR_MEMORY_ERROR; | 
 |  | 
 |     return 0; | 
 | } |