Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

473 lines
14 KiB

/****************************** 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);
}