|
|
/****************************** Module Header ******************************\
* Module Name: ddemlcli.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * DDE Manager main client side module * * Created: 10/3/91 Sanford Staab * \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
// DDEML globals
PCL_INSTANCE_INFO pciiList = NULL; RTL_CRITICAL_SECTION gcsDDEML; #if DBG
PVOID gpDDEMLHeap; #endif
/***************************************************************************\
* DdeInitialize (DDEML API) * * Description: * Used two different ways: * 1) First time call (*pidInst == 0) - causes a DDEML instance to be * created for the calling process/thread. Creates a server side * event window, server side instance structure, DDE Access Object, * and client side instance structure. The callback function address * and filter flags (afCmd) are placed into these structures. * 2) Subsequent call (*pidInst == hInst) - updates filter flags in * client and server side structures. * * History: * 11-1-91 sanfords Created. \***************************************************************************/
FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeInitializeA, LPDWORD, pidInst, PFNCALLBACK, pfnCallback, DWORD, afCmd, DWORD, ulRes) UINT DdeInitializeA( LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes) { if (ulRes != 0) { return (DMLERR_INVALIDPARAMETER); } return (InternalDdeInitialize(pidInst, pfnCallback, afCmd, 0)); }
FUNCLOG4(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeInitializeW, LPDWORD, pidInst, PFNCALLBACK, pfnCallback, DWORD, afCmd, DWORD, ulRes) UINT DdeInitializeW( LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, DWORD ulRes) { if (ulRes != 0) { return (DMLERR_INVALIDPARAMETER); } return (InternalDdeInitialize(pidInst, pfnCallback, afCmd, 1)); }
UINT InternalDdeInitialize( LPDWORD pidInst, PFNCALLBACK pfnCallback, DWORD afCmd, BOOL fUnicode) { UINT uiRet = DMLERR_MEMORY_ERROR; register PCL_INSTANCE_INFO pcii;
if (afCmd & APPCLASS_MONITOR) { afCmd |= CBF_MONMASK; }
if (afCmd & APPCMD_CLIENTONLY) { afCmd |= CBF_FAIL_CONNECTIONS; }
EnterDDECrit;
if (*pidInst != 0) { pcii = ValidateInstance((HANDLE)LongToHandle( *pidInst )); if (pcii == NULL) { uiRet = DMLERR_INVALIDPARAMETER; goto Exit; }
// only allow certain bits to be changed on reinitialize call
pcii->afCmd = (pcii->afCmd & ~(CBF_MASK | MF_MASK)) | (afCmd & (CBF_MASK | MF_MASK));
LeaveDDECrit; NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, afCmd); return (DMLERR_NO_ERROR); }
pcii = (PCL_INSTANCE_INFO)DDEMLAlloc(sizeof(CL_INSTANCE_INFO)); if (pcii == NULL) { uiRet = DMLERR_MEMORY_ERROR; goto Exit; }
pcii->plaNameService = (LATOM *)DDEMLAlloc(sizeof(LATOM)); if (pcii->plaNameService == NULL) { uiRet = DMLERR_MEMORY_ERROR; goto Backout3; } // *pcii->plaNameService = 0; // zero init takes care of this
pcii->cNameServiceAlloc = 1;
/*
* Flag this window as being create from a diff hmod as the app so * hotkeys don't take it as the first window created in the app and * assign it as the hotkey. */ pcii->hwndMother = _CreateWindowEx(0, (LPTSTR)(gpsi->atomSysClass[ICLS_DDEMLMOTHER]), L"", WS_POPUP, 0, 0, 0, 0, (HWND)0, (HMENU)0, 0, (LPVOID)NULL, CW_FLAGS_DIFFHMOD);
if (pcii->hwndMother == 0) { uiRet = DMLERR_SYS_ERROR; goto Backout2; } SetWindowLongPtr(pcii->hwndMother, GWLP_INSTANCE_INFO, (LONG_PTR)pcii);
pcii->afCmd = afCmd | APPCMD_FILTERINITS; pcii->pfnCallback = pfnCallback; // pcii->LastError = DMLERR_NO_ERROR; // zero init
pcii->tid = GetCurrentThreadId(); // pcii->aServerLookup = NULL; // zero init
// pcii->cServerLookupAlloc = 0; // zero init
// pcii->ConvStartupState = 0; // zero init - Not blocked.
// pcii->flags = 0; // zero init
// pcii->cInDDEMLCallback = 0; // zero init
// pcii->pLinkCounts = NULL; // zero init
// Do this last when the client side is ready for whatever events
// flying around may come charging in.
LeaveDDECrit; uiRet = NtUserDdeInitialize(&pcii->hInstServer, &pcii->hwndEvent, &pcii->MonitorFlags, pcii->afCmd, pcii); EnterDDECrit;
if (uiRet != DMLERR_NO_ERROR) { Backout: NtUserDestroyWindow(pcii->hwndMother); Backout2: DDEMLFree(pcii->plaNameService); Backout3: DDEMLFree(pcii); goto Exit; } pcii->hInstClient = AddInstance(pcii->hInstServer); *pidInst = HandleToUlong(pcii->hInstClient); if (pcii->hInstClient == 0) { LeaveDDECrit; NtUserCallOneParam((ULONG_PTR)pcii->hInstServer, SFI__CSDDEUNINITIALIZE); EnterDDECrit; uiRet = DMLERR_MEMORY_ERROR; goto Backout; } SetHandleData(pcii->hInstClient, (ULONG_PTR)pcii);
pcii->next = pciiList; pciiList = pcii; if (fUnicode) { pcii->flags |= IIF_UNICODE; } uiRet = DMLERR_NO_ERROR;
Exit: LeaveDDECrit; return (uiRet); }
/***************************************************************************\
* DdeUninitialize (DDEML API) * * Description: * Shuts down a DDEML instance and frees all associated resources. * * History: * 11-12-91 sanfords Created. \***************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeUninitialize, DWORD, idInst) BOOL DdeUninitialize( DWORD idInst) { PCL_INSTANCE_INFO pcii, pciiPrev; BOOL fRet = FALSE;
CheckDDECritOut; EnterDDECrit;
pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; }
/*
* If this thread is in the middle of a synchronous transaction or * a callback, we need to back out of those first. */ if ((pcii->flags & IIF_IN_SYNC_XACT) || pcii->cInDDEMLCallback) { pcii->afCmd |= APPCMD_UNINIT_ASAP; fRet = TRUE; goto Exit; }
ApplyFunctionToObjects(HTYPE_CONVERSATION_LIST, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnectList); ApplyFunctionToObjects(HTYPE_CLIENT_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnect); ApplyFunctionToObjects(HTYPE_SERVER_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)DdeDisconnect); ApplyFunctionToObjects(HTYPE_ZOMBIE_CONVERSATION, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)WaitForZombieTerminate); ApplyFunctionToObjects(HTYPE_DATA_HANDLE, InstFromHandle(pcii->hInstClient), (PFNHANDLEAPPLY)ApplyFreeDataHandle);
LeaveDDECrit; NtUserCallOneParam((ULONG_PTR)pcii->hInstServer, SFI__CSDDEUNINITIALIZE); NtUserDestroyWindow(pcii->hwndMother); EnterDDECrit;
DDEMLFree(pcii->plaNameService); DestroyInstance(pcii->hInstClient);
// unlink pcii from pciiList
if (pciiList == pcii) { pciiList = pciiList->next; } else { for (pciiPrev = pciiList; pciiPrev != NULL && pciiPrev->next != pcii; pciiPrev = pciiPrev->next) { ; } if (pciiPrev != NULL) { pciiPrev->next = pcii->next; } } DDEMLFree(pcii); fRet = TRUE;
Exit: LeaveDDECrit; return (fRet); }
/***************************************************************************\
* DdeNameService (DDEML API) * * Description: * Registers, and Unregisters service names and sets the Initiate filter * state for an instance. * * History: * 11-1-91 sanfords Created. \***************************************************************************/ HDDEDATA DdeNameService( DWORD idInst, HSZ hsz1, // service name
HSZ hsz2, // reserved for future enhancements
UINT afCmd) // DNS_ flags.
{ BOOL fRet = TRUE; LATOM *plaNameService; PCL_INSTANCE_INFO pcii;
EnterDDECrit;
pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); fRet = FALSE; goto Exit; }
if ((hsz1 && ValidateHSZ(hsz1) == HSZT_INVALID) || hsz2 != 0) { SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); fRet = FALSE; goto Exit; }
if (afCmd & DNS_FILTERON && !(pcii->afCmd & APPCMD_FILTERINITS)) { pcii->afCmd |= APPCMD_FILTERINITS; NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd); } if (afCmd & DNS_FILTEROFF && (pcii->afCmd & APPCMD_FILTERINITS)) { pcii->afCmd &= ~APPCMD_FILTERINITS; NtUserUpdateInstance(pcii->hInstServer, &pcii->MonitorFlags, pcii->afCmd); }
if (afCmd & (DNS_REGISTER | DNS_UNREGISTER)) { GATOM ga;
if (pcii->afCmd & APPCMD_CLIENTONLY) { SetLastDDEMLError(pcii, DMLERR_DLL_USAGE); fRet = FALSE; goto Exit; }
if (hsz1 == 0) { if (afCmd & DNS_REGISTER) {
/*
* registering NULL is not allowed! */ SetLastDDEMLError(pcii, DMLERR_INVALIDPARAMETER); fRet = FALSE; goto Exit; }
/*
* unregistering NULL is just like unregistering each * registered name. * * 10/19/90 - made this a synchronous event so that hsz * can be freed by calling app after this call completes * without us having to keep a copy around forever. */ plaNameService = pcii->plaNameService; while (*plaNameService != 0) { ga = LocalToGlobalAtom(*plaNameService); DeleteAtom(*plaNameService); LeaveDDECrit; RegisterService(FALSE, ga, pcii->hwndMother); EnterDDECrit; GlobalDeleteAtom(ga); plaNameService++; } pcii->cNameServiceAlloc = 1; *pcii->plaNameService = 0; goto Exit; }
if (afCmd & DNS_REGISTER) { plaNameService = (LATOM *)DDEMLReAlloc(pcii->plaNameService, sizeof(LATOM) * ++pcii->cNameServiceAlloc); if (plaNameService == NULL) { SetLastDDEMLError(pcii, DMLERR_MEMORY_ERROR); pcii->cNameServiceAlloc--; fRet = FALSE; goto Exit; } else { pcii->plaNameService = plaNameService; } IncLocalAtomCount(LATOM_FROM_HSZ(hsz1)); // NameService copy
plaNameService[pcii->cNameServiceAlloc - 2] = LATOM_FROM_HSZ(hsz1); plaNameService[pcii->cNameServiceAlloc - 1] = 0;
} else { // DNS_UNREGISTER
plaNameService = pcii->plaNameService; while (*plaNameService != 0 && *plaNameService != LATOM_FROM_HSZ(hsz1)) { plaNameService++; } if (*plaNameService == 0) { goto Exit; // not found just exit
} //
// fill empty slot with last entry and fill last entry with 0
//
pcii->cNameServiceAlloc--; *plaNameService = pcii->plaNameService[pcii->cNameServiceAlloc - 1]; pcii->plaNameService[pcii->cNameServiceAlloc - 1] = 0; }
ga = LocalToGlobalAtom(LATOM_FROM_HSZ(hsz1)); LeaveDDECrit; RegisterService((afCmd & DNS_REGISTER) ? TRUE : FALSE, ga, pcii->hwndMother); EnterDDECrit; GlobalDeleteAtom(ga); }
Exit: LeaveDDECrit; return ((HDDEDATA)IntToPtr( fRet )); }
/***************************************************************************\
* DdeGetLastError (DDEML API) * * Description: * Returns last error code set for the instance given. * * History: * 11-12-91 sanfords Created. \***************************************************************************/
FUNCLOG1(LOG_GENERAL, UINT, DUMMYCALLINGTYPE, DdeGetLastError, DWORD, idInst) UINT DdeGetLastError( DWORD idInst) { UINT uiRet = 0; PCL_INSTANCE_INFO pcii;
EnterDDECrit;
pcii = ValidateInstance((HANDLE)LongToHandle( idInst )); if (pcii == NULL) { uiRet = DMLERR_INVALIDPARAMETER; goto Exit; } uiRet = pcii->LastError; pcii->LastError = DMLERR_NO_ERROR;
Exit: LeaveDDECrit; return (uiRet); }
/***************************************************************************\
* DdeImpersonateClient() * * Description: * Does security impersonation for DDEML server apps. * This API should only be called with server side hConvs; * * History: * 5-4-92 sanfords Created. \***************************************************************************/
FUNCLOG1(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, DdeImpersonateClient, HCONV, hConv) BOOL DdeImpersonateClient( HCONV hConv) { PCONV_INFO pcoi; PCL_INSTANCE_INFO pcii; BOOL fRet = FALSE;
EnterDDECrit;
pcoi = (PCONV_INFO)ValidateCHandle((HANDLE)hConv, HTYPE_SERVER_CONVERSATION, HINST_ANY); if (pcoi == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; } pcii = PciiFromHandle((HANDLE)hConv); if (pcii == NULL) { BestSetLastDDEMLError(DMLERR_INVALIDPARAMETER); goto Exit; }
fRet = NtUserImpersonateDdeClientWindow(pcoi->hwndPartner, pcoi->hwndConv); Exit: LeaveDDECrit; return (fRet); }
|