|
|
/*+
* * Microsoft Windows * Copyright (C) Microsoft Corporation, 1997 - 1998. * * Name : cseclogn.cxx * Author:Jeffrey Richter (v-jeffrr) * * Abstract: * This is the client side for Secondary Logon Service * implemented as CreateProcessWithLogon API * in advapi32.dll * * Revision History: * PraeritG 10/8/97 To integrate this in to services.exe * -*/
#define UNICODE
#define SECURITY_WIN32
#include <Windows.h>
#include <wincred.h>
#include <rpc.h>
#include "seclogon.h"
#include "security.h"
#include "dbgdef.h"
//
// must move to winbase.h soon!
#define LOGON_WITH_PROFILE 0x00000001
#define LOGON_NETCREDENTIALS_ONLY 0x00000002
//
// Global function pointers to user32 functions
// This is to dynamically load user32 when CreateProcessWithLogon
// is called.
//
HMODULE hModule1 = NULL;
typedef HDESK (*OPENDESKTOP) ( LPWSTR lpszDesktop, DWORD dwFlags, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
OPENDESKTOP myOpenDesktop = NULL;
typedef HDESK (*GETTHREADDESKTOP)( DWORD dwThreadId);
GETTHREADDESKTOP myGetThreadDesktop = NULL;
typedef BOOL (*CLOSEDESKTOP)( HDESK hDesktop);
CLOSEDESKTOP myCloseDesktop = NULL;
typedef HWINSTA (*OPENWINDOWSTATION)( LPWSTR lpszWinSta, BOOL fInherit, ACCESS_MASK dwDesiredAccess);
OPENWINDOWSTATION myOpenWindowStation = NULL;
typedef HWINSTA (*GETPROCESSWINDOWSTATION)( VOID);
GETPROCESSWINDOWSTATION myGetProcessWindowStation = NULL;
typedef BOOL (*SETPROCESSWINDOWSTATION)(HWINSTA hWinSta); SETPROCESSWINDOWSTATION mySetProcessWindowStation;
typedef BOOL (*CLOSEWINDOWSTATION)( HWINSTA hWinSta);
CLOSEWINDOWSTATION myCloseWindowStation = NULL;
typedef BOOL (*SETUSEROBJECTSECURITY)( HANDLE hObj, PSECURITY_INFORMATION pSIRequested, PSECURITY_DESCRIPTOR pSID);
SETUSEROBJECTSECURITY mySetUserObjectSecurity = NULL;
typedef BOOL (*GETUSEROBJECTSECURITY)( HANDLE hObj, PSECURITY_INFORMATION pSIRequested, PSECURITY_DESCRIPTOR pSID, DWORD nLength, LPDWORD lpnLengthNeeded);
GETUSEROBJECTSECURITY myGetUserObjectSecurity = NULL;
typedef BOOL (*GETUSEROBJECTINFORMATION)( HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded);
GETUSEROBJECTINFORMATION myGetUserObjectInformation = NULL;
////////////////////////////////////////////////////////////////////////
//
// Function prototypes:
//
////////////////////////////////////////////////////////////////////////
DWORD c_SeclCreateProcessWithLogonW(IN SECL_SLI *psli, OUT SECL_SLRI *pslri);
DWORD To_SECL_BLOB_A(IN LPVOID lpEnvironment, OUT SECL_BLOB *psb);
DWORD To_SECL_BLOB_W(IN LPVOID lpEnvironment, OUT SECL_BLOB *psb);
/////////////////////////////////////////////////////////////////////////
//
// Useful macros:
//
/////////////////////////////////////////////////////////////////////////
#define ARRAYSIZE(array) ((sizeof(array)) / (sizeof(array[0])))
#define ASSIGN_SECL_STRING(ss, wsz) \
{ \ ss.pwsz = wsz; \ if (NULL != wsz) {\ ss.ccLength = ss.ccSize = (wcslen(wsz) + 1); \ } \ else { \ ss.ccLength = ss.ccSize = 0; \ } \ }
////////////////////////////////////////////////////////////////////////
//
// Module implementation:
//
//////////////////////////////////////////////////////////////////////////
extern "C" void *__cdecl _alloca(size_t);
BOOL WINAPI CreateProcessWithLogonW( LPCWSTR lpUsername, LPCWSTR lpDomain, LPCWSTR lpPassword, DWORD dwLogonFlags, LPCWSTR lpApplicationName, LPWSTR lpCommandLine, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
/*++
Routine Description:
Arguments:
Return Value:
--*/ {
BOOL AccessWasAllowed = FALSE; BOOL fOk = FALSE; BOOL fRevertWinsta = FALSE; DWORD LastError = ERROR_SUCCESS; HANDLE hheap = GetProcessHeap(); HDESK hDesk = NULL; HWINSTA hWinsta = NULL; HWINSTA hWinstaSave = NULL; LPWSTR pszApplName = NULL; LPWSTR pszCmdLine = NULL; LPWSTR pwszEmptyString = L""; SECL_SLI sli; SECL_SLRI slri; WCHAR wszDesktopName[2*MAX_PATH + 1];
ZeroMemory(&sli, sizeof(sli)); ZeroMemory(&slri, sizeof(slri)); ZeroMemory(&wszDesktopName, sizeof(wszDesktopName));
//
// dynamically load user32.dll and resolve the functions.
//
// note: last error is left as returned by loadlib or getprocaddress
if(hModule1 == NULL) { hModule1 = LoadLibrary(L"user32.dll"); if(hModule1) { myOpenDesktop = (OPENDESKTOP) GetProcAddress(hModule1, "OpenDesktopW"); if(!myOpenDesktop) return FALSE;
myGetThreadDesktop = (GETTHREADDESKTOP) GetProcAddress( hModule1, "GetThreadDesktop"); if(!myGetThreadDesktop) return FALSE;
myCloseDesktop = (CLOSEDESKTOP) GetProcAddress(hModule1, "CloseDesktop"); if(!myCloseDesktop) return FALSE;
myOpenWindowStation = (OPENWINDOWSTATION) GetProcAddress(hModule1, "OpenWindowStationW"); if(!myOpenWindowStation) return FALSE;
myGetProcessWindowStation = (GETPROCESSWINDOWSTATION) GetProcAddress(hModule1, "GetProcessWindowStation"); if(!myGetProcessWindowStation) return FALSE;
mySetProcessWindowStation = (SETPROCESSWINDOWSTATION)GetProcAddress(hModule1, "SetProcessWindowStation"); if (!mySetProcessWindowStation) return FALSE;
myCloseWindowStation = (CLOSEWINDOWSTATION) GetProcAddress(hModule1, "CloseWindowStation");
if(!myCloseWindowStation) return FALSE;
myGetUserObjectSecurity = (GETUSEROBJECTSECURITY) GetProcAddress(hModule1, "GetUserObjectSecurity"); if(!myGetUserObjectSecurity) return FALSE;
mySetUserObjectSecurity = (SETUSEROBJECTSECURITY) GetProcAddress(hModule1, "SetUserObjectSecurity"); if(!mySetUserObjectSecurity) return FALSE;
myGetUserObjectInformation = (GETUSEROBJECTINFORMATION) GetProcAddress(hModule1, "GetUserObjectInformationW"); if(!mySetUserObjectSecurity) return FALSE; } else { return FALSE; } }
__try {
//
// JMR: Do these flags work: CREATE_SEPARATE_WOW_VDM,
// CREATE_SHARED_WOW_VDM
// Valid flags: CREATE_SUSPENDED, CREATE_UNICODE_ENVIRONMENT,
// *_PRIORITY_CLASS
//
// The following flags are illegal. Fail the call if any are specified.
//
if ((dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS | DETACHED_PROCESS)) != 0) { LastError = ERROR_INVALID_PARAMETER; __leave; }
if(dwLogonFlags & ~(LOGON_WITH_PROFILE | LOGON_NETCREDENTIALS_ONLY)) { LastError = ERROR_INVALID_PARAMETER; __leave; }
//
// Turn on the flags that MUST be turned on
//
// We are overloading CREATE_NEW_CONSOLE to
// CREATE_WITH_NETWORK_LOGON
//
dwCreationFlags |= CREATE_DEFAULT_ERROR_MODE | CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP;
//
// If no priority class explicitly specified and this process is IDLE, force IDLE (See CreateProcess documentation)
//
if ((dwCreationFlags & (NORMAL_PRIORITY_CLASS | IDLE_PRIORITY_CLASS | HIGH_PRIORITY_CLASS | REALTIME_PRIORITY_CLASS)) == 0) {
if (GetPriorityClass(GetCurrentProcess()) == IDLE_PRIORITY_CLASS) dwCreationFlags |= IDLE_PRIORITY_CLASS; }
pszApplName = (LPWSTR) HeapAlloc(hheap, 0, sizeof(WCHAR) * (MAX_PATH)); //
// Lookup the fullpathname of the specified executable
//
pszCmdLine = (LPWSTR) HeapAlloc(hheap, 0, sizeof(WCHAR) * (MAX_PATH + lstrlenW(lpCommandLine)));
if(pszApplName == NULL || pszCmdLine == NULL) { LastError = ERROR_INVALID_PARAMETER; __leave; }
if(lpApplicationName == NULL) { if(lpCommandLine != NULL) { //
// Commandline contains the name, we should parse it out and get
// the full path so that correct executable is invoked.
//
DWORD Length; DWORD fileattr; WCHAR TempChar = L'\0'; LPWSTR TempApplName = NULL; LPWSTR TempRemainderString = NULL; LPWSTR WhiteScan = NULL; BOOL SearchRetry = TRUE; LPWSTR ApplName = (LPWSTR) HeapAlloc( hheap, 0, sizeof(WCHAR) * (lstrlenW(lpCommandLine)+1));
LPWSTR NameBuffer = (LPWSTR) HeapAlloc( hheap, 0, sizeof(WCHAR) * (MAX_PATH+1));
if (ApplName == NULL || NameBuffer == NULL) { LastError = ERROR_NOT_ENOUGH_MEMORY; __leave; }
lstrcpy(ApplName, lpCommandLine); WhiteScan = ApplName;
//
// if there is a leading quote
//
if(*WhiteScan == L'\"') { // we will NOT retry search, as app name is quoted.
SearchRetry = FALSE; WhiteScan++; TempApplName = WhiteScan; while(*WhiteScan) { if( *WhiteScan == L'\"') { TempChar = *WhiteScan; *WhiteScan = L'\0'; TempRemainderString = WhiteScan; break; } WhiteScan++; } } else { // skip to the first non-white char
while(*WhiteScan) { if( *WhiteScan == L' ' || *WhiteScan == L'\t') { WhiteScan++; } else break; } TempApplName = WhiteScan;
while(*WhiteScan) { if( *WhiteScan == L' ' || *WhiteScan == L'\t') { TempChar = *WhiteScan; *WhiteScan = L'\0'; TempRemainderString = WhiteScan; break; } WhiteScan++; }
}
RetrySearch: Length = SearchPathW( NULL, TempApplName, (PWSTR)L".exe", MAX_PATH, NameBuffer, NULL );
if(!Length || Length > MAX_PATH) { if(LastError) SetLastError(LastError); else LastError = GetLastError();
CoverForDirectoryCase: //
// If we still have command line left, then keep going
// the point is to march through the command line looking
// for whitespace so we can try to find an image name
// launches of things like:
// c:\word 95\winword.exe /embedding -automation
// require this. Our first iteration will
// stop at c:\word, our next
// will stop at c:\word 95\winword.exe
//
if(TempRemainderString) { *TempRemainderString = TempChar; WhiteScan++; } if(*WhiteScan & SearchRetry) { // again skip to the first non-white char
while(*WhiteScan) { if( *WhiteScan == L' ' || *WhiteScan == L'\t') { WhiteScan++; } else break; } while(*WhiteScan) { if( *WhiteScan == L' ' || *WhiteScan == L'\t') { TempChar = *WhiteScan; *WhiteScan = L'\0'; TempRemainderString = WhiteScan; break; } WhiteScan++; } // we'll do one last try of the whole string.
if(!WhiteScan) SearchRetry = FALSE; goto RetrySearch; }
//
// otherwise we have failed.
//
if(NameBuffer) HeapFree(hheap, 0, NameBuffer); if(ApplName) HeapFree(hheap, 0, ApplName);
// we should let CreateProcess do its job.
if (pszApplName) { HeapFree(hheap, 0, pszApplName); pszApplName = NULL; } lstrcpy(pszCmdLine, lpCommandLine); } else { // searchpath succeeded.
// but it can find a directory!
fileattr = GetFileAttributesW(NameBuffer); if ( fileattr != 0xffffffff && (fileattr & FILE_ATTRIBUTE_DIRECTORY) ) { Length = 0; goto CoverForDirectoryCase; }
//
// so it is not a directory.. it must be the real thing!
//
lstrcpy(pszApplName, NameBuffer); lstrcpy(pszCmdLine, lpCommandLine);
HeapFree(hheap, 0, ApplName); HeapFree(hheap, 0, NameBuffer); }
} else {
LastError = ERROR_INVALID_PARAMETER; __leave; }
} else {
//
// If ApplicationName is not null, we need to handle
// one case here -- the application name is present in
// current directory. All other cases will be handled by
// CreateProcess in the server side anyway.
//
//
// let us get a FullPath relative to current directory
// and try to open it. If it succeeds, then the full path
// is what we'll give as app name.. otherwise will just
// pass what we got from caller and let CreateProcess deal with it.
LPWSTR lpFilePart;
DWORD cchFullPath = GetFullPathName( lpApplicationName, MAX_PATH, pszApplName, &lpFilePart );
if(cchFullPath) { HANDLE hFile; //
// let us try to open it.
// if it works, pszApplName is already setup correctly.
// just close the handle.
hFile = CreateFile(lpApplicationName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
if(hFile == INVALID_HANDLE_VALUE) { // otherwise, keep what the caller gave us.
lstrcpy(pszApplName,lpApplicationName); } else CloseHandle(hFile);
} else // lets keep what the caller gave us.
lstrcpyn(pszApplName, lpApplicationName, MAX_PATH);
//
// Commandline should be kept as is.
//
if(lpCommandLine != NULL) lstrcpy(pszCmdLine, lpCommandLine); else { HeapFree(hheap, 0, pszCmdLine); pszCmdLine = NULL; } }
#if 0
if(lpApplicationName != NULL) lstrcpy(pszApplName,lpApplicationName); else { HeapFree(hheap, 0, pszApplName); pszApplName = NULL; } if(lpCommandLine != NULL) lstrcpy(pszCmdLine, lpCommandLine); else { HeapFree(hheap, 0, pszCmdLine); pszCmdLine = NULL; } #endif
// Construct a memory block will all the info that needs to go to the server
sli.lLogonIdHighPart = 0; sli.ulLogonIdLowPart = 0; sli.ulLogonFlags = dwLogonFlags; sli.ulProcessId = GetCurrentProcessId(); sli.ulCreationFlags = dwCreationFlags;
ASSIGN_SECL_STRING(sli.ssUsername, (LPWSTR) lpUsername); ASSIGN_SECL_STRING(sli.ssDomain, (LPWSTR) lpDomain); ASSIGN_SECL_STRING(sli.ssPassword, (LPWSTR)lpPassword); ASSIGN_SECL_STRING(sli.ssApplicationName, pszApplName); ASSIGN_SECL_STRING(sli.ssCommandLine, pszCmdLine); ASSIGN_SECL_STRING(sli.ssCurrentDirectory, (LPWSTR)lpCurrentDirectory); ASSIGN_SECL_STRING(sli.ssDesktop, lpStartupInfo->lpDesktop); ASSIGN_SECL_STRING(sli.ssTitle, lpStartupInfo->lpTitle);
if (0 != (sli.ulCreationFlags & CREATE_UNICODE_ENVIRONMENT)) { LastError = To_SECL_BLOB_W(lpEnvironment, &(sli.sbEnvironment)); } else { LastError = To_SECL_BLOB_A(lpEnvironment, &(sli.sbEnvironment)); } if (ERROR_SUCCESS != LastError) { __leave; }
// If the caller hasn't specified their own desktop, we'll do it for
// them (the seclogon service will take care of granting access
// to the desktop).
if (sli.ssDesktop.pwsz == NULL || sli.ssDesktop.pwsz[0] == L'\0') { DWORD Length; HWINSTA Winsta = myGetProcessWindowStation(); HDESK Desk = myGetThreadDesktop(GetCurrentThreadId()); // Send seclogon handles to the current windowstation and desktop:
if (0 == (dwLogonFlags & LOGON_NETCREDENTIALS_ONLY)) { sli.hWinsta = (unsigned __int64)Winsta; sli.hDesk = (unsigned __int64)Desk; } else { // In the /netonly case, we don't need to grant access to the desktop:
sli.hWinsta = 0; sli.hDesk = 0; }
// Send seclogon the name of the current windowstation and desktop.
// Default to empty string if we can't get the name:
ASSIGN_SECL_STRING(sli.ssDesktop, pwszEmptyString); if (myGetUserObjectInformation(Winsta, UOI_NAME, wszDesktopName, (MAX_PATH*sizeof(WCHAR)), &Length)) { Length = wcslen(wszDesktopName); wszDesktopName[Length++] = L'\\'; if(myGetUserObjectInformation(Desk, UOI_NAME, &wszDesktopName[Length], (MAX_PATH*sizeof(WCHAR)), &Length)) { // sli.ssDesktop now contains "windowstation\desktop"
ASSIGN_SECL_STRING(sli.ssDesktop, wszDesktopName); } } } else { LPWSTR pwszDeskName;
// The caller specified their own desktop
sli.ulSeclogonFlags |= SECLOGON_CALLER_SPECIFIED_DESKTOP;
// Open a handle to the specified windowstation and desktop:
wcscpy(wszDesktopName, sli.ssDesktop.pwsz); pwszDeskName = wcschr(wszDesktopName, L'\\'); if (NULL == pwszDeskName) { SetLastError(ERROR_INVALID_PARAMETER); __leave; } *pwszDeskName++ = L'\0'; hWinsta = myOpenWindowStation(wszDesktopName, TRUE, MAXIMUM_ALLOWED); if (NULL == hWinsta) __leave;
hWinstaSave = myGetProcessWindowStation(); if (NULL == hWinstaSave) __leave;
if (!mySetProcessWindowStation(hWinsta)) __leave; fRevertWinsta = TRUE;
hDesk = myOpenDesktop(pwszDeskName, 0, TRUE, MAXIMUM_ALLOWED); if (NULL == hDesk) __leave;
// Pass the windowstation and desktop handles to seclogon:
sli.hWinsta = (unsigned __int64)hWinsta; sli.hDesk = (unsigned __int64)hDesk; }
// Perform the RPC call to the seclogon service:
LastError = c_SeclCreateProcessWithLogonW(&sli, &slri); if (ERROR_SUCCESS != LastError) __leave;
fOk = (slri.ulErrorCode == NO_ERROR); // This function succeeds if the server's function succeeds
if (!fOk) { //
// If the server function failed, set the server's
// returned eror code as this thread's error code
//
LastError = slri.ulErrorCode; SetLastError(slri.ulErrorCode); } else { //
// The server function succeeded, return the
// PROCESS_INFORMATION info
//
lpProcessInformation->hProcess = (HANDLE)slri.hProcess; lpProcessInformation->hThread = (HANDLE)slri.hThread; lpProcessInformation->dwProcessId = slri.ulProcessId; lpProcessInformation->dwThreadId = slri.ulThreadId; LastError = ERROR_SUCCESS; } } __finally { if (NULL != pszCmdLine) HeapFree(hheap, 0, pszCmdLine); if (NULL != pszApplName) HeapFree(hheap, 0, pszApplName); if (fRevertWinsta) mySetProcessWindowStation(hWinstaSave); if (NULL != hWinsta) myCloseWindowStation(hWinsta); if (NULL != hDesk) myCloseDesktop(hDesk); SetLastError(LastError); }
return(fOk); }
////////////////////////////////////////////////////////////////////////
//
// RPC Utility methods:
//
////////////////////////////////////////////////////////////////////////
DWORD To_SECL_BLOB_W(IN LPVOID lpEnvironment, OUT SECL_BLOB *psb) { DWORD cb = 0; DWORD dwResult = NULL; HANDLE hHeap = NULL; LPBYTE pb = NULL; LPWSTR pwsz = NULL;
hHeap = GetProcessHeap(); _JumpCondition(NULL == hHeap, GetProcessHeapError);
if (NULL != lpEnvironment) { for (pwsz = (LPWSTR)lpEnvironment; pwsz[0] != L'\0'; pwsz += wcslen(pwsz) + 1);
cb = sizeof(WCHAR) * (DWORD)(((1 + (pwsz - (LPWSTR)lpEnvironment))) & 0xFFFFFFFF); pb = (LPBYTE)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cb); _JumpCondition(NULL == pb, MemoryError);
CopyMemory(pb, (LPBYTE)lpEnvironment, cb); }
psb->cb = cb; psb->pb = pb; dwResult = ERROR_SUCCESS; CommonReturn: return dwResult;
ErrorReturn: if (NULL != pb) { HeapFree(hHeap, 0, pb); } goto CommonReturn;
SET_DWRESULT(GetProcessHeapError, GetLastError()); SET_DWRESULT(MemoryError, ERROR_NOT_ENOUGH_MEMORY); }
DWORD To_SECL_BLOB_A(IN LPVOID lpEnvironment, OUT SECL_BLOB *psb) { DWORD cb = 0; DWORD dwResult; HANDLE hHeap = NULL; LPBYTE pb = NULL; LPSTR psz = NULL;
hHeap = GetProcessHeap(); _JumpCondition(NULL == hHeap, GetProcessHeapError);
if (NULL != lpEnvironment) { for (psz = (LPSTR)lpEnvironment; psz[0] != '\0'; psz += strlen(psz) + 1);
cb = (DWORD)((1 + (psz - (LPSTR)lpEnvironment) & 0xFFFFFFFF)); pb = (LPBYTE)HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cb); _JumpCondition(NULL == pb, MemoryError);
CopyMemory(pb, (LPBYTE)lpEnvironment, cb); }
psb->cb = cb; psb->pb = pb; dwResult = ERROR_SUCCESS; CommonReturn: return dwResult;
ErrorReturn: if (NULL != pb) { HeapFree(hHeap, 0, pb); } goto CommonReturn;
SET_DWRESULT(GetProcessHeapError, GetLastError()); SET_DWRESULT(MemoryError, ERROR_NOT_ENOUGH_MEMORY); }
DWORD StartSeclogonService() { BOOL fResult; DWORD dwInitialCount; DWORD dwResult; SC_HANDLE hSCM; SC_HANDLE hService; SERVICE_STATUS sSvcStatus;
hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); _JumpCondition(hSCM == NULL, OpenSCManagerError);
hService = OpenService(hSCM, wszSvcName, SERVICE_START | SERVICE_QUERY_STATUS); _JumpCondition(NULL == hService, OpenServiceError);
fResult = StartService(hService, NULL, NULL); _JumpCondition(FALSE == fResult, StartServiceError);
// Wait until the service has actually started.
// Set timeout to 20 seconds.
dwInitialCount = GetTickCount();
// Keep polling to see if the service has started ...
while (TRUE) { fResult = QueryServiceStatus(hService, &sSvcStatus); _JumpCondition(FALSE == fResult, QueryServiceStatusError);
// The service is running. We can stop waiting for it.
if (sSvcStatus.dwCurrentState == SERVICE_RUNNING) break;
// Check to see if we've timed out. If GetTickCount() rolls over,
// then at worst we time out early.
_JumpCondition((GetTickCount() - dwInitialCount) > 20000, ServiceTimeoutError);
// Don't hose the service.
SleepEx(100, FALSE); }
// Ok, the service has successfully started.
dwResult = ERROR_SUCCESS; CommonReturn: if (NULL != hSCM) { CloseServiceHandle(hSCM); } if (NULL != hService) { CloseServiceHandle(hService); } return dwResult;
ErrorReturn: goto CommonReturn;
SET_DWRESULT(OpenSCManagerError, GetLastError()); SET_DWRESULT(OpenServiceError, GetLastError()); SET_DWRESULT(QueryServiceStatusError, GetLastError()); SET_DWRESULT(StartServiceError, GetLastError()); SET_DWRESULT(ServiceTimeoutError, ERROR_SERVICE_REQUEST_TIMEOUT); }
DWORD c_SeclCreateProcessWithLogonW (IN SECL_SLI *psli, OUT SECL_SLRI *pslri) { BOOL fResult; DWORD dwResult; LPWSTR pwszBinding = NULL; RPC_BINDING_HANDLE hRPCBinding = NULL;
dwResult = RpcStringBindingCompose (NULL, (USHORT *)L"ncacn_np", NULL, (USHORT *)L"\\PIPE\\" wszSeclogonSharedProcEndpointName, (USHORT *)L"Security=impersonation static false", (USHORT **)&pwszBinding); _JumpCondition(RPC_S_OK != dwResult, RpcStringBindingComposeError);
dwResult = RpcBindingFromStringBinding((USHORT *)pwszBinding, &hRPCBinding); _JumpCondition(0 != dwResult, RpcBindingFromStringBindingError);
// Perform the RPC call to the seclogon service. If the call fails because the
// service was not started, try again. If the call still fails, give up.
for (BOOL fFirstTry = TRUE; TRUE; fFirstTry = FALSE) { __try { SeclCreateProcessWithLogonW(hRPCBinding, psli, pslri); break; } __except(EXCEPTION_EXECUTE_HANDLER) { dwResult = RpcExceptionCode(); if ((RPC_S_SERVER_UNAVAILABLE == dwResult || RPC_S_UNKNOWN_IF == dwResult) && (TRUE == fFirstTry)) { // Ok, the seclogon service is probably just not started.
// Attempt to start it up and try again.
dwResult = StartSeclogonService(); _JumpCondition(ERROR_SUCCESS != dwResult, SeclCreateProcessWithLogonWError); } else { goto SeclCreateProcessWithLogonWError; } } }
dwResult = ERROR_SUCCESS; CommonReturn: if (NULL != pwszBinding) { RpcStringFree((USHORT **)&pwszBinding); } if (NULL != hRPCBinding) { RpcBindingFree(&hRPCBinding); } return dwResult;
ErrorReturn: goto CommonReturn;
SET_DWRESULT(RpcBindingFromStringBindingError, dwResult); SET_DWRESULT(RpcStringBindingComposeError, dwResult); SET_DWRESULT(SeclCreateProcessWithLogonWError, dwResult); }
void DbgPrintf( DWORD dwSubSysId, LPCSTR pszFormat , ...) { }
//////////////////////////////// End Of File /////////////////////////////////
|