Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1045 lines
34 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002-2004 Microsoft Corporation
//
// Module Name: Quota.cpp
//
// Description:
// Implementation of VDS WMI Provider quota classes
//
// Author: Jim Benton (jbenton) 25-Mar-2002
//
//////////////////////////////////////////////////////////////////////////////
#include "Pch.h"
#include "Quota.h"
#include "volutil.h"
#define INITGUIDS
#include "dskquota.h"
HRESULT FindQuotaUserFromEnum(
WCHAR* pwszUser,
IDiskQuotaControl* pIDQC,
IDiskQuotaUser** ppQuotaUser);
HRESULT FindQuotaUserWithRecord(
IN _bstr_t bstrDomain,
IN _bstr_t bstrUser,
IN IDiskQuotaControl* pIDQC,
OUT IDiskQuotaUser** ppIQuotaUser);
HRESULT FindQuotaUser(
IN _bstr_t bstrDomain,
IN _bstr_t bstrUser,
IN IDiskQuotaControl* pIDQC,
OUT IDiskQuotaUser** ppIQuotaUser);
BOOL TranslateDomainName(
IN WCHAR* pwszDomain,
OUT CVssAutoPWSZ& rawszDomain);
BOOL GetLocalDomainName(
IN DWORD dwWellKnownAuthority,
OUT CVssAutoPWSZ& rawszDomain);
//****************************************************************************
//
// CVolumeQuota
//
//****************************************************************************
CVolumeQuota::CVolumeQuota(
IN LPCWSTR pwszName,
IN CWbemServices* pNamespace
)
: CProvBase(pwszName, pNamespace)
{
} //*** CVolumeQuota::CVolumeQuota()
CProvBase *
CVolumeQuota::S_CreateThis(
IN LPCWSTR pwszName,
IN CWbemServices* pNamespace
)
{
HRESULT hr = WBEM_E_FAILED;
CVolumeQuota * pObj= NULL;
pObj = new CVolumeQuota(pwszName, pNamespace);
if (pObj)
{
hr = pObj->Initialize();
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
delete pObj;
pObj = NULL;
}
return pObj;
} //*** CVolumeQuota::S_CreateThis()
HRESULT
CVolumeQuota::Initialize()
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeQuota::Initialize");
return ft.hr;
}
HRESULT
CVolumeQuota::EnumInstance(
IN long lFlags,
IN IWbemContext* pCtx,
IN IWbemObjectSink * pHandler
)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeQuota::EnumInstance");
CVssAutoPWSZ awszVolume;
try
{
awszVolume.Allocate(MAX_PATH);
CVssVolumeIterator volumeIterator;
while (true)
{
DWORD dwDontCare = 0;
DWORD dwFileSystemFlags = 0;
// Get the volume name
if (!volumeIterator.SelectNewVolume(ft, awszVolume, MAX_PATH))
break;
if (VolumeSupportsQuotas(awszVolume))
{
CComPtr<IWbemClassObject> spInstance;
WCHAR wszDisplayName[MAX_PATH+1] ;
// The key property on the QuotaSetting object is the display name
VssGetVolumeDisplayName(
awszVolume,
wszDisplayName,
MAX_PATH);
ft.hr = m_pClass->SpawnInstance(0, &spInstance);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
LoadInstance(awszVolume, wszDisplayName, spInstance.p);
ft.hr = pHandler->Indicate(1, &spInstance.p);
}
}
}
catch (HRESULT hrEx)
{
ft.hr = hrEx;
}
return ft.hr;
} //*** CVolumeQuota::EnumInstance()
void
CVolumeQuota:: LoadInstance(
IN WCHAR* pwszVolume,
IN WCHAR* pwszQuotaSetting,
IN OUT IWbemClassObject* pObject)
{
CWbemClassObject wcoInstance(pObject);
CObjPath pathQuotaSetting;
CObjPath pathVolume;
// Set the QuotaSetting Ref property
pathQuotaSetting.Init(PVDR_CLASS_QUOTASETTING);
pathQuotaSetting.AddProperty(PVDR_PROP_VOLUMEPATH, pwszQuotaSetting);
wcoInstance.SetProperty((wchar_t*)pathQuotaSetting.GetObjectPathString(), PVD_WBEM_PROP_SETTING);
// Set the Volume Ref property
pathVolume.Init(PVDR_CLASS_VOLUME);
pathVolume.AddProperty(PVDR_PROP_DEVICEID, pwszVolume);
wcoInstance.SetProperty((wchar_t*)pathVolume.GetObjectPathString(), PVD_WBEM_PROP_ELEMENT);
}
//****************************************************************************
//
// CVolumeUserQuota
//
//****************************************************************************
CVolumeUserQuota::CVolumeUserQuota(
IN LPCWSTR pwszName,
IN CWbemServices* pNamespace
)
: CProvBase(pwszName, pNamespace)
{
} //*** CVolumeUserQuota::CVolumeUserQuota()
CProvBase *
CVolumeUserQuota::S_CreateThis(
IN LPCWSTR pwszName,
IN CWbemServices* pNamespace
)
{
HRESULT hr = WBEM_E_FAILED;
CVolumeUserQuota * pObj= NULL;
pObj = new CVolumeUserQuota(pwszName, pNamespace);
if (pObj)
{
hr = pObj->Initialize();
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
delete pObj;
pObj = NULL;
}
return pObj;
} //*** CVolumeUserQuota::S_CreateThis()
HRESULT
CVolumeUserQuota::Initialize()
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::Initialize");
return ft.hr;
}
HRESULT
CVolumeUserQuota::EnumInstance(
IN long lFlags,
IN IWbemContext* pCtx,
IN IWbemObjectSink * pHandler
)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::EnumInstance");
CVssAutoPWSZ awszVolume;
try
{
awszVolume.Allocate(MAX_PATH);
CVssVolumeIterator volumeIterator;
while (true)
{
DWORD dwDontCare = 0;
DWORD dwFileSystemFlags = 0;
// Get the volume name
if (!volumeIterator.SelectNewVolume(ft, awszVolume, MAX_PATH))
break;
if (VolumeSupportsQuotas(awszVolume))
{
CComPtr<IDiskQuotaControl> spIDQC;
IDiskQuotaControl* pIDQC = NULL;
CComPtr<IEnumDiskQuotaUsers> spIEnum;
ft.hr = CoCreateInstance(
CLSID_DiskQuotaControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
(void **)&pIDQC);
if (ft.HrFailed())
{
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"unable to CoCreate IDiskQuotaControl");
}
spIDQC.Attach(pIDQC);
ft.hr = spIDQC->Initialize(awszVolume, FALSE /* read only */);
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaControl::Initialize failed for volume %lS", awszVolume);
continue;
}
// Need to update the cache, else we can get old names
ft.hr = spIDQC->InvalidateSidNameCache();
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaControl::InvalidateSidNameCache failed for volume %lS", awszVolume);
continue;
}
ft.hr = spIDQC->CreateEnumUsers(
NULL, //All the users will be enumerated
0, // Ignored for enumerating all users
DISKQUOTA_USERNAME_RESOLVE_SYNC,
&spIEnum );
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaControl::CreateEnumUsers failed for volume %lS", awszVolume);
continue;
}
if (spIEnum != NULL)
{
while (true)
{
CComPtr<IWbemClassObject> spInstance;
CComPtr<IDiskQuotaUser> spIQuotaUser;
DWORD cUsers = 0;
ft.hr = spIEnum->Next(1, &spIQuotaUser, &cUsers);
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IEnumDiskQuotaUsers::Next failed for volume %lS", awszVolume);
continue;
}
if (ft.hr == S_FALSE)
break;
ft.hr = m_pClass->SpawnInstance(0, &spInstance);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
LoadInstance(awszVolume, spIQuotaUser, spInstance.p);
ft.hr = pHandler->Indicate(1, &spInstance.p);
}
}
}
}
}
catch (HRESULT hrEx)
{
ft.hr = hrEx;
}
return ft.hr;
} //*** CVolumeUserQuota::EnumInstance()
HRESULT
CVolumeUserQuota::GetObject(
IN CObjPath& rObjPath,
IN long lFlags,
IN IWbemContext* pCtx,
IN IWbemObjectSink* pHandler
)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::GetObject");
try
{
_bstr_t bstrVolumeRef, bstrVolumeName;
_bstr_t bstrAccountRef, bstrDomainName, bstrUserName;
CObjPath objPathVolume;
CObjPath objPathAccount;
CComPtr<IWbemClassObject> spInstance;
CComPtr<IDiskQuotaUser> spIQuotaUser;
CComPtr<IDiskQuotaControl> spIDQC;
IDiskQuotaControl* pIDQC = NULL;
_bstr_t bstrFQUser;
// Get the Volume reference
bstrVolumeRef = rObjPath.GetStringValueForProperty(PVDR_PROP_VOLUME);
// Get the Account reference
bstrAccountRef = rObjPath.GetStringValueForProperty(PVDR_PROP_ACCOUNT);
// Extract the Volume and Account Names
objPathVolume.Init(bstrVolumeRef);
objPathAccount.Init(bstrAccountRef);
bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
if ((wchar_t*)bstrVolumeName == NULL || ((wchar_t*)bstrVolumeName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property DeviceID not found");
}
bstrUserName = objPathAccount.GetStringValueForProperty(PVDR_PROP_NAME);
if ((wchar_t*)bstrUserName == NULL || ((wchar_t*)bstrUserName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Name not found");
}
bstrDomainName = objPathAccount.GetStringValueForProperty(PVDR_PROP_DOMAIN);
if ((wchar_t*)bstrDomainName == NULL || ((wchar_t*)bstrDomainName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Domain not found");
}
ft.hr = CoCreateInstance(
CLSID_DiskQuotaControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
(void **)&pIDQC);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"unable to CoCreate IDiskQuotaControl, %#x", ft.hr);
spIDQC.Attach(pIDQC);
ft.hr = spIDQC->Initialize(bstrVolumeName, TRUE /* read/write */);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IDiskQuotaControl::Initialize failed for volume %lS, %#x", bstrVolumeName, ft.hr);
ft.hr = FindQuotaUser(bstrDomainName, bstrUserName, spIDQC, &spIQuotaUser);
if (ft.HrFailed())
{
ft.hr = WBEM_E_NOT_FOUND;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolumeQuotaUser::GetObject: could not find user %lS\\%lS", bstrDomainName, bstrUserName);
}
ft.hr = m_pClass->SpawnInstance(0, &spInstance);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"SpawnInstance failed, hr<%#x>", ft.hr);
LoadInstance(bstrVolumeName, spIQuotaUser, spInstance.p);
ft.hr = pHandler->Indicate(1, &spInstance.p);
}
catch (HRESULT hrEx)
{
ft.hr = hrEx;
}
return ft.hr;
} //*** CVolume::GetObject()
void
CVolumeUserQuota:: LoadInstance(
IN WCHAR* pwszVolume,
IN IDiskQuotaUser* pIQuotaUser,
IN OUT IWbemClassObject* pObject)
{
CWbemClassObject wcoInstance(pObject);
CObjPath pathAccount;
CObjPath pathVolume;
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::LoadInstance");
do
{
WCHAR wszDomain[g_cchAccountNameMax], *pwszDomain = NULL;
WCHAR wszFQUser[g_cchAccountNameMax], *pwszUser = NULL;
CVssAutoPWSZ awszDomain;
DISKQUOTA_USER_INFORMATION UserQuotaInfo;
DWORD dwStatus = 0;
ft.hr = pIQuotaUser->GetName(wszDomain, g_cchAccountNameMax,
wszFQUser, g_cchAccountNameMax, NULL, 0);
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaUser::GetName failed for volume %lS", pwszVolume);
break;
}
// Win32_Account separates domain\user into two keys, Domain and Name
// Prepare the Domain and Name keys
pwszUser = wcschr(wszFQUser, L'\\'); // user name is domain\\name format
if (pwszUser != NULL)
{
pwszDomain = wszFQUser;
*pwszUser = L'\0';
pwszUser++;
}
else
{
pwszDomain = wcschr(wszFQUser, L'@'); // user name is [email protected] format
if (pwszDomain != NULL)
{
pwszUser = wszFQUser;
*pwszDomain = L'\0';
pwszDomain++;
WCHAR* pwc = wcschr(pwszDomain, L'.');
if (pwc != NULL)
*pwc = L'\0';
}
else
{
pwszDomain = wszDomain;
pwszUser = wszFQUser;
}
}
// The GetName API returns BUILTIN and NT AUTHORITY
// as the domain name for built-in local accounts.
// BUILTIN and NT AUTHORITY accounts are represented
// by Win32_Account and its children with the domain
// name being the name of the machine, instead of
// either of these strings. We'll convert the domain name here.
TranslateDomainName(pwszDomain, awszDomain);
ft.hr = pIQuotaUser->GetQuotaInformation(&UserQuotaInfo, sizeof(UserQuotaInfo));
if (ft.HrFailed())
{
ft.Trace(VSSDBG_VSSADMIN, L"IDiskQuotaUser::GetQuotaInformation failed for volume %lS", pwszVolume);
break;
}
// Set the Account Ref property
pathAccount.Init(PVDR_CLASS_ACCOUNT);
pathAccount.AddProperty(PVDR_PROP_DOMAIN, awszDomain);
pathAccount.AddProperty(PVDR_PROP_NAME, pwszUser);
wcoInstance.SetProperty((wchar_t*)pathAccount.GetObjectPathString(), PVDR_PROP_ACCOUNT);
// Set the Volume Ref property
pathVolume.Init(PVDR_CLASS_VOLUME);
pathVolume.AddProperty(PVDR_PROP_DEVICEID, pwszVolume);
wcoInstance.SetProperty((wchar_t*)pathVolume.GetObjectPathString(), PVDR_PROP_VOLUME);
wcoInstance.SetPropertyI64((ULONGLONG)UserQuotaInfo.QuotaUsed, PVDR_PROP_DISKSPACEUSED);
wcoInstance.SetPropertyI64((ULONGLONG)UserQuotaInfo.QuotaThreshold, PVDR_PROP_WARNINGLIMIT);
wcoInstance.SetPropertyI64((ULONGLONG)UserQuotaInfo.QuotaLimit, PVDR_PROP_LIMIT);
if (UserQuotaInfo.QuotaLimit == -1)
dwStatus = 0; // OK, no limit set
else
{
if (UserQuotaInfo.QuotaUsed >= UserQuotaInfo.QuotaLimit)
dwStatus = 2; // Limit exceeded
else if (UserQuotaInfo.QuotaUsed >= UserQuotaInfo.QuotaThreshold)
dwStatus = 1; // Warning limit exceeded
else
dwStatus = 0; // OK, under the warning limit
}
wcoInstance.SetProperty(dwStatus, PVDR_PROP_STATUS);
}
while(false);
}
HRESULT
CVolumeUserQuota::PutInstance(
IN CWbemClassObject& rInstToPut,
IN long lFlag,
IN IWbemContext* pCtx,
IN IWbemObjectSink* pHandler
)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::PutInstance");
try
{
_bstr_t bstrVolumeRef, bstrVolumeName;
_bstr_t bstrAccountRef, bstrDomainName, bstrUserName;
CObjPath objPathVolume;
CObjPath objPathAccount;
_bstr_t bstrFQUser;
CComPtr<IDiskQuotaUser> spIQuotaUser;
CComPtr<IDiskQuotaControl> spIDQC;
IDiskQuotaControl* pIDQC = NULL;
BOOL fCreate = FALSE;
BOOL fUpdate = FALSE;
LONGLONG llLimit = -1, llThreshold = -1;
// Retrieve key properties of the object to be saved.
rInstToPut.GetProperty(bstrVolumeRef, PVDR_PROP_VOLUME);
rInstToPut.GetProperty(bstrAccountRef, PVDR_PROP_ACCOUNT);
// Extract the Volume, Domain and User names
objPathVolume.Init(bstrVolumeRef);
objPathAccount.Init(bstrAccountRef);
bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
if ((wchar_t*)bstrVolumeName == NULL || ((wchar_t*)bstrVolumeName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property DeviceID not found");
}
bstrDomainName = objPathAccount.GetStringValueForProperty(PVDR_PROP_DOMAIN);
if ((wchar_t*)bstrDomainName == NULL || ((wchar_t*)bstrDomainName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Domain not found");
}
bstrUserName = objPathAccount.GetStringValueForProperty(PVDR_PROP_NAME);
if ((wchar_t*)bstrUserName == NULL || ((wchar_t*)bstrUserName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Name not found");
}
// Retrieve writeable properties
// If the properties are NULL it is expected that llLimit and llThreshold will retain their default values (-1)
rInstToPut.GetPropertyI64(&llLimit, PVDR_PROP_LIMIT);
rInstToPut.GetPropertyI64(&llThreshold, PVDR_PROP_WARNINGLIMIT);
ft.hr = CoCreateInstance(
CLSID_DiskQuotaControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
(void **)&pIDQC);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"unable to CoCreate IDiskQuotaControl, %#x", ft.hr);
spIDQC.Attach(pIDQC);
ft.hr = spIDQC->Initialize(bstrVolumeName, TRUE /* read/write */);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IDiskQuotaControl::Initialize failed for volume %lS, %#x", bstrVolumeName, ft.hr);
ft.hr = FindQuotaUserWithRecord(bstrDomainName, bstrUserName, spIDQC, &spIQuotaUser);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unexpected failure searching for quota account");
DWORD dwPossibleOperations = (WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_CREATE_ONLY);
switch (lFlag & dwPossibleOperations)
{
case WBEM_FLAG_CREATE_OR_UPDATE:
{
if (ft.hr == S_FALSE) // account not found
fCreate = TRUE;
else
fUpdate = TRUE;
}
break;
case WBEM_FLAG_UPDATE_ONLY:
{
if (ft.hr == S_FALSE)
{
ft.hr = WBEM_E_NOT_FOUND;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"QuotaUser %lS\\%lS not found", bstrDomainName, bstrUserName);
}
fUpdate = TRUE;
}
break;
case WBEM_FLAG_CREATE_ONLY:
{
if (ft.hr == S_FALSE) // account not found
{
fCreate = TRUE;
}
else
{
ft.hr = WBEM_E_ALREADY_EXISTS;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota %lS/%lS already exists", bstrVolumeName, bstrFQUser);
}
}
break;
default:
{
ft.hr = WBEM_E_PROVIDER_NOT_CAPABLE;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolumeUserQuota::PutInstance flag not supported %d", lFlag);
}
}
ft.hr = S_OK;
if (fCreate)
{
ft.hr = Create(bstrDomainName, bstrUserName, spIDQC, &spIQuotaUser);
if (ft.hr == S_FALSE) // User already exists
ft.hr = E_UNEXPECTED; // If so we should have found it above
else if (ft.HrFailed())
ft.hr = WBEM_E_INVALID_PARAMETER;
}
if (ft.HrSucceeded() || fUpdate)
{
ft.hr = spIQuotaUser->SetQuotaLimit (llLimit, TRUE);
if (ft.HrSucceeded())
ft.hr = spIQuotaUser->SetQuotaThreshold (llThreshold, TRUE);
}
}
catch (HRESULT hrEx)
{
ft.hr = hrEx;
}
return ft.hr;
} //*** CVolumeUserQuota::PutInstance()
// The CIMV2 provider maps BUILTIN and NT AUTHORITY domains to <local machine name>
// so we must try each of these if AddUserName fails
HRESULT
CVolumeUserQuota::Create(
IN _bstr_t bstrDomainName,
IN _bstr_t bstrUserName,
IN IDiskQuotaControl* pIDQC,
OUT IDiskQuotaUser** ppIQuotaUser)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::Create");
_bstr_t bstrFQUser;
bstrFQUser = bstrDomainName + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->AddUserName(
bstrFQUser ,
DISKQUOTA_USERNAME_RESOLVE_SYNC,
ppIQuotaUser);
if (ft.hr == HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER))
{
CVssAutoPWSZ awszDomain;
// Get the localized NT Authority name
if(!GetLocalDomainName(
SECURITY_NETWORK_SERVICE_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'NT Authority' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->AddUserName(
bstrFQUser ,
DISKQUOTA_USERNAME_RESOLVE_SYNC,
ppIQuotaUser);
if (ft.hr == HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER))
{
awszDomain.Clear();
// Get the localized BuiltIn name and try again
if(!GetLocalDomainName(
SECURITY_BUILTIN_DOMAIN_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'BuiltIn' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->AddUserName(
bstrFQUser ,
DISKQUOTA_USERNAME_RESOLVE_SYNC,
ppIQuotaUser);
}
}
return ft.hr;
}
HRESULT
CVolumeUserQuota::DeleteInstance(
IN CObjPath& rObjPath,
IN long lFlag,
IN IWbemContext* pCtx,
IN IWbemObjectSink* pHandler
)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"CVolumeUserQuota::DeleteInstance");
try
{
_bstr_t bstrVolumeRef, bstrVolumeName;
_bstr_t bstrAccountRef, bstrDomainName, bstrUserName;
CObjPath objPathVolume;
CObjPath objPathAccount;
CComPtr<IDiskQuotaUser> spIQuotaUser;
CComPtr<IDiskQuotaControl> spIDQC;
IDiskQuotaControl* pIDQC = NULL;
_bstr_t bstrFQUser;
// Get the Volume reference
bstrVolumeRef = rObjPath.GetStringValueForProperty(PVDR_PROP_VOLUME);
// Get the Account reference
bstrAccountRef = rObjPath.GetStringValueForProperty(PVDR_PROP_ACCOUNT);
// Extract the Volume and Account Names
objPathVolume.Init(bstrVolumeRef);
objPathAccount.Init(bstrAccountRef);
bstrVolumeName = objPathVolume.GetStringValueForProperty(PVDR_PROP_DEVICEID);
if ((wchar_t*)bstrVolumeName == NULL || ((wchar_t*)bstrVolumeName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property DeviceID not found");
}
bstrUserName = objPathAccount.GetStringValueForProperty(PVDR_PROP_NAME);
if ((wchar_t*)bstrUserName == NULL || ((wchar_t*)bstrUserName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Name not found");
}
bstrDomainName = objPathAccount.GetStringValueForProperty(PVDR_PROP_DOMAIN);
if ((wchar_t*)bstrDomainName == NULL || ((wchar_t*)bstrDomainName)[0] == L'\0')
{
ft.hr = E_INVALIDARG;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"VolumeUserQuota key property Domain not found");
}
ft.hr = CoCreateInstance(
CLSID_DiskQuotaControl,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDiskQuotaControl,
(void **)&pIDQC);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"unable to CoCreate IDiskQuotaControl, %#x", ft.hr);
spIDQC.Attach(pIDQC);
ft.hr = spIDQC->Initialize(bstrVolumeName, TRUE /* read/write */);
if (ft.HrFailed())
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"IDiskQuotaControl::Initialize failed for volume %lS, %#x", bstrVolumeName, ft.hr);
ft.hr = FindQuotaUser(bstrDomainName, bstrUserName, spIDQC, &spIQuotaUser);
if (ft.HrFailed())
{
ft.hr = WBEM_E_NOT_FOUND;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"CVolumeQuotaUser::DeleteInstance: could not find user %lS\\%lS", bstrDomainName, bstrUserName);
}
ft.hr = spIDQC->DeleteUser(spIQuotaUser);
}
catch (HRESULT hrEx)
{
ft.hr = hrEx;
}
return ft.hr;
}
BOOL
TranslateDomainName(
IN WCHAR* pwszDomain,
OUT CVssAutoPWSZ& rawszDomain
)
{
BOOL fReturn = FALSE;
CVssAutoPWSZ awszNtAuthorityDomain;
CVssAutoPWSZ awszBuiltInDomain;
CVssAutoPWSZ awszComputerName;
DWORD cchBuf = 0;
do
{
// Get the computer name
awszComputerName.Allocate(MAX_COMPUTERNAME_LENGTH);
cchBuf = MAX_COMPUTERNAME_LENGTH + 1;
fReturn = GetComputerName(awszComputerName, &cchBuf);
if (!fReturn) break;
// Get the localized NT Authority name
fReturn = GetLocalDomainName(
SECURITY_NETWORK_SERVICE_RID, // NetworkService is a member of Nt Authority domain
awszNtAuthorityDomain);
if (!fReturn) break;
// Get the localized BUILTIN name
fReturn = GetLocalDomainName(
SECURITY_BUILTIN_DOMAIN_RID,
awszBuiltInDomain);
if (!fReturn) break;
// Replace either of these domain names with the NetBIOS computer name
if (lstrcmpi(pwszDomain, awszNtAuthorityDomain) == 0 ||
lstrcmpi(pwszDomain, awszBuiltInDomain) == 0)
rawszDomain.TransferFrom(awszComputerName);
else
rawszDomain.CopyFrom(pwszDomain);
}
while(false);
return fReturn;
}
BOOL
GetLocalDomainName(
IN DWORD dwWellKnownAuthority,
OUT CVssAutoPWSZ& rawszDomain
)
{
BOOL fReturn = FALSE;
PSID pSID = NULL;
SID_NAME_USE snUse = SidTypeUnknown;
SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
CVssAutoPWSZ awszAccount;
DWORD cchDomainName = 0;
DWORD cchAccount = 0;
do
{
// Allocate the SID for the given well known Authority
fReturn = AllocateAndInitializeSid(
&sidAuth,
1,
dwWellKnownAuthority,0,0,0,0,0,0,0,
&pSID);
if (!fReturn) break;
// How long is the domain name?
fReturn = LookupAccountSid(
NULL, // computer name defaults to local
pSID,
NULL, // account name
&cchAccount, // account name len
NULL, // domain name
&cchDomainName,
&snUse);
if (!fReturn && GetLastError() != ERROR_INSUFFICIENT_BUFFER) break;
// Allocate the space
rawszDomain.Allocate(cchDomainName); // allocates the term null too
awszAccount.Allocate(cchAccount); // allocates the term null too
// Get the domain name now
fReturn = LookupAccountSid(
NULL, // computer name defaults to local
pSID,
awszAccount, // account name
&cchAccount, // account name len
rawszDomain, // domain name
&cchDomainName,
&snUse);
}
while(false);
if (pSID)
FreeSid(pSID);
return fReturn;
}
HRESULT FindQuotaUserFromEnum(
WCHAR* pwszUser,
IDiskQuotaControl* pIDQC,
IDiskQuotaUser** ppQuotaUser)
{
WCHAR logonName[MAX_PATH+1];
CComPtr<IEnumDiskQuotaUsers> spUserEnum;
_ASSERTE(ppQuotaUser != NULL);
*ppQuotaUser = NULL;
HRESULT hr = pIDQC->CreateEnumUsers(0,0,DISKQUOTA_USERNAME_RESOLVE_SYNC, &spUserEnum);
if (FAILED(hr))
return hr;
while((hr = spUserEnum->Next(1, ppQuotaUser, 0)) == NOERROR)
{
if (SUCCEEDED((*ppQuotaUser)->GetName( 0, 0, logonName, MAX_PATH, 0, 0))
&& _wcsicmp(logonName, pwszUser) == 0) return S_OK;
(*ppQuotaUser)->Release();
*ppQuotaUser = NULL;
};
return hr;
};
HRESULT FindQuotaUserWithRecord(
IN _bstr_t bstrDomainName,
IN _bstr_t bstrUserName,
IN IDiskQuotaControl* pIDQC,
OUT IDiskQuotaUser** ppIQuotaUser)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"FindQuotaUserWithRecord");
_bstr_t bstrFQUser;
bstrFQUser = bstrDomainName + _bstr_t(L"\\") + bstrUserName;
// Look for the account name as-is
ft.hr = FindQuotaUserFromEnum(bstrFQUser, pIDQC, ppIQuotaUser);
if (ft.hr == S_FALSE)
{
CVssAutoPWSZ awszDomain;
// Get the localized NT Authority name and try again
if(!GetLocalDomainName(
SECURITY_NETWORK_SERVICE_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'NT Authority' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = FindQuotaUserFromEnum(bstrFQUser, pIDQC, ppIQuotaUser);
if (ft.hr == S_FALSE)
{
awszDomain.Clear();
// Get the localized BuiltIn name and try again
if(!GetLocalDomainName(
SECURITY_BUILTIN_DOMAIN_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'BuiltIn' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = FindQuotaUserFromEnum(bstrFQUser, pIDQC, ppIQuotaUser);
}
}
return ft.hr;
}
HRESULT FindQuotaUser(
IN _bstr_t bstrDomainName,
IN _bstr_t bstrUserName,
IN IDiskQuotaControl* pIDQC,
OUT IDiskQuotaUser** ppIQuotaUser)
{
CVssFunctionTracer ft(VSSDBG_VSSADMIN, L"FindQuotaUser");
_bstr_t bstrFQUser;
bstrFQUser = bstrDomainName + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->FindUserName(bstrFQUser, ppIQuotaUser);
if (ft.HrFailed())
{
CVssAutoPWSZ awszDomain;
// Get the localized NT Authority name
if(!GetLocalDomainName(
SECURITY_NETWORK_SERVICE_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'NT Authority' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->FindUserName(bstrFQUser, ppIQuotaUser);
if (ft.HrFailed())
{
awszDomain.Clear();
if(!GetLocalDomainName(
SECURITY_BUILTIN_DOMAIN_RID,
awszDomain))
{
ft.hr = E_UNEXPECTED;
ft.Throw(VSSDBG_VSSADMIN, ft.hr, L"Unable to get localized 'BuiltIn' name");
}
bstrFQUser = _bstr_t(awszDomain) + _bstr_t(L"\\") + bstrUserName;
ft.hr = pIDQC->FindUserName(bstrFQUser, ppIQuotaUser);
}
}
return ft.hr;
}