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.
 
 
 
 
 
 

441 lines
15 KiB

/*++
Copyright (C) 2000 Microsoft Corporation
All rights reserved.
Module Name:
gdithnk.cxx
Abstract:
This file contains the startup code for the
surrogate rpc server used to load 64 bit dlls
in 32 bit apps
Author:
Khaled Sedky (khaleds) 19-Jun-2000
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "sddl.h"
#ifndef __LDFUNCS_HPP__
#include "ldfuncs.hpp"
#endif
#ifndef __LDMGR_HPP__
#include "ldmgr.hpp"
#endif
#ifndef __GDITHNK_HPP__
#include "gdithnk.hpp"
#endif
/*++
Function Name:
LPCConnMsgsServingThread
Description:
This funciton is the main loop for processing LPC requests
by dispatching them to the LPC handler which takes the proper
action according to the request.
This function runs in a Thread of its own.
Parameters:
pThredData : The Thread specific data which encapsulates the
pointer to the LPC handler.
Return Value
Always returns 1
--*/
EXTERN_C
DWORD
LPCConnMsgsServingThread(
PVOID pThrdData
)
{
//
// Communication Port Handles are unique , i.e. one per
// Client Server conversation
//
HANDLE ConnectionPortHandle;
NTSTATUS Status = STATUS_SUCCESS;
DWORD ErrorCode = ERROR_SUCCESS;
PVOID pCommunicationPortContext = NULL;
SPROXY_MSG RequestMsg;
PSPROXY_MSG pReplyMsg;
//
// reconstruct the Data passed in for the Thread
//
TLPCMgr* pMgrInst = reinterpret_cast<TLPCMgr*>((reinterpret_cast<PSLPCMSGSTHRDDATA>(pThrdData))->pData);
SPLASSERT(pMgrInst);
ConnectionPortHandle = pMgrInst->GetUMPDLpcConnPortHandle();
for(pReplyMsg=NULL,memset(&RequestMsg,0,sizeof(SPROXY_MSG));
pMgrInst;)
{
//
// Data sent back to client and then call blocked until another message
// comes in
//
Status = NtReplyWaitReceivePort( ConnectionPortHandle,
reinterpret_cast<PVOID*>(&pCommunicationPortContext),
reinterpret_cast<PPORT_MESSAGE>(pReplyMsg),
reinterpret_cast<PPORT_MESSAGE>(&RequestMsg)
);
DBGMSG(DBG_WARN,
("LPCConnMsgsServingThread Active \n"));
ConnectionPortHandle = pMgrInst->GetUMPDLpcConnPortHandle();
pReplyMsg = NULL;
if(NT_SUCCESS(Status))
{
switch(RequestMsg.Msg.u2.s2.Type)
{
//
// For a Connection Request coming from the Client
//
case LPC_CONNECTION_REQUEST:
{
pMgrInst->ProcessConnectionRequest((PPORT_MESSAGE)&RequestMsg);
break;
}
//
// For a Data Request coming in from the client
//
case LPC_REQUEST:
{
if((ErrorCode = pMgrInst->ProcessRequest(&RequestMsg)) == ERROR_SUCCESS)
{
pReplyMsg = &RequestMsg;
}
//
// We retrieve the coomunication handle from LPC becauce this is how we send data
// back to the client. We can't used a connection port
//
ConnectionPortHandle = (reinterpret_cast<TLPCMgr::TClientInfo*>(pCommunicationPortContext))->GetPort();
break;
}
//
// When the client close the port.
//
case LPC_PORT_CLOSED:
{
if(pCommunicationPortContext)
{
HANDLE hPortID =
(reinterpret_cast<TLPCMgr::TClientInfo*>(pCommunicationPortContext))->GetPort();
pMgrInst->ProcessPortClosure(&RequestMsg,hPortID);
}
break;
}
//
// When the client terminates (Normally or Abnormally)
//
case LPC_CLIENT_DIED:
{
if(pCommunicationPortContext)
{
pMgrInst->ProcessClientDeath(&RequestMsg);
}
break;
}
default:
{
//
// Basically here we do nothing, we just retrun.
//
break;
}
}
}
}
//
// Cleaning up the memory allocated before leaving the Thread
//
delete pThrdData;
return 1;
}
EXTERN_C
DWORD
GDIThunkingVIALPCThread(
PVOID pThrdData
)
{
OBJECT_ATTRIBUTES ObjectAttrib;
UNICODE_STRING UString;
PFNGDIPRINTERTHUNKPROC pfnThnkFn;
NTSTATUS Status = STATUS_SUCCESS;
HINSTANCE hGDI = NULL;
WCHAR pszPortName[MAX_PATH] = {0};
WCHAR szFullSD[MAX_PATH] = {0};
//
// reconstruct the Data passed in for the Thread
//
DWORD *pErrorCode = &(reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->ErrorCode;
HANDLE hSyncEvent = (reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->hEvent;
TLPCMgr *pMgrInst = reinterpret_cast<TLPCMgr*>((reinterpret_cast<PSGDIThunkThrdData>(pThrdData))->pData);
if(hGDI = LoadLibrary(L"GDI32.DLL"))
{
if(pfnThnkFn = reinterpret_cast<PFNGDIPRINTERTHUNKPROC>(GetProcAddress(hGDI,
"GdiPrinterThunk")))
{
PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
LPWSTR pszUserSID = NULL;
HRESULT hRes = E_FAIL;
//
// Give System SID a full access ACE
// Give Creator Owner SID a full access ACE
// Give the current user a full access ACE
//
WCHAR* szSD = L"D:"
L"(A;OICI;GA;;;SY)"
L"(A;OICI;GA;;;CO)"
L"(A;;GA;;;";
StringCchPrintfW(pszPortName,
MAX_PATH,
L"%s_%x",
GDI_LPC_PORT_NAME,
pMgrInst->GetCurrSessionId());
RtlInitUnicodeString(&UString,
pszPortName);
if(SUCCEEDED (hRes = GetCurrentUserSID(&pszUserSID,
pErrorCode)))
{
//
// Concatenate everything representing
// the required ACEs for the pipe DACL
//
StringCchPrintf(szFullSD,MAX_PATH,
L"%ws%ws%ws",szSD,pszUserSID,L")");
LocalFree(pszUserSID);
if( ConvertStringSecurityDescriptorToSecurityDescriptor(szFullSD,
SDDL_REVISION_1,
&pSecurityDescriptor,
NULL))
{
InitializeObjectAttributes(&ObjectAttrib,
&UString,
OBJ_CASE_INSENSITIVE,
NULL,
pSecurityDescriptor);
Status = NtCreatePort(pMgrInst->GetUMPDLPCConnPortHandlePtr(),
&ObjectAttrib,
PORT_MAXIMUM_MESSAGE_LENGTH,
PORT_MAXIMUM_MESSAGE_LENGTH,
PORT_MAXIMUM_MESSAGE_LENGTH*32
);
if(NT_SUCCESS(Status))
{
//
// Start processing the LPC messages either in one Thread
// or multiple Threads
//
HANDLE hMsgThrd;
DWORD MsgThrdId;
if(PSLPCMSGSTHRDDATA pLPCMsgData = new SLPCMSGSTHRDDATA)
{
pLPCMsgData->pData = reinterpret_cast<void*>(pMgrInst);
pMgrInst->SetPFN(pfnThnkFn);
if(hMsgThrd = CreateThread(NULL,
0,
LPCConnMsgsServingThread,
(VOID *)pLPCMsgData,
0,
&MsgThrdId))
{
CloseHandle(hMsgThrd);
}
else
{
delete pLPCMsgData;
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to create the messaging thread - %u\n",*pErrorCode));
}
}
else
{
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to allocate memory - %u\n",*pErrorCode));
}
}
else
{
*pErrorCode = pMgrInst->MapNtStatusToWin32Error(Status);
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to create the LPC port - %u\n",Status));
}
LocalFree(pSecurityDescriptor);
}
else
{
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to create the Security Descriptor - %u\n",*pErrorCode));
}
}
}
else
{
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to get the entry point GdiPrinterThunk - %u\n",*pErrorCode));
}
}
else
{
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GDIThunkVIALPCThread: Failed to load GDI32 - %u\n",*pErrorCode));
}
SetEvent(hSyncEvent);
return 1;
}
/*++
Function Name:
GetCurrentUserSID
Description:
This funciton returns the SID of the current logged on user
Parameters:
ppszUserSID : This is the out string to be filled by
the current user SID
pErrorCode : Return the WIN32 error code to the caller
Return Value
HRSEUSLT : S_OK = success
E_FAIL = failure
--*/
HRESULT
GetCurrentUserSID(
PWSTR* ppszUserSID,
PDWORD pErrorCode
)
{
HANDLE hToken = NULL;
PTOKEN_USER pTokenUser = NULL;
DWORD TokenUserLen = 0;
HRESULT hRes = E_FAIL;
if(OpenThreadToken(GetCurrentThread(),
TOKEN_QUERY,
TRUE,
&hToken))
{
hRes = S_OK;
}
else if((*pErrorCode = GetLastError()) == ERROR_NO_TOKEN)
{
if(OpenProcessToken(GetCurrentProcess(),
TOKEN_QUERY,
&hToken))
{
hRes = S_OK;
}
else
{
*pErrorCode = GetLastError();
DBGMSG(DBG_WARN,
("GetCurrentUserSID: Failed to open the Process Token - %u\n",*pErrorCode));
}
}
else
{
DBGMSG(DBG_WARN,
("GetCurrentUserSID: Failed to open the Thread Token - %u\n",*pErrorCode));
}
if(SUCCEEDED(hRes))
{
*pErrorCode = ERROR_SUCCESS;
if(!GetTokenInformation(hToken,
TokenUser,
NULL,
0,
&TokenUserLen) &&
((*pErrorCode = GetLastError()) == ERROR_INSUFFICIENT_BUFFER))
{
if(pTokenUser = reinterpret_cast<PTOKEN_USER>(new BYTE[TokenUserLen]))
{
if(GetTokenInformation(hToken,
TokenUser,
pTokenUser,
TokenUserLen,
&TokenUserLen))
{
*pErrorCode = ERROR_SUCCESS;
//
// The required SID is at pTokenUser->User.Sid
//
if(!ConvertSidToStringSid(pTokenUser->User.Sid,
ppszUserSID))
{
*pErrorCode = GetLastError();
}
}
delete [] reinterpret_cast<BYTE*>(pTokenUser);
}
else
{
*pErrorCode = ERROR_NOT_ENOUGH_MEMORY;
}
}
else
{
DBGMSG(DBG_WARN,
("GetCurrentUserSID: Failed to get Thread Information - %u\n",*pErrorCode));
}
hRes = *pErrorCode == ERROR_SUCCESS ? S_OK : E_FAIL;
CloseHandle(hToken);
}
return hRes;
}