⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- tab-width: 8; c-basic-offset: 4 -*- *//* * DDEML library * * Copyright 1997 Alexandre Julliard * Copyright 1997 Len White * Copyright 1999 Keith Matthews * Copyright 2000 Corel * Copyright 2001 Eric Pouech * * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdarg.h>#include <string.h>#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "winerror.h"#include "dde.h"#include "ddeml.h"#include "win.h"#include "wine/debug.h"#include "dde/dde_private.h"WINE_DEFAULT_DEBUG_CHANNEL(ddeml);static const char  szServerNameClassA[] = "DdeServerNameAnsi";const char  WDML_szServerConvClassA[] = "DdeServerConvAnsi";const WCHAR WDML_szServerConvClassW[] = {'D','d','e','S','e','r','v','e','r','C','o','n','v','U','n','i','c','o','d','e',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("(%ld,%p,%p)\n", idInst, hszTopic, hszItem);    EnterCriticalSection(&WDML_CritSect);    pInstance = WDML_GetInstance(idInst);    if (pInstance == NULL || pInstance->links == NULL)    {	goto theError;    }    atom = WDML_MakeAtomFromHsz(hszItem);    if (!atom) goto theError;    /* 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 (!PostMessageA(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;		    if (!WDML_IsAppOwned(hDdeData))  DdeFreeDataHandle(hDdeData);		    GlobalFree(hItemData);		    goto theError;		}                if (!WDML_IsAppOwned(hDdeData))  DdeFreeDataHandle(hDdeData);	    }	}    }    LeaveCriticalSection(&WDML_CritSect);    return TRUE; theError:    LeaveCriticalSection(&WDML_CritSect);    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;    WNDCLASSEXA  	wndclass;    hDdeData = NULL;    TRACE("(%ld,%p,%p,%x)\n", idInst, hsz1, hsz2, afCmd);    EnterCriticalSection(&WDML_CritSect);    /*  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 */	goto theError;    }    if (hsz2 != 0L)    {	/*	Illegal, reserved parameter	 */	pInstance->lastError = DMLERR_INVALIDPARAMETER;	WARN("Reserved parameter no-zero !!\n");	goto theError;    }    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;	goto theError;    }    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;	    goto theError;	}	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(DWORD);	wndclass.hInstance     = 0;	wndclass.hIcon         = 0;	wndclass.hCursor       = 0;	wndclass.hbrBackground = 0;	wndclass.lpszMenuName  = NULL;	wndclass.lpszClassName = szServerNameClassA;	wndclass.hIconSm       = 0;	RegisterClassExA(&wndclass);	LeaveCriticalSection(&WDML_CritSect);	hwndServer = CreateWindowA(szServerNameClassA, NULL,				   WS_POPUP, 0, 0, 0, 0,				   0, 0, 0, 0);	EnterCriticalSection(&WDML_CritSect);	SetWindowLongA(hwndServer, GWL_WDML_INSTANCE, (DWORD)pInstance);	SetWindowLongA(hwndServer, GWL_WDML_SERVER, (DWORD)pServer);	TRACE("Created nameServer=%p for instance=%08lx\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;	    goto theError;	}	else	{	    pServer->filterOn = (afCmd & DNS_FILTERON) != 0;	}    }    LeaveCriticalSection(&WDML_CritSect);    return (HDDEDATA)TRUE; theError:    LeaveCriticalSection(&WDML_CritSect);    return FALSE;}/****************************************************************** *		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(DWORD);	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(DWORD);	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=%08lx\n",	  hwndServerConv, hwndServerName, pInstance->instanceID);    pConv = WDML_AddConv(pInstance, WDML_SERVER_SIDE, hszApp, hszTopic,			 hwndClient, hwndServerConv);    if (pConv)    {	SetWindowLongA(hwndServerConv, GWL_WDML_INSTANCE, (DWORD)pInstance);	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,		     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=%ld, threadID=0x%lx\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)) &&		 strcmp(buf, WDML_szClientConvClassA) == 0) ||		(GetClassNameW(hwndClient, (LPWSTR)buf, sizeof(buf)/sizeof(WCHAR)) &&		 lstrcmpW((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*)GetWindowLongA(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, (DWORD)pcc, self);		    if ((UINT)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, (DWORD)pcc, self);                        }		    }		}	    }	    else if (pInstance->servers)	    {		/* pass on to the callback  */		hDdeData = WDML_InvokeCallback(pInstance, XTYP_WILDCONNECT,					       0, 0, hszTop, hszApp, 0, (DWORD)pcc, self);		if (hDdeData == (HDDEDATA)CBR_BLOCK)		{		    /* MS doc is not consistent here */		    FIXME("CBR_BLOCK returned for WILDCONNECT\n");		}		else if ((UINT)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, (DWORD)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;    }    return DefWindowProcA(hwndServer, iMsg, wParam, lParam);}/******************************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -