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.
1720 lines
51 KiB
1720 lines
51 KiB
//*************************************************************
|
|
//
|
|
// Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
|
|
//
|
|
// File: diagprov.cpp
|
|
//
|
|
// Description: Rsop diagnostic mode provider
|
|
//
|
|
// History: 8-20-99 leonardm Created
|
|
//
|
|
//*************************************************************
|
|
|
|
#include "uenv.h"
|
|
#include "diagprov.h"
|
|
#include "rsopinc.h"
|
|
#include "Indicate.h"
|
|
#include "rsopdbg.h"
|
|
#include "rsopsec.h"
|
|
#include <strsafe.h>
|
|
|
|
HRESULT EnumerateUserNameSpace( IWbemLocator *pWbemLocator, HANDLE hToken, SAFEARRAY **psaUserSids );
|
|
|
|
HRESULT UpdateGPCoreStatus(IWbemLocator *pWbemLocator,
|
|
LPWSTR szSid, LPWSTR szNameSpace);
|
|
|
|
//*************************************************************
|
|
// TranslateNameXForest
|
|
|
|
DWORD DsNameErrorMap[] = { ERROR_SUCCESS,
|
|
ERROR_NO_SUCH_USER,
|
|
ERROR_NO_SUCH_USER,
|
|
ERROR_NONE_MAPPED,
|
|
ERROR_NONE_MAPPED,
|
|
ERROR_SOME_NOT_MAPPED,
|
|
ERROR_SOME_NOT_MAPPED
|
|
};
|
|
|
|
#define MapDsNameError( x ) ((x < sizeof( DsNameErrorMap ) / sizeof( DWORD ) ) ? \
|
|
DsNameErrorMap[ x ] : ERROR_GEN_FAILURE )
|
|
|
|
|
|
extern "C" BOOLEAN TranslateNameXForest (
|
|
LPTSTR szDomain, // Domain where the name should be resolved
|
|
LPCTSTR lpAccountName, // object name
|
|
DS_NAME_FORMAT AccountNameFormat, // name format
|
|
DS_NAME_FORMAT DesiredNameFormat, // new name format
|
|
LPTSTR *lpTranslatedName // returned name buffer
|
|
);
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetMachAccountName()
|
|
//
|
|
// Purpose: Gets Machine account name
|
|
//
|
|
// Return: Machine Account
|
|
//
|
|
//*************************************************************
|
|
|
|
LPTSTR GetMachAccountName()
|
|
{
|
|
return MyGetComputerName(NameSamCompatible);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
TranslateNameXForest (
|
|
LPTSTR szDomain, // Domain where the name should be resolved
|
|
LPCTSTR lpAccountName, // object name
|
|
DS_NAME_FORMAT AccountNameFormat, // name format
|
|
DS_NAME_FORMAT DesiredNameFormat, // new name format
|
|
LPTSTR *lpTranslatedName // returned name buffer
|
|
)
|
|
{
|
|
BOOL bRetry = FALSE;
|
|
DWORD dwErr;
|
|
PDOMAIN_CONTROLLER_INFO pDCInfo = NULL;
|
|
HANDLE hDS = NULL;
|
|
XLastError xe;
|
|
PDS_NAME_RESULT pResult = NULL;
|
|
BOOLEAN bRet = FALSE;
|
|
XPtrLF<WCHAR> xszTransName;
|
|
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"MyTranslateName: Resolving name <%s> at Domain <%s>", lpAccountName, szDomain ? szDomain : L"");
|
|
|
|
|
|
//
|
|
// get a DC and bind to it. Make sure to force rediscover a DC if the bind fails
|
|
//
|
|
|
|
|
|
for (;;) {
|
|
|
|
dwErr = DsGetDcName( NULL,
|
|
szDomain ? szDomain : L"",
|
|
NULL,
|
|
NULL,
|
|
DS_DIRECTORY_SERVICE_REQUIRED |
|
|
DS_RETURN_DNS_NAME |
|
|
(bRetry ? DS_FORCE_REDISCOVERY : 0) |
|
|
0,
|
|
&pDCInfo );
|
|
|
|
if (dwErr == NO_ERROR) {
|
|
dwErr = DsBind( pDCInfo->DomainControllerName,
|
|
NULL,
|
|
&hDS );
|
|
|
|
if (dwErr == NO_ERROR) {
|
|
break;
|
|
}
|
|
else {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: Failed to bind to DC <%s> with error %d",
|
|
pDCInfo->DomainControllerName, dwErr );
|
|
NetApiBufferFree(pDCInfo);
|
|
pDCInfo = NULL;
|
|
}
|
|
|
|
}
|
|
else {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: Failed to get DC for domain <%s> with error %d",
|
|
szDomain ? szDomain : L"", dwErr );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Failed to bind to a DC. bail
|
|
//
|
|
|
|
if (bRetry) {
|
|
xe = dwErr;
|
|
goto Exit;
|
|
}
|
|
|
|
bRetry = TRUE;
|
|
}
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"MyTranslateName: DC selected is <%s>", pDCInfo->DomainControllerName);
|
|
|
|
|
|
//
|
|
// Now crack names with the DC that is bound
|
|
//
|
|
|
|
dwErr = DsCrackNames( hDS,
|
|
DS_NAME_NO_FLAGS,
|
|
AccountNameFormat,
|
|
DesiredNameFormat,
|
|
1,
|
|
&lpAccountName,
|
|
&pResult);
|
|
|
|
if (dwErr != DS_NAME_NO_ERROR) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: Failed to crack names with error %d", dwErr );
|
|
xe = dwErr;
|
|
goto Exit;
|
|
}
|
|
|
|
if ( pResult->cItems == 0 ) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: Failed to return enough result items" );
|
|
xe = dwErr = ERROR_INVALID_DATA;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
if ( pResult->rItems[0].status == DS_NAME_NO_ERROR ) {
|
|
|
|
//
|
|
// In case of no error, return the resolved name
|
|
//
|
|
DWORD dwTransNameLength = 1 + lstrlen(pResult->rItems[0].pName);
|
|
xszTransName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * ( dwTransNameLength ));
|
|
|
|
if (!xszTransName) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: Failed to allocate memory for domain" );
|
|
xe = dwErr = GetLastError();
|
|
goto Exit;
|
|
}
|
|
|
|
HRESULT hr = StringCchCopy(xszTransName, dwTransNameLength, pResult->rItems[0].pName);
|
|
|
|
if(FAILED(hr)) {
|
|
xe = dwErr = HRESULT_CODE(hr);
|
|
goto Exit;
|
|
}
|
|
|
|
*lpTranslatedName = xszTransName.Acquire();
|
|
}
|
|
else {
|
|
|
|
//
|
|
// remap the error code to win32 error
|
|
//
|
|
|
|
xe = dwErr = MapDsNameError(pResult->rItems[0].status);
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"MyTranslateName: DsCrackNames failed with error %d", pResult->rItems[0].status );
|
|
goto Exit;
|
|
}
|
|
|
|
bRet = TRUE;
|
|
|
|
Exit:
|
|
if ( pDCInfo ) {
|
|
NetApiBufferFree(pDCInfo);
|
|
}
|
|
|
|
if (hDS) {
|
|
DsUnBind( &hDS );
|
|
}
|
|
|
|
if (pResult) {
|
|
DsFreeNameResult(pResult);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// GetSOMFromSID()
|
|
//
|
|
// Purpose: Finds out the FQDN of a given user/computer given the SID
|
|
// It reads from the cache that we have already maintained
|
|
//
|
|
// Parameters: szSID - User Sid or NULL for machine account
|
|
//
|
|
// Return: SOM, NULL otherwise. GetLastError() for details
|
|
// This just returns the DN of the user
|
|
//
|
|
//*************************************************************
|
|
|
|
LPWSTR GetSOMFromSID(LPWSTR szSID)
|
|
{
|
|
BOOL bMachine = FALSE;
|
|
HRESULT hr = S_OK;
|
|
XLastError xe;
|
|
XPtrLF<WCHAR> xszName;
|
|
XPtrLF<WCHAR> xszFinalName;
|
|
DWORD dwError, dwType, dwSize;
|
|
XKey xhKeyState;
|
|
XPtrLF<WCHAR> xszKeyState;
|
|
XPtrLF<WCHAR> xszMachAccount;
|
|
XPtrLF<WCHAR> xszDomain;
|
|
DWORD dwKeyStateLength = lstrlen(GP_STATE_KEY) + lstrlen(szSID ? szSID : L"Machine") + 1;
|
|
|
|
xszKeyState = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * ( dwKeyStateLength ));
|
|
|
|
if (!xszKeyState) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Failed to allocate memory. Error - %d", GetLastError() );
|
|
xe = GetLastError();
|
|
return NULL;
|
|
}
|
|
|
|
if ( !szSID )
|
|
{
|
|
bMachine = TRUE;
|
|
hr = StringCchPrintf( xszKeyState, dwKeyStateLength, GP_STATE_KEY, L"Machine" );
|
|
}
|
|
else
|
|
{
|
|
hr = StringCchPrintf( xszKeyState, dwKeyStateLength, GP_STATE_KEY, szSID );
|
|
}
|
|
|
|
if (FAILED(hr)) {
|
|
xe = HRESULT_CODE(hr);
|
|
return NULL;
|
|
}
|
|
|
|
dwSize = 0;
|
|
dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
xszKeyState,
|
|
0,
|
|
KEY_READ,
|
|
&xhKeyState );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Failed to open state key for %s. Error - %d", (LPWSTR)xszKeyState, dwError );
|
|
xe = dwError;
|
|
return NULL;
|
|
}
|
|
|
|
dwError = RegQueryValueEx(xhKeyState,
|
|
DN,
|
|
0,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Failed to get the size of DN value. Error - %d", dwError );
|
|
xe = dwError;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
xszName = (LPWSTR)LocalAlloc(LPTR, dwSize+2);
|
|
|
|
if ( !xszName ) {
|
|
xe = GetLastError();
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Failed to get the size of DN value. Error - %d", GetLastError() );
|
|
return NULL;
|
|
}
|
|
|
|
dwError = RegQueryValueEx(xhKeyState,
|
|
DN,
|
|
0,
|
|
&dwType,
|
|
(LPBYTE)(LPWSTR)xszName,
|
|
&dwSize );
|
|
|
|
if ( dwError != ERROR_SUCCESS )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Failed to get the size of DN value. Error - %d", dwError );
|
|
xe = dwError;
|
|
return NULL;
|
|
}
|
|
|
|
if (xszName[0] == L'\0') {
|
|
xe = ERROR_NON_DOMAIN_SID;
|
|
return NULL;
|
|
}
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"GetSOMFromSID: Som for SID <%s> in registry is %s.", szSID ? szSID : L"Machine", (LPWSTR)xszName );
|
|
|
|
|
|
//
|
|
// Confirming that the SOMs haven't changed since the last time the user was logged on
|
|
// get the domain and requery for the som
|
|
//
|
|
|
|
dwError = GetDomain(xszName, &xszDomain);
|
|
if (dwError != ERROR_SUCCESS) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Cannot get the domain from the som path. Error - %d", dwError );
|
|
xe = dwError;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if (bMachine) {
|
|
xszMachAccount = GetMachAccountName();
|
|
|
|
if (!xszMachAccount) {
|
|
xe = GetLastError();
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Couldn't get the machine account. Error - %d", GetLastError() );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
if (!TranslateNameXForest( xszDomain, xszMachAccount, DS_NT4_ACCOUNT_NAME, DS_FQDN_1779_NAME, &xszFinalName)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Translate name failed for machine account. Error - %d", GetLastError() );
|
|
}
|
|
else {
|
|
xszName = xszFinalName.Acquire();
|
|
}
|
|
|
|
}
|
|
else {
|
|
if (!TranslateNameXForest( xszDomain, szSID, DS_SID_OR_SID_HISTORY_NAME, DS_FQDN_1779_NAME, &xszFinalName)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, L"GetSOMFromSID: Translate name failed for user account. Error - %d", GetLastError() );
|
|
}
|
|
else {
|
|
xszName = xszFinalName.Acquire();
|
|
}
|
|
}
|
|
|
|
return xszName.Acquire();
|
|
}
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// CheckRsopDiagPolicyInteractive()
|
|
//
|
|
// Purpose: Can this user get the rsop data even if the user is logged
|
|
// on interactively
|
|
//
|
|
// Parameters:
|
|
//
|
|
// Return: CheckRsopDiagPolicyInteractive
|
|
//
|
|
//*************************************************************
|
|
|
|
BOOL CheckRsopDiagPolicyInteractive()
|
|
{
|
|
HKEY hKeyUser = NULL;
|
|
HKEY hKey;
|
|
DWORD dwSize = 0, dwType = 0;
|
|
BOOL bDeny = FALSE;
|
|
|
|
HRESULT hr = CoImpersonateClient();
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CheckRsopDiagPolicyInteractive::CoImpersonateClient failed with 0x%x"), hr );
|
|
}
|
|
else if (!RegOpenCurrentUser(KEY_READ, &hKeyUser) == ERROR_SUCCESS)
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CheckRsopDiagPolicyInteractive:: couldn't access registry of interactive user."));
|
|
hKeyUser = NULL;
|
|
}
|
|
CoRevertToSelf();
|
|
|
|
|
|
//
|
|
// First, check for a user preference
|
|
//
|
|
|
|
if (hKeyUser) {
|
|
if (RegOpenKeyEx (hKeyUser, WINLOGON_KEY, 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(bDeny);
|
|
RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
|
|
(LPBYTE) &bDeny, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Check for a machine preference
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, WINLOGON_KEY, 0,
|
|
KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(bDeny);
|
|
RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
|
|
(LPBYTE) &bDeny, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
|
|
//
|
|
// Check for a user policy
|
|
//
|
|
|
|
if (hKeyUser) {
|
|
if (RegOpenKeyEx (hKeyUser, SYSTEM_POLICIES_KEY, 0,
|
|
KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(bDeny);
|
|
RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
|
|
(LPBYTE) &bDeny, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check for a machine policy
|
|
//
|
|
|
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, SYSTEM_POLICIES_KEY, 0,
|
|
KEY_READ, &hKey) == ERROR_SUCCESS) {
|
|
|
|
dwSize = sizeof(bDeny);
|
|
RegQueryValueEx (hKey, DENY_RSOP_FROM_INTERACTIVE_USER, NULL, &dwType,
|
|
(LPBYTE) &bDeny, &dwSize);
|
|
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
if (hKeyUser) {
|
|
RegCloseKey(hKeyUser);
|
|
}
|
|
|
|
return (!bDeny);
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// Functions: Constructor, Destructor, QueryInterface, AddRef, Release
|
|
//
|
|
//*************************************************************
|
|
|
|
CSnapProv::CSnapProv()
|
|
: m_cRef(1),
|
|
m_bInitialized(false),
|
|
m_pNamespace(NULL)
|
|
{
|
|
InterlockedIncrement(&g_cObj);
|
|
|
|
m_xbstrUserSid = L"userSid";
|
|
if ( !m_xbstrUserSid )
|
|
return;
|
|
|
|
m_xbstrUserSids = L"userSids";
|
|
if ( !m_xbstrUserSids )
|
|
return;
|
|
|
|
m_xbstrNameSpace = L"nameSpace";
|
|
if ( !m_xbstrNameSpace )
|
|
return;
|
|
|
|
m_xbstrResult = L"hResult";
|
|
if ( !m_xbstrResult )
|
|
return;
|
|
|
|
m_xbstrFlags = L"flags";
|
|
if ( !m_xbstrFlags )
|
|
return;
|
|
|
|
m_xbstrExtendedInfo = L"ExtendedInfo";
|
|
if ( !m_xbstrExtendedInfo )
|
|
return;
|
|
|
|
m_xbstrClass = L"RsopLoggingModeProvider";
|
|
if ( !m_xbstrClass )
|
|
return;
|
|
|
|
m_bInitialized = TRUE;
|
|
}
|
|
|
|
|
|
CSnapProv::~CSnapProv()
|
|
{
|
|
if(m_pNamespace != NULL)
|
|
{
|
|
m_pNamespace->Release();
|
|
}
|
|
|
|
InterlockedDecrement(&g_cObj);
|
|
}
|
|
|
|
STDMETHODIMP CSnapProv::QueryInterface (REFIID riid, LPVOID* ppv)
|
|
{
|
|
if(riid == IID_IUnknown || riid == IID_IWbemServices)
|
|
{
|
|
*ppv = static_cast<IWbemServices*>(this);
|
|
}
|
|
else if(riid == IID_IWbemProviderInit)
|
|
{
|
|
*ppv = static_cast<IWbemProviderInit*>(this);
|
|
}
|
|
else
|
|
{
|
|
*ppv=NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CSnapProv::AddRef()
|
|
{
|
|
return InterlockedIncrement( &m_cRef );
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CSnapProv::Release()
|
|
{
|
|
if (!InterlockedDecrement(&m_cRef))
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
//*************************************************************
|
|
//
|
|
// Initialize()
|
|
//
|
|
// Purpose: WbemProvider's initialize method
|
|
//
|
|
// Parameters: See IWbemProivderInit::Initialize
|
|
//
|
|
// Return: hresult
|
|
//
|
|
//*************************************************************
|
|
|
|
STDMETHODIMP CSnapProv::Initialize( LPWSTR pszUser,
|
|
LONG lFlags,
|
|
LPWSTR pszNamespace,
|
|
LPWSTR pszLocale,
|
|
IWbemServices __RPC_FAR *pNamespace,
|
|
IWbemContext __RPC_FAR *pCtx,
|
|
IWbemProviderInitSink __RPC_FAR *pInitSink)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( !m_bInitialized ) {
|
|
hr = pInitSink->SetStatus(E_FAIL, 0);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// No need to authenticate user. The ACLs on Rsop namespace will
|
|
// deny access to users that cannot snapshot diagnostic mode data.
|
|
//
|
|
|
|
m_pNamespace = pNamespace;
|
|
m_pNamespace->AddRef();
|
|
|
|
hr = pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
#if _MSC_FULL_VER <= 13008827 && defined(_M_IX86)
|
|
#pragma optimize("", off)
|
|
#endif
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// ExecMethodAsync()
|
|
//
|
|
// Purpose: Execute method
|
|
//
|
|
// Parameters: See IWbemServices::ExecMethodAsync
|
|
//
|
|
// Return: hresult
|
|
//
|
|
//*************************************************************
|
|
|
|
STDMETHODIMP CSnapProv::ExecMethodAsync( const BSTR bstrObject,
|
|
const BSTR bstrMethod,
|
|
long lFlags,
|
|
IWbemContext __RPC_FAR *pCtx,
|
|
IWbemClassObject __RPC_FAR *pInParams,
|
|
IWbemObjectSink __RPC_FAR *pResponseHandler)
|
|
{
|
|
HRESULT hr;
|
|
|
|
CFailRetStatus retStatus( pResponseHandler );
|
|
IUnknown *pOldSecContext;
|
|
|
|
//
|
|
// Make sure the provider is properly initialized
|
|
//
|
|
|
|
//
|
|
// Allow for debugging level to be dynamically changed during queries
|
|
//
|
|
|
|
|
|
dbgRsop.Initialize( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon",
|
|
L"RsopDebugLevel",
|
|
L"userenv.log",
|
|
L"userenv.bak",
|
|
FALSE );
|
|
|
|
InitDebugSupport(0);
|
|
|
|
if ( !m_bInitialized )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Initialize the return status object to fail status
|
|
//
|
|
|
|
IWbemLocator *pWbemLocator = NULL;
|
|
hr = CoCreateInstance( CLSID_WbemAuthenticatedLocator,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID *) &pWbemLocator );
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync: CoCreateInstance returned 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
XInterface<IWbemLocator> xLocator( pWbemLocator );
|
|
|
|
IWbemClassObject* pProvClass = NULL;
|
|
IWbemClassObject* pOutClass = NULL;
|
|
IWbemClassObject* pOutParams = NULL;
|
|
|
|
hr = m_pNamespace->GetObject( m_xbstrClass, 0, pCtx, &pProvClass, NULL);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetObject failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
XInterface<IWbemClassObject> xProvClass( pProvClass );
|
|
|
|
hr = pProvClass->GetMethod( bstrMethod, 0, NULL, &pOutClass);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetMethod failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
XInterface<IWbemClassObject> xOutClass( pOutClass );
|
|
|
|
hr = pOutClass->SpawnInstance(0, &pOutParams);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::SpawnInstance failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Get the tokens and Sids upfront
|
|
//
|
|
|
|
XPtrLF <WCHAR> xszSidString;
|
|
XPtrLF <SID> xSid;
|
|
XHandle xUserToken;
|
|
|
|
hr = CoImpersonateClient();
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
if (OpenThreadToken (GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &xUserToken)) {
|
|
|
|
|
|
LPWSTR szSid = GetSidString(xUserToken);
|
|
if (!szSid) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetSidString failed with %d"), GetLastError() );
|
|
CoRevertToSelf();
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
else {
|
|
DWORD szSidStrLength = lstrlen(szSid) + 1;
|
|
xszSidString = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * ( szSidStrLength ));
|
|
|
|
if (!xszSidString) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::LocalAlloc failed with %d"), GetLastError() );
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DeleteSidString(szSid);
|
|
CoRevertToSelf();
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = StringCchCopy(xszSidString, szSidStrLength, szSid);
|
|
|
|
if(FAILED(hr)){
|
|
DeleteSidString(szSid);
|
|
CoRevertToSelf();
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
DeleteSidString(szSid);
|
|
}
|
|
|
|
|
|
xSid = (SID *)GetUserSid(xUserToken);
|
|
if (!xSid) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetUserSid failed with %d"), GetLastError() );
|
|
CoRevertToSelf();
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
} else {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Openthreadtoken failed with 0x%x"), hr );
|
|
CoRevertToSelf();
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
CoRevertToSelf();
|
|
|
|
|
|
XInterface<IWbemClassObject> xOutParams( pOutParams );
|
|
|
|
if ( _wcsicmp( (WCHAR *) bstrMethod, L"RsopDeleteSession" ) == 0 ) {
|
|
|
|
//
|
|
// rsopdeletesession
|
|
//
|
|
|
|
VARIANT vNameSpace;
|
|
hr = pInParams->Get( m_xbstrNameSpace, 0, &vNameSpace, NULL, NULL);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get machine name failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
XVariant xvNameSpace( &vNameSpace );
|
|
|
|
|
|
if (vNameSpace.vt != VT_NULL ) {
|
|
|
|
//
|
|
// We want to run as LS
|
|
//
|
|
|
|
hr = CoSwitchCallContext(NULL, &pOldSecContext);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = ProviderDeleteRsopNameSpace( pWbemLocator,
|
|
vNameSpace.bstrVal,
|
|
xUserToken,
|
|
xszSidString,
|
|
SETUP_NS_SM);
|
|
|
|
|
|
IUnknown *pNewObject;
|
|
HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
|
|
|
|
if (FAILED(hr2)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
|
|
}
|
|
}
|
|
else {
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
|
|
VARIANT var;
|
|
var.vt = VT_I4;
|
|
var.lVal = hr;
|
|
|
|
hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = pResponseHandler->Indicate(1, &pOutParams);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
else if ( _wcsicmp( (WCHAR *) bstrMethod, L"RsopEnumerateUsers" ) == 0 )
|
|
{
|
|
|
|
//
|
|
// RsopenumerateUsers
|
|
//
|
|
|
|
SAFEARRAY *pArray;
|
|
|
|
hr = EnumerateUserNameSpace( pWbemLocator, xUserToken, &pArray );
|
|
|
|
XSafeArray xsaUserSids(pArray);
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::EnumerateUserNameSpace failed") );
|
|
}
|
|
|
|
VARIANT var;
|
|
var.vt = VT_I4;
|
|
var.lVal = hr;
|
|
|
|
hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
var.vt = VT_ARRAY | VT_BSTR;
|
|
var.parray = xsaUserSids;
|
|
|
|
hr = pOutParams->Put( m_xbstrUserSids, 0, &var, 0 );
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put sids failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
hr = pResponseHandler->Indicate(1, &pOutParams);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// progress indicator.
|
|
// 25% done when we enter the first critical section.
|
|
// 50% done when we enter the second critical section.
|
|
// 100% complete when we copy the namespace.
|
|
//
|
|
|
|
CProgressIndicator Indicator( pResponseHandler,
|
|
(lFlags & WBEM_FLAG_SEND_STATUS) != 0 );
|
|
|
|
//
|
|
// 5% done. Hack for UI.
|
|
//
|
|
|
|
hr = Indicator.IncrementBy( 5 );
|
|
|
|
VARIANT vUserSid;
|
|
hr = pInParams->Get( m_xbstrUserSid, 0, &vUserSid, NULL, NULL);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get RemoteComputer failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
XVariant xvUserSid ( &vUserSid );
|
|
|
|
|
|
VARIANT vFlags;
|
|
VariantInit( &vFlags );
|
|
hr = pInParams->Get( m_xbstrFlags, 0, &vFlags, NULL, NULL);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get dwFlags failed with 0x%x."), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
DWORD dwFlags = vFlags.vt == VT_EMPTY || vFlags.vt == VT_NULL ? 0 : vFlags.ulVal;
|
|
|
|
//
|
|
// Flags specific to Diagnostic mode provider
|
|
//
|
|
|
|
if ((dwFlags & FLAG_NO_USER) && (dwFlags & FLAG_NO_COMPUTER)) {
|
|
hr = WBEM_E_INVALID_PARAMETER;
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Both user and computer are null."));
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// We can dump out all the input parameters here later on.
|
|
//
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------"));
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::UserSid = <%s>"), vUserSid.vt == VT_NULL ? L"NULL" : vUserSid.bstrVal);
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::flags = <%d>"), dwFlags);
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------"));
|
|
|
|
|
|
//
|
|
// Code for RsopCreateSession method
|
|
//
|
|
|
|
|
|
|
|
XPtrLF<TCHAR> xszMachSOM;
|
|
XPtrLF<TCHAR> xszUserSOM;
|
|
BOOL bDelegated = FALSE;
|
|
BOOL bCheckAccess = TRUE;
|
|
DWORD dwExtendedInfo = 0;
|
|
|
|
|
|
//
|
|
// Get the machine SOM
|
|
//
|
|
|
|
if ( !(dwFlags & FLAG_NO_COMPUTER) ) {
|
|
|
|
dwExtendedInfo |= RSOP_COMPUTER_ACCESS_DENIED;
|
|
|
|
xszMachSOM = GetSOMFromSID(NULL);
|
|
|
|
if (xszMachSOM) {
|
|
dwExtendedInfo &= ~RSOP_COMPUTER_ACCESS_DENIED;
|
|
}
|
|
else {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No machine SOM. error %d"), GetLastError() );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get the User SOM
|
|
//
|
|
|
|
if ( !(dwFlags & FLAG_NO_USER) ) {
|
|
|
|
dwExtendedInfo |= RSOP_USER_ACCESS_DENIED;
|
|
|
|
xszUserSOM = GetSOMFromSID(vUserSid.vt == VT_NULL ? xszSidString : vUserSid.bstrVal);
|
|
|
|
if (xszUserSOM) {
|
|
dwExtendedInfo &= ~RSOP_USER_ACCESS_DENIED;
|
|
}
|
|
else {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No User SOM. error %d"), GetLastError() );
|
|
}
|
|
}
|
|
|
|
// at this point we already know whether to treat the user as delegated or not...
|
|
if (!xszMachSOM && !xszUserSOM)
|
|
{
|
|
bCheckAccess = FALSE;
|
|
}
|
|
|
|
//
|
|
// Check access now
|
|
//
|
|
|
|
if (bCheckAccess) {
|
|
hr = AuthenticateUser(xUserToken, xszMachSOM, xszUserSOM, TRUE, &dwExtendedInfo);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is not a delegated admin. Error 0x%x"), hr );
|
|
hr = S_OK;
|
|
}
|
|
else {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is a delegated admin. Error 0x%x"), hr );
|
|
}
|
|
}
|
|
|
|
if ((!(dwExtendedInfo & RSOP_USER_ACCESS_DENIED)) &&
|
|
(!(dwExtendedInfo & RSOP_COMPUTER_ACCESS_DENIED)))
|
|
{
|
|
bDelegated = TRUE;
|
|
}
|
|
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecMethodAsync::Getting policy critical sections"));
|
|
|
|
XCriticalPolicySection criticalPolicySectionMACHINE( EnterCriticalPolicySectionEx(TRUE, 40000, ECP_FAIL_ON_WAIT_TIMEOUT) );
|
|
|
|
if ( !criticalPolicySectionMACHINE )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// 25% done when we enter the first critical section.
|
|
//
|
|
|
|
hr = Indicator.IncrementBy( 20 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
|
|
}
|
|
|
|
|
|
XCriticalPolicySection criticalPolicySectionUSER( EnterCriticalPolicySectionEx(FALSE, 40000, ECP_FAIL_ON_WAIT_TIMEOUT) );
|
|
|
|
if ( !criticalPolicySectionUSER )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( GetLastError() );
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// 50% done when we enter the second critical section.
|
|
//
|
|
hr = Indicator.IncrementBy( 25 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
|
|
}
|
|
|
|
|
|
LPWSTR wszNameSpace = 0;
|
|
|
|
|
|
//
|
|
// Impersonate if not delegated
|
|
//
|
|
|
|
if (!bDelegated) {
|
|
hr = CoImpersonateClient();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
}
|
|
else {
|
|
|
|
//
|
|
// We want to run as LS
|
|
//
|
|
|
|
hr = CoSwitchCallContext(NULL, &pOldSecContext);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
|
|
XPtrLF<WCHAR> xwszNameSpace;
|
|
|
|
DWORD dwNewNameSpaceFlags = SETUP_NS_SM;
|
|
|
|
dwNewNameSpaceFlags |= (dwFlags & FLAG_NO_USER) ? SETUP_NS_SM_NO_USER : 0;
|
|
dwNewNameSpaceFlags |= (dwFlags & FLAG_NO_COMPUTER) ? SETUP_NS_SM_NO_COMPUTER : 0;
|
|
|
|
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::UserSid = <%s>"), vUserSid.vt == VT_NULL ? L"NULL" : vUserSid.bstrVal);
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User who is running the tool = <%s>"), (LPWSTR)xszSidString);
|
|
|
|
hr = SetupNewNameSpace( &xwszNameSpace,
|
|
0, // namespace on this machine
|
|
(vUserSid.vt == VT_NULL) ? ((LPWSTR)xszSidString) : vUserSid.bstrVal,
|
|
xSid,
|
|
pWbemLocator,
|
|
dwNewNameSpaceFlags,
|
|
&dwExtendedInfo);
|
|
|
|
if (!bDelegated) {
|
|
CoRevertToSelf();
|
|
}
|
|
else {
|
|
|
|
//
|
|
// restore call context
|
|
//
|
|
|
|
IUnknown *pNewObject;
|
|
HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
|
|
|
|
if (FAILED(hr2)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ( FAILED(hr) && !bDelegated)
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::SetupNewNameSpace failed with 0x%x"), hr );
|
|
|
|
if (IsUserAnInteractiveUser(xUserToken) && CheckRsopDiagPolicyInteractive()) {
|
|
|
|
// if the user had permissions on the computer or if the user didn't ask for computer
|
|
// continue
|
|
|
|
// clear out the user access denied right in any case.
|
|
dwExtendedInfo &= ~RSOP_USER_ACCESS_DENIED;
|
|
|
|
if ( (!(dwExtendedInfo & RSOP_COMPUTER_ACCESS_DENIED)) ||
|
|
(dwFlags & FLAG_NO_COMPUTER) ) {
|
|
|
|
// if the user asked for their own rsop data
|
|
if ( (vUserSid.vt == VT_NULL) || (_wcsicmp(vUserSid.bstrVal, xszSidString) == 0 )) {
|
|
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::SetupNewNameSpace failed. retrying in interactive mode"), hr );
|
|
|
|
|
|
//
|
|
// We want to run as LS
|
|
//
|
|
|
|
hr = CoSwitchCallContext(NULL, &pOldSecContext);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// if the namespace is null, get the name of the interactive namespace
|
|
//
|
|
|
|
XPtrLF<WCHAR> xszInteractiveNS;
|
|
|
|
hr = GetInteractiveNameSpace(xszSidString, &xszInteractiveNS);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
BOOL bContinue=TRUE;
|
|
|
|
if (dwFlags & FLAG_FORCE_CREATENAMESPACE) {
|
|
hr = DeleteRsopNameSpace( xszInteractiveNS, pWbemLocator );
|
|
// ignore error
|
|
}
|
|
else {
|
|
XInterface<IWbemServices> xWbemServices;
|
|
|
|
hr = pWbemLocator->ConnectServer( xszInteractiveNS,
|
|
NULL,
|
|
NULL,
|
|
0L,
|
|
0L,
|
|
NULL,
|
|
NULL,
|
|
&xWbemServices );
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Namespace already exists. Failing call"));
|
|
hr = WBEM_E_ALREADY_EXISTS;
|
|
dwExtendedInfo = RSOP_TEMPNAMESPACE_EXISTS;
|
|
bContinue = FALSE;
|
|
}
|
|
}
|
|
|
|
if (bContinue) {
|
|
dwNewNameSpaceFlags |= SETUP_NS_SM_INTERACTIVE;
|
|
|
|
hr = SetupNewNameSpace( &xwszNameSpace,
|
|
0, // namespace on this machine
|
|
xszSidString,
|
|
xSid,
|
|
pWbemLocator,
|
|
dwNewNameSpaceFlags,
|
|
&dwExtendedInfo);
|
|
|
|
}
|
|
|
|
//
|
|
// restore call context
|
|
//
|
|
|
|
IUnknown *pNewObject;
|
|
HRESULT hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
|
|
|
|
if (FAILED(hr2)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::SetupNewNameSpace failed with 0x%x"), hr );
|
|
}
|
|
else
|
|
{
|
|
HRESULT hr2;
|
|
VARIANT var;
|
|
//
|
|
// if we managed to get a snapshot, then ignore the extended access denied info
|
|
//
|
|
|
|
dwExtendedInfo = 0;
|
|
|
|
|
|
//
|
|
// We want to run as LS
|
|
//
|
|
|
|
hr = CoSwitchCallContext(NULL, &pOldSecContext);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
if ( !(dwFlags & FLAG_NO_COMPUTER) ) {
|
|
|
|
hr = UpdateGPCoreStatus(pWbemLocator, NULL, xwszNameSpace);
|
|
}
|
|
|
|
if ( (SUCCEEDED(hr)) && (!(dwFlags & FLAG_NO_USER)) ) {
|
|
hr = UpdateGPCoreStatus(pWbemLocator,
|
|
vUserSid.vt == VT_NULL ? xszSidString : vUserSid.bstrVal,
|
|
xwszNameSpace);
|
|
|
|
}
|
|
|
|
//
|
|
// restore call context
|
|
//
|
|
|
|
IUnknown *pNewObject;
|
|
hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
|
|
|
|
if (FAILED(hr2)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
|
|
}
|
|
|
|
|
|
//
|
|
// Return the error code if the status cannot be updated..
|
|
//
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::UpdateGPCoreStatus failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
XBStr xbstrNS( xwszNameSpace );
|
|
if ( !xbstrNS )
|
|
{
|
|
hr2 = HRESULT_FROM_WIN32( E_OUTOFMEMORY );
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Memory allocate failed") );
|
|
retStatus.SetError( hr2 );
|
|
return hr2;
|
|
}
|
|
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = xbstrNS;
|
|
hr2 = pOutParams->Put( m_xbstrNameSpace, 0, &var, 0);
|
|
if ( FAILED(hr2) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put namespace failed with 0x%x"), hr );
|
|
retStatus.SetError( hr2 );
|
|
return hr2;
|
|
}
|
|
}
|
|
|
|
|
|
VARIANT var;
|
|
var.vt = VT_I4;
|
|
var.lVal = hr;
|
|
|
|
hr = pOutParams->Put( m_xbstrResult, 0, &var, 0);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
var.lVal = dwExtendedInfo;
|
|
hr = pOutParams->Put( m_xbstrExtendedInfo, 0, &var, 0);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put result failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// 100% complete when we copy the namespace.
|
|
//
|
|
hr = Indicator.SetComplete();
|
|
if ( FAILED( hr ) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::IncrementBy() failed with 0x%x"), hr );
|
|
}
|
|
|
|
hr = pResponseHandler->Indicate(1, &pOutParams);
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Indicate failed with 0x%x"), hr );
|
|
retStatus.SetError( hr );
|
|
return hr;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
#if _MSC_FULL_VER <= 13008827 && defined(_M_IX86)
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
|
|
|
|
//*************************************************************
|
|
//
|
|
// EnumerateUserNameSpace()
|
|
//
|
|
// Purpose: EnumerateUserNameSpace
|
|
//
|
|
// Parameters:
|
|
// pWbemLocator - Pointer to a locator
|
|
// [out] psaUserSids - Pointer to User Sids
|
|
//
|
|
// Return: hresult
|
|
//
|
|
//*************************************************************
|
|
|
|
typedef struct _UserSidList {
|
|
LPWSTR szUserSid;
|
|
struct _UserSidList *pNext;
|
|
} USERSIDLIST, *PUSERSIDLIST;
|
|
|
|
HRESULT EnumerateUserNameSpace( IWbemLocator *pWbemLocator, HANDLE hToken, SAFEARRAY **psaUserSids )
|
|
{
|
|
USERSIDLIST SidList = {0,0};
|
|
DWORD dwNum = 0;
|
|
PUSERSIDLIST pElem = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwExtendedInfo;
|
|
IUnknown *pOldSecContext;
|
|
|
|
//
|
|
// Connect to namespace ROOT\RSOP\User
|
|
//
|
|
|
|
*psaUserSids = NULL;
|
|
|
|
XInterface<IWbemServices>xpWbemServices = NULL;
|
|
|
|
XBStr xbstrNamespace = RSOP_NS_DIAG_USERROOT;
|
|
|
|
if(!xbstrNamespace)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pWbemLocator->ConnectServer(xbstrNamespace,
|
|
NULL,
|
|
NULL,
|
|
0L,
|
|
0L,
|
|
NULL,
|
|
NULL,
|
|
&xpWbemServices);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: ConnectServer failed. hr=0x%x" ), hr ));
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// Enumerate all instances of __namespace at the root\rsop\user level.
|
|
//
|
|
|
|
XInterface<IEnumWbemClassObject> xpEnum;
|
|
XBStr xbstrClass = L"__namespace";
|
|
if(!xbstrClass)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = xpWbemServices->CreateInstanceEnum( xbstrClass,
|
|
WBEM_FLAG_SHALLOW | WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
&xpEnum);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: CreateInstanceEnum failed. hr=0x%x" ), hr ));
|
|
return hr;
|
|
}
|
|
|
|
XBStr xbstrProperty = L"Name";
|
|
if(!xbstrProperty)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
XInterface<IWbemClassObject>xpInstance = NULL;
|
|
ULONG ulReturned = 1;
|
|
|
|
while(1)
|
|
{
|
|
hr = xpEnum->Next( WBEM_NO_WAIT, 1, &xpInstance, &ulReturned);
|
|
if (hr != WBEM_S_NO_ERROR || !ulReturned)
|
|
{
|
|
break;
|
|
}
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
|
|
hr = xpInstance->Get(xbstrProperty, 0L, &var, NULL, NULL);
|
|
xpInstance = NULL;
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: Get failed. hr=0x%x" ), hr ));
|
|
goto Exit; // continue
|
|
}
|
|
|
|
|
|
//
|
|
// Check to see whether user is delegated admin for the user account
|
|
//
|
|
|
|
XPtrLF<WCHAR> xszUserSid = (LPWSTR)LocalAlloc(LPTR, (1+lstrlen(var.bstrVal))*sizeof(WCHAR));
|
|
|
|
if (!xszUserSid) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: AllocMem failed. hr=0x%x" ), hr ));
|
|
goto Exit;
|
|
}
|
|
|
|
ConvertWMINameToSid(var.bstrVal, xszUserSid);
|
|
|
|
//
|
|
// See whether it is a valid Sid
|
|
//
|
|
|
|
PSID pSid = NULL;
|
|
|
|
if (AllocateAndInitSidFromString(xszUserSid, &pSid) != STATUS_SUCCESS ) {
|
|
DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: AllocateAndInitSidFromString - %s is not a valid Sid" ), xszUserSid));
|
|
continue;
|
|
}
|
|
|
|
|
|
if (!IsValidSid(pSid)) {
|
|
DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: %s is not a valid Sid" ), xszUserSid));
|
|
LocalFree(pSid);
|
|
continue;
|
|
}
|
|
|
|
LocalFree(pSid);
|
|
|
|
|
|
//
|
|
// First try to connect to the NameSpace
|
|
//
|
|
|
|
hr = CoImpersonateClient();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient failed with 0x%x"), hr );
|
|
goto Exit;
|
|
}
|
|
|
|
XInterface<IWbemServices> xpChildNamespace = NULL;
|
|
hr = xpWbemServices->OpenNamespace( var.bstrVal,
|
|
0,
|
|
NULL,
|
|
&xpChildNamespace,
|
|
NULL);
|
|
|
|
CoRevertToSelf();
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
IUnknown *pNewObject;
|
|
HRESULT hr2=S_OK;
|
|
BOOL bDelegated = TRUE;
|
|
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("EnumerateUserNameSpace: OpenNamespace returned 0x%x"), hr));
|
|
|
|
//
|
|
// Check whether user has access as LS
|
|
//
|
|
|
|
//
|
|
// We want to run as LS
|
|
//
|
|
|
|
hr = CoSwitchCallContext(NULL, &pOldSecContext);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr );
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
XPtrLF<TCHAR> xszUserSOM;
|
|
|
|
if (bDelegated) {
|
|
xszUserSOM = GetSOMFromSID(xszUserSid);
|
|
if (!xszUserSOM) {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::No User SOM. Probably local account. error %d"), GetLastError() );
|
|
bDelegated = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check access now
|
|
//
|
|
|
|
if (bDelegated) {
|
|
hr = AuthenticateUser(hToken, NULL, xszUserSOM, TRUE, &dwExtendedInfo);
|
|
|
|
if (FAILED(hr)) {
|
|
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::User is not a delegated admin. Error 0x%x"), hr );
|
|
bDelegated = FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// restore call context
|
|
//
|
|
|
|
hr2 = CoSwitchCallContext(pOldSecContext, &pNewObject);
|
|
|
|
if (FAILED(hr2)) {
|
|
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoSwitchCallContext failed with 0x%x"), hr2 );
|
|
}
|
|
|
|
if (!bDelegated) {
|
|
continue;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// For every instance of __namespace under ROOT\RSOP\user
|
|
// convert it to Sid and return
|
|
//
|
|
|
|
pElem = (PUSERSIDLIST)LocalAlloc(LPTR, sizeof(USERSIDLIST));
|
|
|
|
if (!pElem) {
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Couldn't allocate memory Error = GetLastError()" ), GetLastError()));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
pElem->szUserSid = xszUserSid.Acquire();
|
|
|
|
//
|
|
// Attach to the beginning of the list
|
|
//
|
|
|
|
pElem->pNext = SidList.pNext;
|
|
SidList.pNext = pElem;
|
|
dwNum++;
|
|
|
|
VariantClear( &var );
|
|
|
|
}
|
|
|
|
|
|
if(hr != (HRESULT) WBEM_S_FALSE || ulReturned)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Get failed. hr=0x%x" ), hr ));
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Now make the safe array from the list that we got
|
|
//
|
|
|
|
SAFEARRAYBOUND arrayBound[1];
|
|
arrayBound[0].lLbound = 0;
|
|
arrayBound[0].cElements = dwNum;
|
|
|
|
*psaUserSids = SafeArrayCreate( VT_BSTR, 1, arrayBound );
|
|
|
|
if ( *psaUserSids == NULL ) {
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: Failed to allocate memory. Error = %d" ), GetLastError() ));
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// traverse the list
|
|
//
|
|
|
|
DWORD i;
|
|
for (i=0, pElem = SidList.pNext; (i < dwNum); i++, pElem = pElem->pNext) {
|
|
XBStr xbstrUserSid(pElem->szUserSid);
|
|
|
|
hr = SafeArrayPutElement( *psaUserSids, (LONG *)&i, xbstrUserSid);
|
|
|
|
if(FAILED(hr)) {
|
|
DebugMsg((DM_WARNING, TEXT("EnumerateUserNameSpace: SafeArrayPutElement failed. Error = 0x%x" ), hr ));
|
|
goto Exit; // free up the SidList
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
|
|
// free
|
|
for (i=0, pElem = SidList.pNext; (i < dwNum); i++ ) {
|
|
if (pElem->szUserSid)
|
|
LocalFree(pElem->szUserSid);
|
|
|
|
PUSERSIDLIST pTemp = pElem;
|
|
|
|
pElem = pElem->pNext;
|
|
LocalFree(pTemp);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|