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.
672 lines
22 KiB
672 lines
22 KiB
//******************************************************************************
|
|
//
|
|
// Microsoft Confidential. Copyright (c) Microsoft Corporation 1999. All rights reserved
|
|
//
|
|
// File: Collect.cpp
|
|
//
|
|
// Description: Support for Namespace Garbage Collection
|
|
//
|
|
// History: 12-01-99 leonardm Created
|
|
//
|
|
//******************************************************************************
|
|
|
|
|
|
#include "uenv.h"
|
|
#include "collect.h"
|
|
#include "..\rsoputil\smartptr.h"
|
|
#include "..\rsoputil\rsoputil.h"
|
|
#include "..\rsoputil\wbemtime.h"
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function: GetMinutesElapsed
|
|
//
|
|
// Description: Returns the number of minutes elapsed between a time represented
|
|
// in a BSTR in WBEM format and the present time.
|
|
// It expects a string in WBEM datetime format: "yyyymmddhhmmss.000000+000"
|
|
// where yyyy=year, mm=month, dd=day, hh=hour, mm=minutes, ss=seconds
|
|
//
|
|
//
|
|
// Parameters: xbstrOldTime - Reference to XBStr representing the time from which
|
|
// calculate the time span.
|
|
//
|
|
// pMinutesElapsed - Pointer to a ULONG that receives the minutes elapsed
|
|
// between xbstrOldTime and the present time.
|
|
//
|
|
// Return: S_OK on success. An HRESULT error code on failure.
|
|
//
|
|
// History: 12/01/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
|
|
HRESULT GetMinutesElapsed(XBStr& xbstrOldTime, ULONG* pMinutesElapsed)
|
|
{
|
|
|
|
//
|
|
// Convert the WbemTime value to a SYSTEMTIME value.
|
|
//
|
|
|
|
SYSTEMTIME systemTime_Old;
|
|
|
|
HRESULT hr = WbemTimeToSystemTime(xbstrOldTime, systemTime_Old);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetMinutesElapsed: WbemTimeToSystemTime failed. hr=0x%08X."), hr));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Convert the SYSTEMTIME value to a FILETIME value.
|
|
//
|
|
|
|
BOOL bRes;
|
|
FILETIME fileTime_Old;
|
|
|
|
bRes = SystemTimeToFileTime(&systemTime_Old, &fileTime_Old);
|
|
if(!bRes)
|
|
{
|
|
DWORD dwLastError = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("GetMinutesElapsed: SystemTimeToFileTime failed. LastError=0x%08X."), dwLastError));
|
|
return E_FAIL;
|
|
}
|
|
|
|
unsigned __int64 old = fileTime_Old.dwHighDateTime;
|
|
old <<= 32;
|
|
old |= fileTime_Old.dwLowDateTime;
|
|
|
|
|
|
//
|
|
// Get the current time in SYSTEMTIME format
|
|
//
|
|
|
|
SYSTEMTIME systemTime_Current;
|
|
GetSystemTime(&systemTime_Current);
|
|
|
|
//
|
|
// Convert the current time from a SYSTEMTIME to a FILETIME value
|
|
//
|
|
|
|
FILETIME fileTime_Current;
|
|
bRes = SystemTimeToFileTime(&systemTime_Current, &fileTime_Current);
|
|
if(!bRes)
|
|
{
|
|
DWORD dwLastError = GetLastError();
|
|
DebugMsg((DM_WARNING, TEXT("GetMinutesElapsed: SystemTimeToFileTime failed. LastError=0x%08X."), dwLastError));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// The time passed in as a parameter must precede the current time
|
|
//
|
|
|
|
unsigned __int64 current = fileTime_Current.dwHighDateTime;
|
|
current <<= 32;
|
|
current |= fileTime_Current.dwLowDateTime;
|
|
|
|
if(old > current)
|
|
{
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// We have converted SYSTEMTIMEs to FILETIMEs.
|
|
// "The FILETIME structure is a 64-bit value representing the number
|
|
// of 100-nanosecond intervals since January 1, 1601."
|
|
// Therefore we need to divide by ten million to obtain seconds
|
|
// and by sixty to obtain minutes.
|
|
//
|
|
|
|
*pMinutesElapsed = (ULONG) (( current - old ) / (60 * 10 * 1000 * 1000));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function: IsNamespaceStale
|
|
//
|
|
// Description: Check if namespace is stale Sub-namespaces 'User' and 'Computer' are expected to have
|
|
// RSOP_Session. The data member 'creationTime' of that instance is examined when
|
|
// evaluating whether the sub-namespace should be deleted. For some failures treat the
|
|
// namespace as garbage-collectable because we don't clean up properly when an error is
|
|
// encountered during the creation of the namespace, and setting up security etc.
|
|
//
|
|
//
|
|
// Parameters: pChildNamespace - Pointer to IWbemServices associated with child namespace
|
|
// TTLMinutes - ULONG variable that represents the maximum number of
|
|
// minutes that may have elapsed before a sub-namespace is
|
|
// deleted.
|
|
//
|
|
// Return: True if namespace is stale, false otherwise
|
|
//
|
|
//******************************************************************************
|
|
|
|
BOOL IsNamespaceStale( IWbemServices *pChildNamespace, ULONG TTLMinutes )
|
|
{
|
|
//
|
|
// compute TTL
|
|
// To do so compare the "creationTime" data member of class RSOP_Session with
|
|
// the current time. If the time span exceeds the threshold (as found in the
|
|
// registry), the namespace is to be deleted.
|
|
//
|
|
|
|
XBStr xbstrInstancePath = L"RSOP_Session.id=\"Session1\"";
|
|
if(!xbstrInstancePath)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return FALSE;
|
|
}
|
|
|
|
XInterface<IWbemClassObject>xpInstance = NULL;
|
|
HRESULT hr = pChildNamespace->GetObject(xbstrInstancePath, 0, NULL, &xpInstance, NULL);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("GarbageCollectNamespace: GetObject failed. hr=0x%08X"), hr));
|
|
return TRUE;
|
|
}
|
|
|
|
XBStr xbstrPropertyName = L"creationTime";
|
|
if(!xbstrPropertyName)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return TRUE;
|
|
}
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
XVariant xVar(&var);
|
|
|
|
hr = xpInstance->Get(xbstrPropertyName, 0, &var, NULL, NULL);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("GarbageCollectNamespace: Get failed. hr=0x%08X."), hr));
|
|
return TRUE;
|
|
}
|
|
|
|
if ( var.vt == VT_NULL )
|
|
return TRUE;
|
|
|
|
XBStr xbstrPropertyValue = var.bstrVal;
|
|
|
|
if(!xbstrPropertyValue)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return FALSE;
|
|
}
|
|
|
|
ULONG minutesElapsed = 10;
|
|
|
|
hr = GetMinutesElapsed(xbstrPropertyValue, &minutesElapsed);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_VERBOSE, TEXT("GarbageCollectNamespace: GetMinutesElapsed failed. hr=0x%08X."), hr));
|
|
return TRUE;
|
|
}
|
|
|
|
if(minutesElapsed > TTLMinutes)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function: GarbageCollectNamespace
|
|
//
|
|
// Description: Garabage-collects the namespace passed in as a parameter.
|
|
// If no sub-namespaces are found or if all sub-namespaces
|
|
// are deleted, it deletes the parent namespace as well.
|
|
// It deletes sub-namespaces whose TTL has expired.
|
|
// It computes the TTL from the 'creationTime' data member of the only
|
|
// instance of class RSOP_Session as defined in rsop.mof.
|
|
//
|
|
// Any of the sub-namespaces that is older than TTLMinutes will be deleted.
|
|
// If no sub-namespaces are left, then the parent namespace is deleted as well.
|
|
//
|
|
// Garbage-collectable are those namespaces which satisfy a set of
|
|
// criteria which at the present time is based solely on the naming convention
|
|
// as follows: namespaces under root\rsop whose name starts with "NS"
|
|
//
|
|
// Sub-namespaces 'User' and 'Computer' are expected to have an instance of class
|
|
// RSOP_Session. The data member 'creationTime' of that instance is examined when
|
|
// evaluating whether the sub-namespace should be deleted.
|
|
//
|
|
//
|
|
// Parameters: bstrNamespace - Name of the namesapce to garbage collect.
|
|
// pWbemServices - Pointer to IWbemServices associated with
|
|
// the parent of bstrNamespace (root\rsop)
|
|
// TTLMinutes - ULONG variable that represents the maximum number of
|
|
// minutes that may have elapsed before a sub-namespace is
|
|
// deleted.
|
|
//
|
|
// Return: S_OK on success. An HRESULT error code on failure.
|
|
//
|
|
// History: 12/01/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
|
|
HRESULT GarbageCollectNamespace(BSTR bstrNamespace, IWbemServices* pWbemServices, ULONG TTLMinutes)
|
|
{
|
|
if(!bstrNamespace || !pWbemServices)
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Connect to that namespace and enumerate instances of __namespace.
|
|
// It's assumed that there will be at most 2 namespaces:
|
|
// "User" and "Computer".
|
|
//
|
|
|
|
XInterface<IWbemServices> xpParentNamespace;
|
|
HRESULT hr = pWbemServices->OpenNamespace( bstrNamespace,
|
|
0,
|
|
NULL,
|
|
&xpParentNamespace,
|
|
NULL);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: OpenNamespace failed. hr=0x%08X"), hr));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Enumerate all instances of __namespace.
|
|
//
|
|
|
|
XInterface<IEnumWbemClassObject> xpEnum;
|
|
XBStr xbstrClass = L"__namespace";
|
|
if(!xbstrClass)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = xpParentNamespace->CreateInstanceEnum( xbstrClass,
|
|
WBEM_FLAG_SHALLOW | WBEM_FLAG_FORWARD_ONLY,
|
|
NULL,
|
|
&xpEnum);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: CreateInstanceEnum failed. hr=0x%08X" ), hr ));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// We re interested in data member "Name" of class __namespace.
|
|
//
|
|
|
|
XBStr xbstrProperty = L"Name";
|
|
if(!xbstrProperty)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory")));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// This pointer will be used to iterate through every instance
|
|
// in the enumeration.
|
|
//
|
|
|
|
XInterface<IWbemClassObject>xpInstance = NULL;
|
|
|
|
ULONG ulReturned = 0;
|
|
long namespacesFound = 0;
|
|
long namespacesDeleted = 0;
|
|
|
|
while(1)
|
|
{
|
|
//
|
|
// Retrieve the next instance in the enumeration.
|
|
//
|
|
|
|
hr = xpEnum->Next( WBEM_NO_WAIT, 1, &xpInstance, &ulReturned);
|
|
if (hr != WBEM_S_NO_ERROR || !ulReturned)
|
|
{
|
|
//
|
|
// Either the end of the enumeration has been reached or an error
|
|
// ocurred. We will find out outside the loop.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
namespacesFound++;
|
|
|
|
//
|
|
// Get the namespace name.
|
|
//
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
|
|
hr = xpInstance->Get(xbstrProperty, 0L, &var, NULL, NULL);
|
|
|
|
//
|
|
// Release the pointer to the current element of the enumeration..
|
|
//
|
|
|
|
xpInstance = NULL;
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Get failed. hr=0x%x" ), hr ));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Use the name of the namespace to connect to it.
|
|
//
|
|
|
|
XBStr xbstrChildNamespace = var.bstrVal;
|
|
VariantClear( &var );
|
|
|
|
if(!xbstrChildNamespace)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory" )));
|
|
return E_FAIL;
|
|
}
|
|
|
|
XInterface<IWbemServices> xpChildNamespace = NULL;
|
|
hr = xpParentNamespace->OpenNamespace( xbstrChildNamespace,
|
|
0,
|
|
NULL,
|
|
&xpChildNamespace,
|
|
NULL);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: OpenNamespace returned 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
BOOL bStale = IsNamespaceStale( xpChildNamespace, TTLMinutes );
|
|
xpChildNamespace = NULL;
|
|
|
|
if ( bStale )
|
|
{
|
|
//
|
|
// DeleteInstance
|
|
//
|
|
|
|
CWString sNamespaceToDelete = L"__namespace.name=\"";
|
|
sNamespaceToDelete += (WCHAR*)xbstrChildNamespace;
|
|
sNamespaceToDelete += L"\"";
|
|
|
|
if(!sNamespaceToDelete.ValidString())
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
XBStr xbstrInstancePath = sNamespaceToDelete;
|
|
if(!xbstrInstancePath)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = xpParentNamespace->DeleteInstance(xbstrInstancePath, 0, NULL, NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: DeleteInstance returned 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("GarbageCollectNamespace: Deleted namespace:%ws\\%ws\n"),
|
|
(WCHAR*)bstrNamespace, (WCHAR*)xbstrChildNamespace ));
|
|
|
|
namespacesDeleted++;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Check to find out whther the loop was exited because the end of the
|
|
// enumeration was reached or because an error ocurred.
|
|
//
|
|
|
|
if(hr != (HRESULT) WBEM_S_FALSE || ulReturned)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Get failed. hr=0x%x" ), hr ));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// If no namespaces are found or if namespaces in enumeration
|
|
// equal deleted namespaces delete the parent namespace as well.
|
|
//
|
|
|
|
if((!namespacesFound) || (namespacesDeleted == namespacesFound))
|
|
{
|
|
xpParentNamespace = NULL;
|
|
|
|
CWString sNamespaceToDelete = L"__namespace.name=\"";
|
|
sNamespaceToDelete += (WCHAR*)bstrNamespace;
|
|
sNamespaceToDelete += L"\"";
|
|
|
|
if(!sNamespaceToDelete.ValidString())
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
XBStr xbstrInstancePath = sNamespaceToDelete;
|
|
if(!xbstrInstancePath)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = pWbemServices->DeleteInstance(xbstrInstancePath, 0, NULL, NULL);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespace: DeleteInstance returned 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
DebugMsg((DM_VERBOSE, TEXT("GarbageCollectNamespace: Deleted namespace %ws\n"),
|
|
(WCHAR*)bstrNamespace ));
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function: IsGarbageCollectable
|
|
//
|
|
// Description: Determines whether a namespace is garbage-collectable.
|
|
// Garbage-collectable are those namespaces which satisfy a set of
|
|
// criteria which at the present time is based solely on the naming convention
|
|
// as follows: namespaces under root\rsop whose name starts with "NS"
|
|
//
|
|
//
|
|
// Parameters: bstrNamespace - BSTR that represents the namespace name.
|
|
//
|
|
// Return: 'true' or 'false'.
|
|
//
|
|
// History: 12/01/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
|
|
bool IsGarbageCollectable(BSTR bstrNamespace)
|
|
{
|
|
if(bstrNamespace && wcslen(bstrNamespace) > 1 && _wcsnicmp(bstrNamespace, L"NS", 2) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//******************************************************************************
|
|
//
|
|
// Function: GarbageCollectNamespaces
|
|
//
|
|
// Description: Iterates through namespaces under root\rsop and for each of those
|
|
// that are determined to be garbage-collectable, it connects to
|
|
// sub-namespaces 'User' and 'Computer'.
|
|
//
|
|
// Any of the sub-namespaces that is older than TTLMinutes will be deleted.
|
|
// If no sub-namespaces are left, then the parent namespace is deleted as well.
|
|
//
|
|
// Garbage-collectable are those namespaces which satisfy a set of
|
|
// criteria which at the present time is based solely on the naming convention
|
|
// as follows: namespaces under root\rsop whose name starts with "NS"
|
|
//
|
|
// Sub-namespaces 'User' and 'Computer' are expected to have an instance of class
|
|
// RSOP_Session. The data member 'creationTime' of that instance is examined when
|
|
// evaluating whether the sub-namespace should be deleted.
|
|
//
|
|
//
|
|
// Parameters: TTLMinutes - The maximum number of minutes that may have
|
|
// elapsed since the creation of a sub-namespace
|
|
//
|
|
// Return:
|
|
//
|
|
// History: 12/01/99 leonardm Created.
|
|
//
|
|
//******************************************************************************
|
|
|
|
HRESULT GarbageCollectNamespaces(ULONG TTLMinutes)
|
|
{
|
|
XInterface<IWbemLocator> xpWbemLocator = NULL;
|
|
|
|
//
|
|
// Connect to namespace ROOT\RSOP
|
|
//
|
|
|
|
HRESULT hr = CoCreateInstance( CLSID_WbemLocator,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IWbemLocator,
|
|
(LPVOID*) &xpWbemLocator);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: CoCreateInstance returned 0x%x"), hr));
|
|
return hr;
|
|
}
|
|
|
|
XInterface<IWbemServices> xpWbemServices = NULL;
|
|
|
|
XBStr xbstrNamespace = L"root\\rsop";
|
|
|
|
if(!xbstrNamespace)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
hr = xpWbemLocator->ConnectServer(xbstrNamespace,
|
|
NULL,
|
|
NULL,
|
|
0L,
|
|
0L,
|
|
NULL,
|
|
NULL,
|
|
&xpWbemServices);
|
|
if(FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: ConnectServer failed. hr=0x%x" ), hr ));
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Enumerate all instances of __namespace at the root\rsop level.
|
|
//
|
|
|
|
XInterface<IEnumWbemClassObject> xpEnum;
|
|
XBStr xbstrClass = L"__namespace";
|
|
if(!xbstrClass)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: 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("GarbageCollectNamespaces: CreateInstanceEnum failed. hr=0x%x" ), hr ));
|
|
return hr;
|
|
}
|
|
|
|
XBStr xbstrProperty = L"Name";
|
|
if(!xbstrProperty)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: 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_WARNING, TEXT("GarbageCollectNamespaces: Get failed. hr=0x%x" ), hr ));
|
|
return E_FAIL;
|
|
}
|
|
|
|
XBStr xbstrGCNamespace = var.bstrVal;
|
|
|
|
VariantClear( &var );
|
|
|
|
if(!xbstrGCNamespace)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: Failed to allocate memory.")));
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// For every instance of __namespace under ROOT\RSOP
|
|
// find out whether it is garbage-collectable.
|
|
//
|
|
|
|
if(IsGarbageCollectable(xbstrGCNamespace))
|
|
{
|
|
//
|
|
// If it is garbage-collectable, delete it if it
|
|
// was created more than 'TTLMinutes' minutes ago.
|
|
// In case of failure, continue with next namespace
|
|
// in the enumeration.
|
|
//
|
|
|
|
GarbageCollectNamespace(xbstrGCNamespace, xpWbemServices, TTLMinutes);
|
|
}
|
|
}
|
|
|
|
if(hr != (HRESULT) WBEM_S_FALSE || ulReturned)
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GarbageCollectNamespaces: Get failed. hr=0x%x" ), hr ));
|
|
return E_FAIL;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|