📄 misc.c
字号:
/* -*- 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 + -