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

📄 misc.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- 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 "config.h"#include "wine/port.h"#include <string.h>#include <stdarg.h>#include <stdio.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);/* convert between ATOM and HSZ avoiding compiler warnings */#define ATOM2HSZ(atom)	((HSZ)	(ULONG_PTR)(atom))#define HSZ2ATOM(hsz)	((ATOM)	(ULONG_PTR)(hsz))static WDML_INSTANCE*	WDML_InstanceList = NULL;static DWORD		WDML_MaxInstanceID = 0;  /* OK for present, have to worry about wrap-around later */const char		WDML_szEventClass[] = "DdeEventClass";static CRITICAL_SECTION_DEBUG critsect_debug ={    0, 0, &WDML_CritSect,    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },      0, 0, { 0, (DWORD)(__FILE__ ": WDML_CritSect") }};CRITICAL_SECTION WDML_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };/* ================================================================ * * 			Pure DDE (non DDEML) management * * ================================================================ *//***************************************************************** *            PackDDElParam (USER32.@) * * RETURNS *   the packed lParam */LPARAM WINAPI PackDDElParam(UINT msg, UINT_PTR uiLo, UINT_PTR uiHi){    HGLOBAL hMem;    UINT_PTR *params;    switch (msg)    {    case WM_DDE_ACK:    case WM_DDE_ADVISE:    case WM_DDE_DATA:    case WM_DDE_POKE:        if (!(hMem = GlobalAlloc(GMEM_DDESHARE, sizeof(UINT_PTR) * 2)))        {            ERR("GlobalAlloc failed\n");            return 0;        }        if (!(params = GlobalLock(hMem)))        {            ERR("GlobalLock failed (%p)\n", hMem);            return 0;        }        params[0] = uiLo;        params[1] = uiHi;        GlobalUnlock(hMem);        return (LPARAM)hMem;    case WM_DDE_EXECUTE:        return uiHi;    default:        return MAKELPARAM(uiLo, uiHi);    }}/***************************************************************** *            UnpackDDElParam (USER32.@) * * RETURNS *   success: nonzero *   failure: zero */BOOL WINAPI UnpackDDElParam(UINT msg, LPARAM lParam,			    PUINT_PTR uiLo, PUINT_PTR uiHi){    UINT_PTR *params;    switch (msg)    {    case WM_DDE_ACK:    case WM_DDE_ADVISE:    case WM_DDE_DATA:    case WM_DDE_POKE:        if (!lParam) return FALSE;        if (!(params = GlobalLock( (HGLOBAL)lParam )))        {            ERR("GlobalLock failed (%lx)\n", lParam);            return FALSE;        }        TRACE("unpacked: low %08x, high %08x\n", params[0], params[1]);        if (uiLo) *uiLo = params[0];        if (uiHi) *uiHi = params[1];        GlobalUnlock( (HGLOBAL)lParam );        return TRUE;    case WM_DDE_EXECUTE:        if (uiLo) *uiLo = 0;        if (uiHi) *uiHi = lParam;        return TRUE;    default:        if (uiLo) *uiLo = LOWORD(lParam);        if (uiHi) *uiHi = HIWORD(lParam);        return TRUE;    }}/***************************************************************** *            FreeDDElParam (USER32.@) * * RETURNS *   success: nonzero *   failure: zero */BOOL WINAPI FreeDDElParam(UINT msg, LPARAM lParam){    switch (msg)    {    case WM_DDE_ACK:    case WM_DDE_ADVISE:    case WM_DDE_DATA:    case WM_DDE_POKE:        /* first check if it's a global handle */        if (!GlobalHandle( (LPVOID)lParam )) return TRUE;        return !GlobalFree( (HGLOBAL)lParam );    default:        return TRUE;     }}/***************************************************************** *            ReuseDDElParam (USER32.@) * * RETURNS *   the packed lParam */LPARAM WINAPI ReuseDDElParam(LPARAM lParam, UINT msgIn, UINT msgOut,                             UINT_PTR uiLo, UINT_PTR uiHi){    UINT_PTR *params;    switch (msgIn)    {    case WM_DDE_ACK:    case WM_DDE_ADVISE:    case WM_DDE_DATA:    case WM_DDE_POKE:        switch(msgOut)        {        case WM_DDE_ACK:        case WM_DDE_ADVISE:        case WM_DDE_DATA:        case WM_DDE_POKE:            if (!lParam) return 0;            if (!(params = GlobalLock( (HGLOBAL)lParam )))            {                ERR("GlobalLock failed\n");                return 0;            }            params[0] = uiLo;            params[1] = uiHi;            TRACE("Reusing pack %08x %08x\n", uiLo, uiHi);            GlobalLock( (HGLOBAL)lParam );            return lParam;        case WM_DDE_EXECUTE:            FreeDDElParam( msgIn, lParam );            return uiHi;        default:            FreeDDElParam( msgIn, lParam );            return MAKELPARAM(uiLo, uiHi);        }    default:        return PackDDElParam( msgOut, uiLo, uiHi );    }}/***************************************************************** *            ImpersonateDdeClientWindow (USER32.@) * * PARAMS * hWndClient	  [I] handle to DDE client window * hWndServer	  [I] handle to DDE server window */BOOL WINAPI ImpersonateDdeClientWindow(HWND hWndClient, HWND hWndServer){     FIXME("(%p %p): stub\n", hWndClient, hWndServer);     return FALSE;}/***************************************************************** *            DdeSetQualityOfService (USER32.@) */BOOL WINAPI DdeSetQualityOfService(HWND hwndClient, CONST SECURITY_QUALITY_OF_SERVICE *pqosNew,				   PSECURITY_QUALITY_OF_SERVICE pqosPrev){     FIXME("(%p %p %p): stub\n", hwndClient, pqosNew, pqosPrev);     return TRUE;}/* ================================================================ * * 			Instance management * * ================================================================ *//****************************************************************************** *		IncrementInstanceId * *	generic routine to increment the max instance Id and allocate a new application instance */static void WDML_IncrementInstanceId(WDML_INSTANCE* pInstance){    DWORD	id = InterlockedIncrement(&WDML_MaxInstanceID);    pInstance->instanceID = id;    TRACE("New instance id %ld allocated\n", id);}/****************************************************************** *		WDML_EventProc * * */static LRESULT CALLBACK WDML_EventProc(HWND hwndEvent, UINT uMsg, WPARAM wParam, LPARAM lParam){    WDML_INSTANCE*	pInstance;    HSZ			hsz1, hsz2;    switch (uMsg)    {    case WM_WDML_REGISTER:	pInstance = WDML_GetInstanceFromWnd(hwndEvent);        /* try calling the Callback */	if (pInstance && !(pInstance->CBFflags & CBF_SKIP_REGISTRATIONS))	{	    hsz1 = WDML_MakeHszFromAtom(pInstance, wParam);	    hsz2 = WDML_MakeHszFromAtom(pInstance, lParam);	    WDML_InvokeCallback(pInstance, XTYP_REGISTER, 0, 0, hsz1, hsz2, 0, 0, 0);	    WDML_DecHSZ(pInstance, hsz1);	    WDML_DecHSZ(pInstance, hsz2);	}	break;    case WM_WDML_UNREGISTER:	pInstance = WDML_GetInstanceFromWnd(hwndEvent);	if (pInstance && !(pInstance->CBFflags & CBF_SKIP_UNREGISTRATIONS))	{	    hsz1 = WDML_MakeHszFromAtom(pInstance, wParam);	    hsz2 = WDML_MakeHszFromAtom(pInstance, lParam);	    WDML_InvokeCallback(pInstance, XTYP_UNREGISTER, 0, 0, hsz1, hsz2, 0, 0, 0);	    WDML_DecHSZ(pInstance, hsz1);	    WDML_DecHSZ(pInstance, hsz2);	}	break;    case WM_WDML_CONNECT_CONFIRM:	pInstance = WDML_GetInstanceFromWnd(hwndEvent);	if (pInstance && !(pInstance->CBFflags & CBF_SKIP_CONNECT_CONFIRMS))	{	    WDML_CONV*	pConv;	    /* confirm connection...	     * lookup for this conv handle	     */            HWND client = WIN_GetFullHandle( (HWND)wParam );            HWND server = WIN_GetFullHandle( (HWND)lParam );	    for (pConv = pInstance->convs[WDML_SERVER_SIDE]; pConv != NULL; pConv = pConv->next)	    {		if (pConv->hwndClient == client && pConv->hwndServer == server)		    break;	    }	    if (pConv)	    {		pConv->wStatus |= ST_ISLOCAL;		WDML_InvokeCallback(pInstance, XTYP_CONNECT_CONFIRM, 0, (HCONV)pConv,				    pConv->hszTopic, pConv->hszService, 0, 0,				    (pConv->wStatus & ST_ISSELF) ? 1 : 0);	    }	}	break;    default:	return DefWindowProcA(hwndEvent, uMsg, wParam, lParam);    }    return 0;}/****************************************************************** *		WDML_Initialize * * */UINT WDML_Initialize(LPDWORD pidInst, PFNCALLBACK pfnCallback,		     DWORD afCmd, DWORD ulRes, BOOL bUnicode, BOOL b16){    WDML_INSTANCE*		pInstance;    WDML_INSTANCE*		reference_inst;    UINT			ret;    WNDCLASSEXA			wndclass;    TRACE("(%p,%p,0x%lx,%ld)\n",	  pidInst, pfnCallback, afCmd, ulRes);    if (ulRes)    {	ERR("Reserved value not zero?  What does this mean?\n");	/* trap this and no more until we know more */	return DMLERR_NO_ERROR;    }    /* grab enough heap for one control struct - not really necessary for re-initialise     *	but allows us to use same validation routines */    pInstance = (WDML_INSTANCE*)HeapAlloc(GetProcessHeap(), 0, sizeof(WDML_INSTANCE));    if (pInstance == NULL)    {	/* catastrophe !! warn user & abort */	ERR("Instance create failed - out of memory\n");	return DMLERR_SYS_ERROR;    }    pInstance->next = NULL;    pInstance->monitor = (afCmd | APPCLASS_MONITOR);    /* messy bit, spec implies that 'Client Only' can be set in 2 different ways, catch 1 here */    pInstance->clientOnly = afCmd & APPCMD_CLIENTONLY;    pInstance->instanceID = *pidInst; /* May need to add calling proc Id */    pInstance->threadID = GetCurrentThreadId();    pInstance->callback = *pfnCallback;    pInstance->unicode = bUnicode;    pInstance->win16 = b16;    pInstance->nodeList = NULL; /* node will be added later */    pInstance->monitorFlags = afCmd & MF_MASK;    pInstance->servers = NULL;    pInstance->convs[0] = NULL;    pInstance->convs[1] = NULL;    pInstance->links[0] = NULL;    pInstance->links[1] = NULL;    /* isolate CBF flags in one go, expect this will go the way of all attempts to be clever !! */    pInstance->CBFflags = afCmd^((afCmd&MF_MASK)|((afCmd&APPCMD_MASK)|(afCmd&APPCLASS_MASK)));    if (!pInstance->clientOnly)    {	/* Check for other way of setting Client-only !! */	pInstance->clientOnly =	    (pInstance->CBFflags & CBF_FAIL_ALLSVRXACTIONS) == CBF_FAIL_ALLSVRXACTIONS;    }    TRACE("instance created - checking validity \n");    if (*pidInst == 0)    {	/*  Initialisation of new Instance Identifier */	TRACE("new instance, callback %p flags %lX\n",pfnCallback,afCmd);	EnterCriticalSection(&WDML_CritSect);	if (WDML_InstanceList == NULL)	{	    /* can't be another instance in this case, assign to the base pointer */	    WDML_InstanceList = pInstance;	    /* since first must force filter of XTYP_CONNECT and XTYP_WILDCONNECT for	     *		present	     *	-------------------------------      NOTE NOTE NOTE    --------------------------	     *	     *	the manual is not clear if this condition	     *	applies to the first call to DdeInitialize from an application, or the	     *	first call for a given callback !!!	     */	    pInstance->CBFflags = pInstance->CBFflags|APPCMD_FILTERINITS;	    TRACE("First application instance detected OK\n");	    /*	allocate new instance ID */	    WDML_IncrementInstanceId(pInstance);	}	else	{	    /* really need to chain the new one in to the latest here, but after checking conditions	     *	such as trying to start a conversation from an application trying to monitor */	    reference_inst = WDML_InstanceList;	    TRACE("Subsequent application instance - starting checks\n");	    while (reference_inst->next != NULL)	    {		/*		 *	This set of tests will work if application uses same instance Id		 *	at application level once allocated - which is what manual implies		 *	should happen. If someone tries to be		 *	clever (lazy ?) it will fail to pick up that later calls are for		 *	the same application - should we trust them ?		 */		if (pInstance->instanceID == reference_inst->instanceID)		{		    /* Check 1 - must be same Client-only state */		    if (pInstance->clientOnly != reference_inst->clientOnly)		    {			ret = DMLERR_DLL_USAGE;			goto theError;		    }		    /* Check 2 - cannot use 'Monitor' with any non-monitor modes */		    if (pInstance->monitor != reference_inst->monitor)		    {			ret = DMLERR_INVALIDPARAMETER;			goto theError;		    }		    /* Check 3 - must supply different callback address */		    if (pInstance->callback == reference_inst->callback)		    {			ret = DMLERR_DLL_USAGE;			goto theError;		    }		}		reference_inst = reference_inst->next;	    }	    /*  All cleared, add to chain */	    TRACE("Application Instance checks finished\n");	    WDML_IncrementInstanceId(pInstance);	    reference_inst->next = pInstance;	}	LeaveCriticalSection(&WDML_CritSect);	*pidInst = pInstance->instanceID;	/* for deadlock issues, windows must always be created when outside the critical section */	wndclass.cbSize        = sizeof(wndclass);	wndclass.style         = 0;	wndclass.lpfnWndProc   = WDML_EventProc;	wndclass.cbClsExtra    = 0;	wndclass.cbWndExtra    = sizeof(DWORD);	wndclass.hInstance     = 0;	wndclass.hIcon         = 0;

⌨️ 快捷键说明

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