//************************************************************* // // Copyright (c)1999 Microsoft Corporation, All Rights Reserved // // gpdas.cpp // // Module: Rsop Planning mode Provider // // History: 11-Jul-99 MickH Created // //************************************************************* #include "stdafx.h" #include "planprov.h" #include "gpdas.h" #include #include #define SECURITY_WIN32 #include #include "userenv.h" #include "userenvp.h" #include "rsopinc.h" #include "rsoputil.h" #include "rsopdbg.h" #include "rsopsec.h" #include "Indicate.h" #include "events.h" #include "gpfilter.h" CDebug dbgRsop( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon", L"RsopDebugLevel", L"gpdas.log", L"gpdas.bak", TRUE ); CDebug dbgCommon( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon", L"RsopDebugLevel", L"gpdas.log", L"gpdas.bak", FALSE ); extern "C" PSID GetUserSid (HANDLE UserToken); class CAutoNetApiBufferFree { private: LPVOID _pV; public: CAutoNetApiBufferFree(LPVOID pV) : _pV(pV) { } ~CAutoNetApiBufferFree() { if (_pV) NetApiBufferFree(_pV); } }; bool SplitName(LPCWSTR pszUser, LPWSTR* ppszUserDomain, LPWSTR* ppszUserName) { if(!pszUser) { return false; } *ppszUserDomain = NULL; *ppszUserName = NULL; wchar_t* p = wcschr(pszUser, L'\\'); if(p) { LONG userDomainLength = (LONG)(p - pszUser); if(!userDomainLength) { return false; } *ppszUserDomain = new wchar_t[userDomainLength + 1]; if(!*ppszUserDomain) { return false; } int userNameLength = wcslen(pszUser) - userDomainLength - 1; *ppszUserName = new wchar_t[userNameLength + 1]; if(!*ppszUserName) { delete[] *ppszUserDomain; *ppszUserDomain = NULL; return false; } wcsncpy(*ppszUserDomain, pszUser, userDomainLength); wcscpy(*ppszUserName, pszUser + userDomainLength + 1); } else { int userNameLength = wcslen(pszUser); *ppszUserName = new wchar_t[userNameLength + 1]; if(!*ppszUserName) { return false; } wcscpy(*ppszUserName, pszUser); *ppszUserDomain = NULL; } return true; } //************************************************************* // // RsopPlanningModeProvider::RsopPlanningModeProvider() // // Purpose: Constructor // //************************************************************* RsopPlanningModeProvider::RsopPlanningModeProvider() : m_pWbemServices(NULL), m_bInitialized(NULL) { _Module.IncrementServiceCount(); m_xbstrMachName = L"computerName"; if ( !m_xbstrMachName ) return; m_xbstrMachSOM = L"computerSOM"; if ( !m_xbstrMachSOM ) return; m_xbstrMachGroups = L"computerSecurityGroups"; if ( !m_xbstrMachGroups ) return; m_xbstrUserName = L"userName"; if ( !m_xbstrUserName ) return; m_xbstrUserSOM = L"userSOM"; if ( !m_xbstrUserSOM ) return; m_xbstrUserGroups = L"userSecurityGroups"; if ( !m_xbstrUserGroups ) return; m_xbstrSite = L"site"; if ( !m_xbstrSite ) return; m_xbstrUserGpoFilter = L"userGPOFilters"; if ( !m_xbstrUserGpoFilter ) return; m_xbstrComputerGpoFilter = L"computerGPOFilters"; if ( !m_xbstrComputerGpoFilter ) return; m_xbstrFlags = L"flags"; if ( !m_xbstrFlags ) return; m_xbstrNameSpace = L"nameSpace"; if ( !m_xbstrNameSpace ) return; m_xbstrResult = L"hResult"; if ( !m_xbstrResult ) return; m_xbstrExtendedInfo = L"ExtendedInfo"; if ( !m_xbstrExtendedInfo ) return; m_xbstrClass = L"RsopPlanningModeProvider"; if ( !m_xbstrClass ) return; // m_xptrInvokerName = 0; m_bInitialized = TRUE; } //************************************************************* // // Initialize() // // Purpose: WbemProvider's initialize method // // Parameters: See IWbemProivderInit::Initialize // // Return: hresult // //************************************************************* STDMETHODIMP RsopPlanningModeProvider::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; } if ( !pszUser ) { hr = pInitSink->SetStatus(E_INVALIDARG, 0); return hr; } if(m_pWbemServices) { m_pWbemServices->Release(); m_pWbemServices = NULL; } m_pWbemServices = pNamespace; m_pWbemServices->AddRef(); hr = CoMarshalInterThreadInterfaceInStream(__uuidof(IWbemServices), m_pWbemServices, &m_pStream); if(SUCCEEDED(hr)) hr = pInitSink->SetStatus(WBEM_S_INITIALIZED, 0); else { m_pWbemServices->Release(); hr = pInitSink->SetStatus(hr, 0); } return hr; } //************************************************************* // // ExecMethodAsync() // // Purpose: Execute method // // Parameters: See IWbemServices::ExecMethodAsync // // Return: hresult // //************************************************************* STDMETHODIMP RsopPlanningModeProvider::ExecMethodAsync( BSTR bstrObject, BSTR bstrMethod, long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams, IWbemObjectSink* pResponseHandler ) { dbgRsop.Initialize( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon", L"RsopDebugLevel", L"gpdas.log", L"gpdas.bak", FALSE ); dbgCommon.Initialize( L"Software\\Microsoft\\Windows NT\\CurrentVersion\\winlogon", L"RsopDebugLevel", L"gpdas.log", L"gpdas.bak", FALSE ); // // Initialize the return status object to fail status // dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecMethodAsync: Entering") ); CFailRetStatus retStatus( pResponseHandler ); HRESULT hr; XInterface xLocator; hr = CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *) &xLocator ); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync: CoCreateInstance returned 0x%x"), hr ); retStatus.SetError( hr ); return hr; } IWbemClassObject* pProvClass = NULL; IWbemClassObject* pOutClass = NULL; IWbemClassObject* pOutParams = NULL; IWbemServices* pWbemServices = NULL; hr = CoGetInterfaceAndReleaseStream(m_pStream, __uuidof(IWbemServices), (void**)&pWbemServices); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoGetInterfaceAndReleaseStream failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } hr = pWbemServices->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 xProvClass( pProvClass ); hr = CoMarshalInterThreadInterfaceInStream(__uuidof(IWbemServices), pWbemServices, &m_pStream); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoMarshallInterThreadInterfaceInStream failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } 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 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; } XInterface xOutParams( pOutParams ); XHandle xhUserToken; { XImpersonate xImp; if ( FAILED( xImp.Status() ) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::CoImpersonateClient() failed with 0x%x."), xImp.Status() ); retStatus.SetError( xImp.Status() ); return xImp.Status(); } if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &xhUserToken)) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Openthreadtoken failed with 0x%x after impersonation."), GetLastError() ); retStatus.SetError( HRESULT_FROM_WIN32(GetLastError()) ); return HRESULT_FROM_WIN32(GetLastError()); } } if ( _wcsicmp( (WCHAR *) bstrMethod, L"RsopDeleteSession" ) == 0 ) { 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 ) hr = E_INVALIDARG; else { hr = ProviderDeleteRsopNameSpace( xLocator, vNameSpace.bstrVal, xhUserToken, NULL, SETUP_NS_PM); } 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; } // // Code for RsopCreateSession method // BOOL bMachineData = TRUE; BOOL bUserData = TRUE; VARIANT vMachName; VariantInit( &vMachName ); hr = pInParams->Get( m_xbstrMachName, 0, &vMachName, 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 xvMachName( &vMachName ); VARIANT vMachSOM; VariantInit( &vMachSOM ); hr = pInParams->Get( m_xbstrMachSOM, 0, &vMachSOM, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get machine SOM failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } if ( vMachSOM.vt == VT_EMPTY || vMachSOM.vt == VT_NULL ) { if ( vMachName.vt == VT_EMPTY || vMachName.vt == VT_NULL ) { dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod:: Machine name and SOM are NULL.")); bMachineData = FALSE; } else { XPtrLF szMachine = LocalAlloc( LPTR, ( wcslen( vMachName.bstrVal ) + 2 ) * sizeof( WCHAR ) ); if ( !szMachine ) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Not enough memory 0x%x."), hr ); retStatus.SetError( hr ); return hr; } wcscpy( szMachine, vMachName.bstrVal ); XBStr xbstrSOM = GetSOM( szMachine ); if ( !xbstrSOM ) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get machine SOM failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } vMachSOM.vt = VT_BSTR; vMachSOM.bstrVal = xbstrSOM.Acquire(); } } CProgressIndicator Indicator( pResponseHandler, (lFlags & WBEM_FLAG_SEND_STATUS) != 0 ); Indicator.IncrementBy( 5 ); // // vMachSOM is going to have at least empty data in it all cases // XVariant xvMachSOM( &vMachSOM ); VARIANT vUserName; VariantInit( &vUserName ); hr = pInParams->Get( m_xbstrUserName, 0, &vUserName, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get user name failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvUserName( &vUserName ); VARIANT vUserSOM; VariantInit( &vUserSOM ); hr = pInParams->Get( m_xbstrUserSOM, 0, &vUserSOM, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get user SOM failed with 0x%x."), GetLastError() ); retStatus.SetError( hr ); return hr; } if ( vUserSOM.vt == VT_EMPTY || vUserSOM.vt == VT_NULL ) { if ( vUserName.vt == VT_EMPTY || vUserName.vt == VT_NULL ) { dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod:: User name and SOM are NULL.")); bUserData = FALSE; } else { XBStr xbstrSOM = GetSOM( vUserName.bstrVal ); if ( !xbstrSOM ) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get user SOM failed with 0x%x."), GetLastError() ); retStatus.SetError( hr ); return hr; } vUserSOM.vt = VT_BSTR; vUserSOM.bstrVal = xbstrSOM.Acquire(); } } // // vUserSOM is going to have at least empty data in it all cases // XVariant xvUserSOM( &vUserSOM ); // // Nothing was asked for.. // if ( (!bMachineData) && (!bUserData) ) { hr = S_OK; dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: User and machine (both name and SOM) are NULL.")); retStatus.SetError( WBEM_E_INVALID_PARAMETER ); return hr; } VARIANT vMachGroups; hr = pInParams->Get( m_xbstrMachGroups, 0, &vMachGroups, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get machine groups failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvMachGroups( &vMachGroups ); VARIANT vUserGroups; hr = pInParams->Get( m_xbstrUserGroups, 0, &vUserGroups, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get user groups failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvUserGroups( &vUserGroups ); VARIANT vSite; hr = pInParams->Get( m_xbstrSite, 0, &vSite, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get site failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvSite( &vSite ); // // Add computer gpo filters // VARIANT vComputerGpoFilter; hr = pInParams->Get( m_xbstrComputerGpoFilter, 0, &vComputerGpoFilter, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get Gpo filter failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvComputerGpoFilter( &vComputerGpoFilter ); dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::Gpo filter:Adding Computer filters") ); CGpoFilter computerGpoFilter; hr = computerGpoFilter.Add( &vComputerGpoFilter ); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Gpo filter:Add failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } // // Add user gpo filters // VARIANT vUserGpoFilter; hr = pInParams->Get( m_xbstrUserGpoFilter, 0, &vUserGpoFilter, NULL, NULL); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Get Gpo filter failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } XVariant xvUserGpoFilter( &vUserGpoFilter ); CGpoFilter userGpoFilter; dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::Gpo filter:Adding User filters") ); hr = userGpoFilter.Add( &vUserGpoFilter ); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Gpo filter:Add failed with 0x%x."), hr ); retStatus.SetError( hr ); return hr; } 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; dwFlags &= ~FLAG_INTERNAL_MASK; if ( dwFlags & FLAG_NO_GPO_FILTER ) { dwFlags |= FLAG_NO_CSE_INVOKE; } // // do some parameter checks // if ((dwFlags & FLAG_LOOPBACK_MERGE) && (dwFlags & FLAG_LOOPBACK_REPLACE)) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Loopback merge and replace, both are specified. failing")); retStatus.SetError( WBEM_E_INVALID_PARAMETER ); return S_OK; } if (dwFlags & FLAG_LOOPBACK_MERGE) { if (!bMachineData || !bUserData) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Loopback mode both user AND computer data needs to be specified")); retStatus.SetError( WBEM_E_INVALID_PARAMETER ); return S_OK; } dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod:: Loopback merge mode specified")); } if (dwFlags & FLAG_LOOPBACK_REPLACE) { if (!bMachineData) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: Loopback mode computer data needs to be specified")); retStatus.SetError( WBEM_E_INVALID_PARAMETER ); return S_OK; } dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod:: Loopback replace mode specified")); } // // Below is a hack... // In case of replace mode, user som or account doesn't need to be supplied... // but we need to fool the rest of the code to think that user data is specified // and desired and we need to access check againt user som alone. // Copy Mach som to user som // if (dwFlags & FLAG_LOOPBACK_REPLACE) { xvUserSOM = NULL; // reinit user som VariantInit( &vUserSOM ); vUserSOM.vt = VT_BSTR; vUserSOM.bstrVal = SysAllocString(vMachSOM.bstrVal); if (!vUserSOM.bstrVal) { retStatus.SetError( hr ); return hr; } xvUserSOM = &vUserSOM; } // // We can dump out all the input parameters here later on. // Currently dumping only remote Computer. // dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------")); dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::dwFlags = 0x%x"), dwFlags); dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("ExecAsyncMethod::---------------RsopCreateSession::Input Parameters--------------------")); // by this point we have finished all param checks. All future errors needs to be // returned in the method specific hResult // // Check for access before entering policy critical section // DWORD dwExtendedInfo = 0; hr = AuthenticateUser( xhUserToken, vMachSOM.vt != VT_NULL ? vMachSOM.bstrVal : 0, vUserSOM.vt != VT_NULL ? vUserSOM.bstrVal : 0, FALSE, &dwExtendedInfo ); if ( FAILED( hr ) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod:: AuthenticateUser() failed with 0x%x."), hr ); } // // Synchronize with garbage collection thread in userenv.dll by acquiring Group Policy critical section // if (SUCCEEDED(hr)) { XCriticalPolicySection criticalPolicySectionMACHINE( EnterCriticalPolicySection(TRUE) ); if(!criticalPolicySectionMACHINE) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection (machine) failed with 0x%x"), hr ); retStatus.SetError( hr ); return hr; } XCriticalPolicySection criticalPolicySectionUSER( EnterCriticalPolicySection(FALSE) ); if( !criticalPolicySectionUSER ) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecMethodAsync::EnterCriticalPolicySection (user) failed with 0x%x"), hr ); retStatus.SetError( hr ); return hr; } XPtrLF xwszNameSpace; XPtrLF xSid = GetUserSid(xhUserToken); if (!xSid) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GetUserSid failed with error %d."), GetLastError() ); return HRESULT_FROM_WIN32(GetLastError()); } hr = SetupNewNameSpace( &xwszNameSpace, 0, // namespace on this machine NULL, xSid, xLocator, SETUP_NS_PM, NULL); if ( FAILED( hr ) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::SetupNewNameSpace failed with 0x%x"), hr ); } else { BOOL bOk; bOk = GenerateRsopPolicy( dwFlags, vMachName.vt == VT_NULL ? 0 : vMachName.bstrVal, vMachSOM.vt == VT_NULL ? 0 : vMachSOM.bstrVal, vMachGroups.vt == VT_NULL ? 0 : vMachGroups.parray, vUserName.vt == VT_NULL ? 0 : vUserName.bstrVal, vUserSOM.vt == VT_NULL ? 0 : vUserSOM.bstrVal, vUserGroups.vt == VT_NULL ? 0 : vUserGroups.parray, vSite.vt == VT_NULL ? 0 : vSite.bstrVal, xwszNameSpace, &Indicator, &computerGpoFilter, &userGpoFilter ); if ( !bOk ) { hr = HRESULT_FROM_WIN32( GetLastError() ); if ( SUCCEEDED( hr ) ) { hr = E_FAIL; } dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::GenerateRsopPolicy failed with 0x%x"), hr ); // CEvents ev(TRUE, EVENT_GENRSOP_FAILED); // ev.AddArg(hr); ev.Report(); HRESULT hrDel = DeleteRsopNameSpace( xwszNameSpace, xLocator ); if ( FAILED( hrDel ) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::DeleteRsopNameSpace failed with 0x%x"), hrDel ); } } else { XBStr xbstrNS( xwszNameSpace ); if ( !xbstrNS ) { hr = HRESULT_FROM_WIN32( GetLastError() ); dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Memory allocate failed") ); retStatus.SetError( hr ); return hr; } VARIANT var; var.vt = VT_BSTR; var.bstrVal = xbstrNS; hr = pOutParams->Put( m_xbstrNameSpace, 0, &var, 0); if ( FAILED(hr) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Put namespace failed with 0x%x"), hr ); retStatus.SetError( hr ); return hr; } } } } 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; } // // change all returns to retStatus = error_code; return S_OK; // hr = Indicator.SetComplete(); if ( FAILED( hr ) ) { dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("ExecAsyncMethod::Increment() 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; }