/****************************************************************** DskQuota.CPP -- WMI provider class implementation Description: Disk Quota Provider Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved ******************************************************************/ #include "precomp.h" // #include for DiskQuota Provider Class #include "DiskQuota.h" #include "dllutils.h" CDiskQuota MyCDiskQuota ( IDS_DiskQuotaClass , NameSpace ) ; /***************************************************************************** * * FUNCTION : CDiskQuota::CDiskQuota * * DESCRIPTION : Constructor * * COMMENTS : Calls the Provider constructor. * *****************************************************************************/ CDiskQuota :: CDiskQuota ( LPCWSTR lpwszName, LPCWSTR lpwszNameSpace ) : Provider ( lpwszName , lpwszNameSpace ) { m_ComputerName = GetLocalComputerName(); } /***************************************************************************** * * FUNCTION : CDiskQuota::~CDiskQuota * * DESCRIPTION : Destructor * * COMMENTS : * *****************************************************************************/ CDiskQuota :: ~CDiskQuota () { } HRESULT FindUser(CHString& user, IDiskQuotaControlPtr& controler) { IEnumDiskQuotaUsersPtr userEnum; HRESULT hr = controler->CreateEnumUsers(0,0,DISKQUOTA_USERNAME_RESOLVE_SYNC, &userEnum); if (FAILED(hr)) return hr; CHString logonName; LPWSTR logonNameBuffer = logonName.GetBuffer(MAX_PATH + 1); IDiskQuotaUserPtr userQuota; while((hr = userEnum->Next(1, &userQuota, 0)) == NOERROR) { if (SUCCEEDED(userQuota->GetName( 0, 0, logonNameBuffer, MAX_PATH, 0, 0)) && logonName == user) return S_OK; userQuota.Release(); }; if (hr== S_FALSE) // Enumeration completed return WBEM_E_NOT_FOUND; else return hr; }; /***************************************************************************** * * FUNCTION : CDiskQuota::EnumerateInstances * * DESCRIPTION : Returns all the instances of this class. * * COMMENTS : All instances of Disk Quota users on all Logical Disks that * supports disk quota on a machine with all the properties of * DiskQuota users should be returned here. * *****************************************************************************/ HRESULT CDiskQuota :: EnumerateInstances ( MethodContext *pMethodContext, long lFlags ) { DWORD dwPropertiesReq = DSKQUOTA_ALL_PROPS; HRESULT hRes = WBEM_S_NO_ERROR; hRes = EnumerateUsersOfAllVolumes ( pMethodContext, dwPropertiesReq ); return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::GetObject * * DESCRIPTION : Find a single instance based on the key properties for the * class. * *****************************************************************************/ HRESULT CDiskQuota :: GetObject ( CInstance *pInstance, long lFlags , CFrameworkQuery &Query ) { HRESULT hRes = WBEM_S_NO_ERROR; CHString t_Key1; CHString t_Key2; // Obtain the keys. if ( pInstance->GetCHString ( IDS_LogicalDiskObjectPath , t_Key1 ) == FALSE ) { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { if ( pInstance->GetCHString ( IDS_UserObjectPath , t_Key2 ) == FALSE ) { hRes = WBEM_E_FAILED ; } } if ( SUCCEEDED ( hRes ) ) { CHString t_DiskPropVolumePath; GetKeyValue ( t_DiskPropVolumePath,t_Key1 ); if (t_DiskPropVolumePath.IsEmpty()) { hRes = WBEM_E_NOT_FOUND; } else { // verify this logical drives actually exists WCHAR lpDriveStrings[(MAX_PATH * 2) + 1]; DWORD dwDLength = GetLogicalDriveStrings ( (MAX_PATH * 2), lpDriveStrings ); hRes = m_CommonRoutine.SearchLogicalDisk ( t_DiskPropVolumePath.GetAt ( 0 ), lpDriveStrings ); } if ( SUCCEEDED ( hRes ) ) { WCHAR w_VolumePathName [ MAX_PATH + 1 ]; t_DiskPropVolumePath += L"\\"; if ( GetVolumeNameForVolumeMountPoint( t_DiskPropVolumePath, w_VolumePathName, MAX_PATH )) { // Get the key values, which will be the object path. // Now from the Volume Object path, parse out the volumename // from the User object path extract out the user Id. // for the volume specified check whether the given volume Supports Disk Quotas CHString t_VolumeName; hRes = m_CommonRoutine.VolumeSupportsDiskQuota ( w_VolumePathName, t_VolumeName ); if ( SUCCEEDED ( hRes ) ) { // Get IDIskQuotaCOntrol for this interface pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // Initialise the pIQuotaControl with the given volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, w_VolumePathName ); if ( SUCCEEDED ( hRes ) ) { IDiskQuotaUserPtr pIQuotaUser; CHString t_UserLogName; GetKeyValue ( t_UserLogName, t_Key2 ); HRESULT hrTemp = WBEM_E_NOT_FOUND; if (!t_UserLogName.IsEmpty()) { hrTemp = pIQuotaControl->FindUserName( t_UserLogName, &pIQuotaUser); // Certain Win32_Account instances report // the Domain as computername instead of // builtin, so change domain to builtin and // try again. CHString chstrBuiltIn; if(FAILED(hrTemp) && GetLocalizedBuiltInString(chstrBuiltIn)) { int iWhackPos = t_UserLogName.Find(L"\\"); CHString chstrDomain = t_UserLogName.Left(iWhackPos); if(chstrDomain.CompareNoCase(GetLocalComputerName()) == 0) { CHString chstrUNameOnly = t_UserLogName.Mid(iWhackPos); CHString chstrDomWhackName = chstrBuiltIn; chstrDomWhackName += chstrUNameOnly; hrTemp = pIQuotaControl->FindUserName( chstrDomWhackName, &pIQuotaUser); } } // Certain Win32_Account instances report // the Domain as computername instead of // NT AUTHORITY, so change domain to NT AUTHORITY and // try again. if(FAILED(hrTemp)) { int iWhackPos = t_UserLogName.Find(L"\\"); CHString chstrDomain = t_UserLogName.Left(iWhackPos); if(chstrDomain.CompareNoCase(GetLocalComputerName()) == 0) { CHString chstrUNameOnly = t_UserLogName.Mid(iWhackPos); CHString chstrNT_AUTHORITY; CHString chstrDomWhackName; if(GetLocalizedNTAuthorityString(chstrNT_AUTHORITY)) { chstrDomWhackName = chstrNT_AUTHORITY; } else { chstrDomWhackName = L"NT AUTHORITY"; } chstrDomWhackName += chstrUNameOnly; hrTemp = pIQuotaControl->FindUserName( chstrDomWhackName, &pIQuotaUser); } } } if(SUCCEEDED(hrTemp)) { // Put this Instance DWORD dwPropertiesReq; if ( Query.AllPropertiesAreRequired() ) { dwPropertiesReq = DSKQUOTA_ALL_PROPS; } else { SetPropertiesReq ( &Query, dwPropertiesReq ); } hRes = LoadDiskQuotaUserProperties ( pIQuotaUser, pInstance, dwPropertiesReq ); } else { hRes = WBEM_E_NOT_FOUND; } } } else { hRes = WBEM_E_FAILED; } } } else { hRes = WBEM_E_NOT_FOUND; } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::ExecQuery * * DESCRIPTION : You are passed a method context to use in the creation of * instances that satisfy the query, and a CFrameworkQuery * which describes the query. Create and populate all * instances which satisfy the query. * a) Queries involving Properties other than Win32_LogicalDisk * are not optimized. Since that would involve enumerating * every user on all volumes * *****************************************************************************/ HRESULT CDiskQuota :: ExecQuery ( MethodContext *pMethodContext, CFrameworkQuery &Query, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR; DWORD dwPropertiesReq; CHStringArray t_Values; // Now a check for the attribute which if present in where clause the query optimization is supported // We need not care for the other attributes for which Optimization is not supported, winmgmt will take // care of those. hRes = Query.GetValuesForProp( IDS_LogicalDiskObjectPath, t_Values ); if ( Query.AllPropertiesAreRequired() ) { dwPropertiesReq = DSKQUOTA_ALL_PROPS; } else { SetPropertiesReq ( &Query, dwPropertiesReq ); } if ( SUCCEEDED ( hRes ) ) { if ( t_Values.GetSize() == 0 ) { hRes = EnumerateUsersOfAllVolumes ( pMethodContext, dwPropertiesReq ); } else { // Only Volume in QuotaVolume properties are needed to be enumerated int iSize = t_Values.GetSize (); // verify this logical drives actually exists WCHAR lpDriveStrings [(MAX_PATH * 2) + 1]; DWORD dwDLength = GetLogicalDriveStrings ( (MAX_PATH * 2), lpDriveStrings ); for ( int i = 0; i < iSize; i++ ) { CHString t_VolumePath; //Here we need to parse the VolumeObject path and extract VolumePath from it. GetKeyValue ( t_VolumePath, t_Values.GetAt(i) ); if (( t_VolumePath.GetLength() == 2 ) && ( t_VolumePath.GetAt ( 1 ) == _L(':') ) ) { HRESULT tmpHR = m_CommonRoutine.SearchLogicalDisk ( t_VolumePath.GetAt ( 0 ), lpDriveStrings ); if ( SUCCEEDED ( tmpHR ) ) { t_VolumePath += L"\\"; hRes = EnumerateUsers ( pMethodContext, t_VolumePath, dwPropertiesReq ); } } } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::PutInstance * * DESCRIPTION : If the instance is already existing, we only modify the instance * if it doesnt exist, we will add the instance based on the flags. * *****************************************************************************/ HRESULT CDiskQuota :: PutInstance ( const CInstance &Instance, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR; CHString t_Key1; CHString t_Key2; BOOL bFound = TRUE; if ( Instance.GetCHString ( IDS_LogicalDiskObjectPath , t_Key1 ) == FALSE ) { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { if ( Instance.GetCHString ( IDS_UserObjectPath , t_Key2 ) == FALSE ) { hRes = WBEM_E_FAILED ; } } if ( SUCCEEDED ( hRes ) ) { WCHAR t_VolumePathName[MAX_PATH + 1]; CHString t_UserLogonName; CHString t_VolumePath; GetKeyValue ( t_VolumePath,t_Key1 ); if (t_VolumePath.IsEmpty()) { hRes = WBEM_E_NOT_FOUND ; } else { // verify this logical drives actually exists WCHAR lpDriveStrings [(MAX_PATH * 2) + 1]; DWORD dwDLength = GetLogicalDriveStrings ( (MAX_PATH * 2), lpDriveStrings ); hRes = m_CommonRoutine.SearchLogicalDisk ( t_VolumePath.GetAt ( 0 ), lpDriveStrings ); } if ( SUCCEEDED ( hRes ) ) { GetKeyValue ( t_UserLogonName, t_Key2 ); if (t_UserLogonName.IsEmpty()) { hRes = WBEM_E_NOT_FOUND; } else { t_VolumePath += L"\\"; if ( GetVolumeNameForVolumeMountPoint( t_VolumePath, t_VolumePathName, MAX_PATH )) { // Check if the user already exists hRes = m_CommonRoutine.VolumeSupportsDiskQuota ( t_VolumePathName, t_VolumePath ); if ( SUCCEEDED ( hRes ) ) { // Get IDIskQuotaCOntrol for this interface pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // Initialise the pIQuotaControl with the given volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, t_VolumePathName ); if ( SUCCEEDED ( hRes ) ) { hRes = FindUser(t_UserLogonName,pIQuotaControl ); // Certain Win32_Account instances report // the Domain as computername instead of // builtin, so change domain to builtin and // try again. CHString chstrBuiltIn; if( hRes == WBEM_E_NOT_FOUND && GetLocalizedBuiltInString(chstrBuiltIn)) { int iWhackPos = t_UserLogonName.Find(L"\\"); CHString chstrDomain = t_UserLogonName.Left(iWhackPos); if(chstrDomain.CompareNoCase(GetLocalComputerName()) == 0) { CHString chstrUNameOnly = t_UserLogonName.Mid(iWhackPos); CHString chstrDomWhackName = chstrBuiltIn; chstrDomWhackName += chstrUNameOnly; hRes = FindUser(chstrDomWhackName,pIQuotaControl); if(SUCCEEDED(hRes)) { t_UserLogonName = chstrDomWhackName; } else if (hRes == WBEM_E_NOT_FOUND) { CHString chstrNT_AUTHORITY; CHString chstrDomWhackName; if(GetLocalizedNTAuthorityString(chstrNT_AUTHORITY)) { chstrDomWhackName = chstrNT_AUTHORITY; } else { chstrDomWhackName = L"NT AUTHORITY"; } chstrDomWhackName += chstrUNameOnly; hRes = FindUser(chstrDomWhackName,pIQuotaControl); if(SUCCEEDED(hRes)) { t_UserLogonName = chstrDomWhackName; } } } } } } else { hRes = WBEM_E_FAILED; } } } else { hRes = WBEM_E_NOT_FOUND; } } } if ( SUCCEEDED ( hRes ) || ( hRes == WBEM_E_NOT_FOUND ) ) { BOOL bCreate = FALSE; BOOL bUpdate = FALSE; switch ( lFlags & 3 ) { case WBEM_FLAG_CREATE_OR_UPDATE: { if ( hRes == WBEM_E_NOT_FOUND ) { bCreate = TRUE; hRes = WBEM_S_NO_ERROR; } else bUpdate = TRUE; } break; case WBEM_FLAG_UPDATE_ONLY: { bUpdate = TRUE; } break; case WBEM_FLAG_CREATE_ONLY: { if ( hRes == WBEM_E_NOT_FOUND ) { bCreate = TRUE; hRes = WBEM_S_NO_ERROR; } else { hRes = WBEM_E_ALREADY_EXISTS ; } } break; default: { hRes = WBEM_E_PROVIDER_NOT_CAPABLE; } } if (SUCCEEDED(hRes)) { if ( bCreate ) { hRes = AddUserOnVolume ( Instance, t_VolumePathName, t_UserLogonName ); } else if ( bUpdate ) { hRes = UpdateUserQuotaProperties ( Instance, t_VolumePathName, t_UserLogonName); } } } } return hRes ; } /***************************************************************************** * * FUNCTION : CDiskQuota:: DeleteInstance * * DESCRIPTION : If the given instance of a user exists on the Volume, * the user is deleted, meaning diskquota properties * will no t be applicable to this user. * *****************************************************************************/ HRESULT CDiskQuota :: DeleteInstance ( const CInstance &Instance, long lFlags ) { HRESULT hRes = WBEM_S_NO_ERROR; CHString t_Key1; CHString t_Key2; if ( Instance.GetCHString ( IDS_LogicalDiskObjectPath , t_Key1 ) == FALSE ) { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { if ( Instance.GetCHString ( IDS_UserObjectPath , t_Key2 ) == FALSE ) { hRes = WBEM_E_FAILED ; } } if ( SUCCEEDED ( hRes ) ) { CHString t_VolumePath; GetKeyValue ( t_VolumePath,t_Key1 ); if (t_VolumePath.IsEmpty()) { hRes = WBEM_E_NOT_FOUND; } else { // verify this logical drives actually exists WCHAR lpDriveStrings [ (MAX_PATH * 2) + 1 ]; DWORD dwDLength = GetLogicalDriveStrings ( (MAX_PATH * 2), lpDriveStrings ); if ( ( t_VolumePath.GetLength() == 2 ) && ( t_VolumePath.GetAt ( 1 ) == L':') ) { hRes = m_CommonRoutine.SearchLogicalDisk ( t_VolumePath.GetAt ( 0 ), lpDriveStrings ); if ( SUCCEEDED ( hRes ) ) { t_VolumePath += L"\\"; CHString t_UserLogonName; GetKeyValue ( t_UserLogonName, t_Key2 ); if (t_UserLogonName.IsEmpty()) { hRes = WBEM_E_NOT_FOUND; } else { WCHAR t_VolumePathName[MAX_PATH + 1]; if ( GetVolumeNameForVolumeMountPoint( t_VolumePath, t_VolumePathName, MAX_PATH ) ) { // for the volume specified check whether the given volume Supports Disk Quotas CHString t_TempVolumeName; hRes = m_CommonRoutine.VolumeSupportsDiskQuota ( t_VolumePathName, t_TempVolumeName ); if ( SUCCEEDED ( hRes ) ) { // Get IDIskQuotaCOntrol for this interface pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // Initialise the pIQuotaControl with the given volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, t_VolumePathName ); if ( SUCCEEDED ( hRes ) ) { IDiskQuotaUserPtr pIQuotaUser; hRes = pIQuotaControl->FindUserName( t_UserLogonName, &pIQuotaUser ); // Certain Win32_Account instances report // the Domain as computername instead of // builtin, so change domain to builtin and // try again. CHString chstrBuiltIn; if(FAILED(hRes) && GetLocalizedBuiltInString(chstrBuiltIn)) { int iWhackPos = t_UserLogonName.Find(L"\\"); CHString chstrDomain = t_UserLogonName.Left(iWhackPos); if(chstrDomain.CompareNoCase(GetLocalComputerName()) == 0) { CHString chstrUNameOnly = t_UserLogonName.Mid(iWhackPos); CHString chstrDomWhackName = chstrBuiltIn; chstrDomWhackName += chstrUNameOnly; hRes = pIQuotaControl->FindUserName( chstrDomWhackName, &pIQuotaUser); } } // Get the user properties if ( SUCCEEDED ( hRes ) ) { // Since the user is found delete the user. hRes = pIQuotaControl->DeleteUser ( pIQuotaUser ); if (FAILED(hRes)) { if (SCODE_CODE(hRes) == ERROR_ACCESS_DENIED) { hRes = WBEM_E_ACCESS_DENIED; } else { hRes = WBEM_E_FAILED; } } } else { hRes = WBEM_E_NOT_FOUND; } } } else { hRes = WBEM_E_FAILED; } } } else { hRes = WBEM_E_NOT_FOUND; } } } } else { hRes = WBEM_E_NOT_FOUND; } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::EnumerateUsersOfAllVolumes * * DESCRIPTION : In this method enumerating volumes and calling enumerate users * for that volume * *****************************************************************************/ HRESULT CDiskQuota :: EnumerateUsersOfAllVolumes ( MethodContext *pMethodContext, DWORD a_PropertiesReq ) { HRESULT hRes = WBEM_S_NO_ERROR; WCHAR t_VolumeName[MAX_PATH + 1]; SmartCloseVolumeHandle hVol; hVol = FindFirstVolume( t_VolumeName, // output buffer MAX_PATH // size of output buffer ); if ( hVol != INVALID_HANDLE_VALUE ) { BOOL bNextVol = TRUE; // verify this logical drives actually exists WCHAR lpDriveStrings[(MAX_PATH * 2) + 1]; DWORD dwDLength = GetLogicalDriveStrings ( (MAX_PATH * 2), lpDriveStrings ); CHString t_VolumePath; while ( bNextVol ) { m_CommonRoutine.GetVolumeDrive ( t_VolumeName, lpDriveStrings, t_VolumePath ); EnumerateUsers ( pMethodContext, t_VolumePath, a_PropertiesReq ); bNextVol = FindNextVolume( hVol, // volume search handle t_VolumeName, // output buffer MAX_PATH // size of output buffer ); } } else { hRes = WBEM_E_FAILED; } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::EnumerateUsers * * DESCRIPTION : In this method Enumerating all the users of a given volume that * Supports DiskQuotas * *****************************************************************************/ HRESULT CDiskQuota :: EnumerateUsers ( MethodContext *pMethodContext, LPCWSTR a_VolumeName, DWORD a_PropertiesReq ) { HRESULT hRes = WBEM_S_NO_ERROR; // checking whether the given volume supports disk quotas, and getting the Volume name which is readable to the // user, i.e. not containing the GUID. CHString t_VolumeName; hRes = m_CommonRoutine.VolumeSupportsDiskQuota ( a_VolumeName, t_VolumeName ); if ( SUCCEEDED ( hRes ) ) { // Get the QuotaInterface Pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // initializing the Interface pointer for a particular volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, a_VolumeName ); if ( SUCCEEDED ( hRes ) ) { // need to update the cache, else we can get old names pIQuotaControl->InvalidateSidNameCache(); IEnumDiskQuotaUsersPtr pIEnumDiskQuotaUsers; if ( SUCCEEDED ( pIQuotaControl->CreateEnumUsers( NULL, //All the users will be enumerated 0, // Ignored for enumerating all users DISKQUOTA_USERNAME_RESOLVE_SYNC, &pIEnumDiskQuotaUsers ) ) ) { if ( pIEnumDiskQuotaUsers != NULL ) { hRes = pIEnumDiskQuotaUsers->Reset(); if ( SUCCEEDED(hRes)) { IDiskQuotaUserPtr pIQuotaUser; DWORD dwNoOfUsers = 0; HRESULT hRes = S_OK; hRes = pIEnumDiskQuotaUsers->Next( 1, &pIQuotaUser, &dwNoOfUsers ); CInstancePtr pInstance; while ( SUCCEEDED ( hRes ) ) { if ( dwNoOfUsers == 0 ) { break; } if ( pIQuotaUser != NULL ) { pInstance.Attach(CreateNewInstance ( pMethodContext )); hRes = LoadDiskQuotaUserProperties ( pIQuotaUser, pInstance, a_PropertiesReq ); if ( SUCCEEDED ( hRes ) ) { if(SUCCEEDED(SetKeys( pInstance, a_VolumeName[0], a_PropertiesReq, pIQuotaUser ))) { hRes = pInstance->Commit (); } if (SUCCEEDED(hRes)) { dwNoOfUsers = 0; hRes = pIEnumDiskQuotaUsers->Next( 1, &pIQuotaUser, &dwNoOfUsers ); } } else { break; } } else { // No more Users break; } } } } } else { hRes = WBEM_E_FAILED; } } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::LoadDiskQuotaUserProperties * * DESCRIPTION : In this method Getting the User properties into a Given Structure * *****************************************************************************/ HRESULT CDiskQuota :: LoadDiskQuotaUserProperties ( IDiskQuotaUser* pIQuotaUser, CInstance* pInstance, DWORD a_PropertiesReq ) { HRESULT hRes = WBEM_S_NO_ERROR; if ( ( ( a_PropertiesReq & DSKQUOTA_PROP_Status ) == DSKQUOTA_PROP_Status ) || ( ( a_PropertiesReq & DSKQUOTA_PROP_WarningLimit ) == DSKQUOTA_PROP_WarningLimit ) || ( ( a_PropertiesReq & DSKQUOTA_PROP_Limit ) == DSKQUOTA_PROP_Limit ) || ( ( a_PropertiesReq & DSKQUOTA_PROP_DiskSpaceUsed ) == DSKQUOTA_PROP_DiskSpaceUsed ) ) { DISKQUOTA_USER_INFORMATION t_QuotaInformation; if ( SUCCEEDED ( pIQuotaUser->GetQuotaInformation ( &t_QuotaInformation, sizeof ( DISKQUOTA_USER_INFORMATION ) ) ) ) { LONGLONG llLimit = -1; LONGLONG llWarningLimit = -1; UINT64 ullDiskSpaceUsed = 0; DWORD dwStatus; if ( t_QuotaInformation.QuotaLimit >= 0 ) { llLimit = t_QuotaInformation.QuotaLimit; } if ( t_QuotaInformation.QuotaThreshold >= 0 ) { llWarningLimit = t_QuotaInformation.QuotaThreshold; } ullDiskSpaceUsed = t_QuotaInformation.QuotaUsed; if ( t_QuotaInformation.QuotaThreshold > -1 ) { // Since -1 means no Warning limit is set for the user, the deault is the complete Volume Space if ( t_QuotaInformation.QuotaUsed < t_QuotaInformation.QuotaThreshold ) { dwStatus = 0; } } else { dwStatus = 0; } if ( t_QuotaInformation.QuotaThreshold > -1 ) { // Since -1 means no Warning limit is set for the user, the deault is the complete Volume Space if ( t_QuotaInformation.QuotaUsed >= t_QuotaInformation.QuotaThreshold ) { dwStatus = 1; } } if ( t_QuotaInformation.QuotaLimit > -1 ) { if ( t_QuotaInformation.QuotaUsed >= t_QuotaInformation.QuotaLimit ) { dwStatus = 2; } } if ( ( a_PropertiesReq & DSKQUOTA_PROP_Status ) == DSKQUOTA_PROP_Status ) { if ( pInstance->SetDWORD ( IDS_QuotaStatus, dwStatus ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( ( a_PropertiesReq & DSKQUOTA_PROP_WarningLimit ) == DSKQUOTA_PROP_WarningLimit ) { if ( pInstance->SetWBEMINT64 ( IDS_QuotaWarningLimit, (ULONGLONG)llWarningLimit ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( ( a_PropertiesReq & DSKQUOTA_PROP_Limit ) == DSKQUOTA_PROP_Limit ) { if ( pInstance->SetWBEMINT64 ( IDS_QuotaLimit, (ULONGLONG)llLimit ) == FALSE ) { hRes = WBEM_E_FAILED; } } if ( ( a_PropertiesReq & DSKQUOTA_PROP_DiskSpaceUsed ) == DSKQUOTA_PROP_DiskSpaceUsed ) { if ( pInstance->SetWBEMINT64 ( IDS_DiskSpaceUsed, ullDiskSpaceUsed ) == FALSE ) { hRes = WBEM_E_FAILED; } } } else { hRes = WBEM_E_FAILED; } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::SetKeys * * DESCRIPTION : In this method Setting the User properties in a Given Instance * *****************************************************************************/ HRESULT CDiskQuota :: SetKeys( CInstance* pInstance, WCHAR w_Drive, DWORD a_PropertiesReq, IDiskQuotaUser* pIQuotaUser ) { LPWSTR lpLogicalDiskObjectPath; LPWSTR lpUserObjectPath; HRESULT hRes = WBEM_S_NO_ERROR; if ( ( a_PropertiesReq & DSKQUOTA_PROP_LogicalDiskObjectPath ) == DSKQUOTA_PROP_LogicalDiskObjectPath ) { LPWSTR lpLogicalDiskObjectPath; WCHAR t_DeviceId[3]; t_DeviceId[0] = w_Drive; t_DeviceId[1] = L':'; t_DeviceId[2] = L'\0'; m_CommonRoutine.MakeObjectPath ( lpLogicalDiskObjectPath, IDS_LogicalDiskClass, IDS_DeviceID, t_DeviceId ); if ( lpLogicalDiskObjectPath != NULL ) { try { if ( pInstance->SetWCHARSplat ( IDS_LogicalDiskObjectPath, lpLogicalDiskObjectPath ) == FALSE ) { hRes = WBEM_E_FAILED; } } catch ( ... ) { delete [] lpLogicalDiskObjectPath; throw; } delete [] lpLogicalDiskObjectPath; } } if (SUCCEEDED(hRes) && (( a_PropertiesReq & DSKQUOTA_PROP_UserObjectPath ) == DSKQUOTA_PROP_UserObjectPath) ) { // Obtaining the users logon Name CHString t_LogonName; WCHAR w_AccountContainer [ MAX_PATH + 1 ]; WCHAR w_DisplayName [ MAX_PATH + 1 ]; LPWSTR t_LogonNamePtr = t_LogonName.GetBuffer(MAX_PATH + 1); if ( SUCCEEDED ( pIQuotaUser->GetName ( w_AccountContainer, MAX_PATH, t_LogonNamePtr, MAX_PATH, w_DisplayName, MAX_PATH ) ) ) { t_LogonName.ReleaseBuffer(); // Have seen cases where GetName succeeds, but // the t_LogonName variable contains an empty string. if(t_LogonName.GetLength() > 0) { CHString t_DomainName; ExtractUserLogOnName ( t_LogonName, t_DomainName ); // 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. Hence the change below: CHString chstrNT_AUTHORITY; CHString chstrBuiltIn; if(!GetLocalizedNTAuthorityString(chstrNT_AUTHORITY) || !GetLocalizedBuiltInString(chstrBuiltIn)) { hRes = WBEM_E_FAILED; } if(SUCCEEDED(hRes)) { if(t_DomainName.CompareNoCase(chstrBuiltIn) == 0 || t_DomainName.CompareNoCase(chstrNT_AUTHORITY) == 0) { t_DomainName = m_ComputerName; } m_CommonRoutine.MakeObjectPath ( lpUserObjectPath, IDS_AccountClass, IDS_Domain, t_DomainName ); if ( lpUserObjectPath != NULL ) { m_CommonRoutine.AddToObjectPath ( lpUserObjectPath, IDS_Name, t_LogonName ); } if ( lpUserObjectPath != NULL ) { try { if ( pInstance->SetWCHARSplat ( IDS_UserObjectPath, lpUserObjectPath ) == FALSE ) { hRes = WBEM_E_FAILED; } } catch ( ... ) { delete [] lpUserObjectPath; throw; } delete [] lpUserObjectPath; } } } else { hRes = WBEM_E_FAILED; } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::AddUserOnVolume * * DESCRIPTION : In this method Adding a user on a volume that supports disk quota * *****************************************************************************/ HRESULT CDiskQuota :: AddUserOnVolume ( const CInstance &Instance, LPCWSTR a_VolumePathName, LPCWSTR a_UserLogonName ) { HRESULT hRes = WBEM_S_NO_ERROR; // Get all the properties and check for their validity. // all the properties should be provided // if the properties like limit and warning limit are not supplied // then they should be taken as default values specified on that volume. // Also disk space used will not be defined, only the user logon name will be given that will include // the domain name so that the logon name would be uniquely defined. CHString t_Key1; CHString t_Key2; if ( Instance.GetCHString ( IDS_LogicalDiskObjectPath , t_Key1 ) == FALSE ) { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { if ( Instance.GetCHString ( IDS_UserObjectPath , t_Key2 ) == FALSE ) { hRes = WBEM_E_FAILED ; } } if ( SUCCEEDED ( hRes ) ) { CHString t_VolumePath; GetKeyValue ( t_VolumePath,t_Key1 ); if (!t_VolumePath.IsEmpty()) { hRes = CheckParameters ( Instance ); } else { hRes = WBEM_E_FAILED; } if ( SUCCEEDED ( hRes ) ) { CHString t_VolumeName; // Get the key values, which will be the object path. // Now from the Volume Object path, parse out the volumename // from the User object path extract out the user Id. // for the volume specified check whether the given volume Supports Disk Quota if ( SUCCEEDED(m_CommonRoutine.VolumeSupportsDiskQuota ( a_VolumePathName, t_VolumeName ) ) ) { // Get IDIskQuotaCOntrol for this interface pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // Initialise the pIQuotaControl with the given volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, a_VolumePathName ); if ( SUCCEEDED ( hRes ) ) { IDiskQuotaUserPtr pIQuotaUser = NULL; hRes = pIQuotaControl->AddUserName( a_UserLogonName , DISKQUOTA_USERNAME_RESOLVE_SYNC, &pIQuotaUser ); if ( SUCCEEDED ( hRes ) ) { LONGLONG llLimit; Instance.GetWBEMINT64 ( IDS_QuotaLimit, llLimit ); hRes = pIQuotaUser->SetQuotaLimit ( llLimit, TRUE); if (SUCCEEDED(hRes)) { // Set the User Warning Limit Instance.GetWBEMINT64 ( IDS_QuotaWarningLimit, llLimit ); hRes = pIQuotaUser->SetQuotaThreshold ( llLimit, TRUE ); } } else if ( hRes == S_FALSE ) { hRes = WBEM_E_ALREADY_EXISTS ; } else { hRes = WBEM_E_INVALID_PARAMETER; } } } else { hRes = WBEM_E_FAILED; } } else { hRes = WBEM_E_FAILED; } } else { hRes = WBEM_E_FAILED; } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::UpdateUserQuotaProperties * * DESCRIPTION : In this method modifying a disk quota properties of a given user * on a given volume that supports disk quota * *****************************************************************************/ HRESULT CDiskQuota :: UpdateUserQuotaProperties ( const CInstance &Instance, LPCWSTR a_VolumePathName, LPCWSTR a_UserLogonName ) { HRESULT hRes = WBEM_S_NO_ERROR; CHString t_Key1; CHString t_Key2; if ( Instance.GetCHString ( IDS_LogicalDiskObjectPath , t_Key1 ) == FALSE ) { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { if ( Instance.GetCHString ( IDS_UserObjectPath , t_Key2 ) == FALSE ) { hRes = WBEM_E_FAILED ; } } if ( SUCCEEDED ( hRes ) ) { CHString t_VolumePath; GetKeyValue ( t_VolumePath ,t_Key1 ); if (!t_VolumePath.IsEmpty()) { hRes = CheckParameters ( Instance ); } else { hRes = WBEM_E_FAILED ; } if ( SUCCEEDED ( hRes ) ) { CHString t_VolumeName; if ( SUCCEEDED(m_CommonRoutine.VolumeSupportsDiskQuota ( a_VolumePathName, t_VolumeName )) ) { // Get IDIskQuotaCOntrol for this interface pointer IDiskQuotaControlPtr pIQuotaControl; if ( SUCCEEDED ( CoCreateInstance( CLSID_DiskQuotaControl, NULL, CLSCTX_INPROC_SERVER, IID_IDiskQuotaControl, (void **)&pIQuotaControl ) ) ) { // Initialise the pIQuotaControl with the given volume hRes = m_CommonRoutine.InitializeInterfacePointer ( pIQuotaControl, a_VolumePathName ); if ( SUCCEEDED ( hRes ) ) { IDiskQuotaUserPtr pIQuotaUser; hRes = pIQuotaControl->FindUserName( a_UserLogonName , &pIQuotaUser ); if ( SUCCEEDED ( hRes ) ) { LONGLONG llLimit; if (Instance.GetWBEMINT64 ( IDS_QuotaLimit, llLimit )) { hRes = pIQuotaUser->SetQuotaLimit ( llLimit, TRUE); } // Set the User Warning Limit if (SUCCEEDED(hRes) && Instance.GetWBEMINT64 ( IDS_QuotaWarningLimit, llLimit )) { hRes = pIQuotaUser->SetQuotaThreshold ( llLimit, TRUE ); } } else { hRes = WBEM_E_NOT_FOUND; } } } else { hRes = WBEM_E_FAILED; } } else { hRes = WBEM_E_FAILED; } } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::CheckParameters * * DESCRIPTION : In this method verifying the validity of the parameters * which are supplied in PutInstance by the user. * *****************************************************************************/ HRESULT CDiskQuota :: CheckParameters ( const CInstance &a_Instance ) { // Get all the Properties from the Instance to Verify HRESULT hRes = WBEM_S_NO_ERROR ; bool t_Exists ; VARTYPE t_Type ; if ( a_Instance.GetStatus ( IDS_QuotaLimit , t_Exists , t_Type ) ) { if ( t_Exists && ( t_Type == VT_BSTR ) ) { LONGLONG llLimit; if ( a_Instance.GetWBEMINT64 ( IDS_QuotaLimit , llLimit ) == FALSE ) { hRes = WBEM_E_INVALID_PARAMETER ; } } else if ( t_Exists == false ) { hRes = WBEM_E_INVALID_PARAMETER ; } } if ( a_Instance.GetStatus ( IDS_QuotaWarningLimit , t_Exists , t_Type ) ) { if ( t_Exists && ( t_Type == VT_BSTR ) ) { LONGLONG llLimit; if ( a_Instance.GetWBEMINT64 ( IDS_QuotaWarningLimit , llLimit ) == FALSE ) { hRes = WBEM_E_INVALID_PARAMETER ; } } else if ( t_Exists == false ) { hRes = WBEM_E_INVALID_PARAMETER ; } } return hRes; } /***************************************************************************** * * FUNCTION : CDiskQuota::SetPropertiesReq * * DESCRIPTION : In this method setting the properties required requested * by the user. * *****************************************************************************/ void CDiskQuota :: SetPropertiesReq ( CFrameworkQuery *Query, DWORD &a_PropertiesReq ) { a_PropertiesReq = 0; // being key this property needs to be delivered if ( Query->IsPropertyRequired ( IDS_LogicalDiskObjectPath ) ) { a_PropertiesReq |= DSKQUOTA_PROP_LogicalDiskObjectPath; } if ( Query->IsPropertyRequired ( IDS_UserObjectPath ) ) { a_PropertiesReq |= DSKQUOTA_PROP_UserObjectPath; } if ( Query->IsPropertyRequired ( IDS_QuotaStatus ) ) { a_PropertiesReq |= DSKQUOTA_PROP_Status; } if ( Query->IsPropertyRequired ( IDS_QuotaWarningLimit ) ) { a_PropertiesReq |= DSKQUOTA_PROP_WarningLimit; } if ( Query->IsPropertyRequired ( IDS_QuotaLimit ) ) { a_PropertiesReq |= DSKQUOTA_PROP_Limit; } if ( Query->IsPropertyRequired ( IDS_DiskSpaceUsed ) ) { a_PropertiesReq |= DSKQUOTA_PROP_DiskSpaceUsed; } } /***************************************************************************** * * FUNCTION : CDiskQuota::ExtractUserLogOnName * * DESCRIPTION : Here the user logon name is in the form * ComputerName\userlogonname or Domainname\Userlogonname * or eg like * builtin\adminitrator, where buildin is treated as a * domain name by the Win32_UserAccount class. Hence * we need to seperate the userlogon name and a domain name, * so that the keys will match the Win32_UserAccount class. * OR... * the name may be of the form: User@domain.something.com * *****************************************************************************/ void CDiskQuota :: ExtractUserLogOnName ( CHString &a_UserLogonName, CHString &a_DomainName ) { // Need the string "NT AUTHORITY". However, on non-english // builds, this is something else. Hence, get if from the // sid. PSID pSidNTAuthority = NULL; SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY; CHString cstrAuthorityDomain; if (AllocateAndInitializeSid (&sia ,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSidNTAuthority)) { try { CHString cstrName; GetDomainAndNameFromSid(pSidNTAuthority, cstrAuthorityDomain, cstrName); } catch(...) { FreeSid(pSidNTAuthority); throw; } FreeSid(pSidNTAuthority); } int iPos = a_UserLogonName.Find( L'\\'); // found backwhack: name is of the form domain\user if ( iPos != -1 ) { a_DomainName = a_UserLogonName.Left ( iPos ); // Win32_SystemAccount domain names are always the computer // name, never BUILTIN. The string BUILTIN is not localized. CHString chstrBuiltIn; if (GetLocalizedBuiltInString(chstrBuiltIn) && (a_DomainName.CompareNoCase(chstrBuiltIn) == 0)) { a_DomainName = m_ComputerName; } if(a_DomainName.CompareNoCase(cstrAuthorityDomain) == 0) { a_DomainName = m_ComputerName; } a_UserLogonName = a_UserLogonName.Right ( a_UserLogonName.GetLength() - (iPos + 1) ); } else { iPos = a_UserLogonName.Find( L'@'); // found 'at' - name is of the form user@domain.somesuch.com if (iPos != -1) { // start by slicing off everything after the @ a_DomainName = a_UserLogonName.Right(a_UserLogonName.GetLength() - (iPos + 1)); // keep the user name portion before we step on iPos a_UserLogonName = a_UserLogonName.Left ( iPos ); // now cut out everything after the first dot iPos = a_DomainName.Find(L'.'); if (iPos != -1) a_DomainName = a_DomainName.Left(iPos); } else // else we have a local account a_DomainName = m_ComputerName; } } /***************************************************************************** * * FUNCTION : CDiskQuota::GetKeyValue * * DESCRIPTION : From the object path we extract the key value * *****************************************************************************/ void CDiskQuota::GetKeyValue ( CHString &a_VolumePath, LPCWSTR a_ObjectPath ) { ParsedObjectPath *t_ObjPath; CObjectPathParser t_PathParser; a_VolumePath.Empty(); if ( ( t_PathParser.Parse( a_ObjectPath, &t_ObjPath ) ) == CObjectPathParser::NoError ) { try { if (t_ObjPath->m_dwNumKeys == 1) { if((V_VT(&t_ObjPath->m_paKeys [ 0 ]->m_vValue) == VT_BSTR) && (t_ObjPath->m_paKeys [ 0 ]->m_vValue.bstrVal != NULL) ) { a_VolumePath = t_ObjPath->m_paKeys [ 0 ]->m_vValue.bstrVal; } } else if (t_ObjPath->m_dwNumKeys == 2) { if ((V_VT(&t_ObjPath->m_paKeys [ 0 ]->m_vValue) == VT_BSTR) && (V_VT(&t_ObjPath->m_paKeys [ 1 ]->m_vValue) == VT_BSTR) && (t_ObjPath->m_paKeys [ 0 ]->m_vValue.bstrVal != NULL) && (t_ObjPath->m_paKeys [ 1 ]->m_vValue.bstrVal != NULL) ) { a_VolumePath.Format ( L"%s%s%s", t_ObjPath->m_paKeys [ 0 ]->m_vValue.bstrVal, L"\\", t_ObjPath->m_paKeys [ 1 ]->m_vValue.bstrVal ); } } } catch ( ... ) { t_PathParser.Free( t_ObjPath ); throw; } t_PathParser.Free( t_ObjPath ); } } BOOL CDiskQuota::GetDomainAndNameFromSid( PSID pSid, CHString& chstrDomain, CHString& chstrName) { BOOL fRet = FALSE; // Initialize account name and domain name LPTSTR pszAccountName = NULL; LPTSTR pszDomainName = NULL; DWORD dwAccountNameSize = 0; DWORD dwDomainNameSize = 0; SID_NAME_USE snuAccountType; try { // This call should fail fRet = ::LookupAccountSid(NULL, pSid, pszAccountName, &dwAccountNameSize, pszDomainName, &dwDomainNameSize, &snuAccountType ); if(fRet && (ERROR_INSUFFICIENT_BUFFER == ::GetLastError())) { // Allocate buffers if ( dwAccountNameSize != 0 ) { pszAccountName = (LPTSTR) malloc( dwAccountNameSize * sizeof(TCHAR)); if (pszAccountName == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } if ( dwDomainNameSize != 0 ) { pszDomainName = (LPTSTR) malloc( dwDomainNameSize * sizeof(TCHAR)); if (pszDomainName == NULL) { throw CHeap_Exception ( CHeap_Exception :: E_ALLOCATION_ERROR ) ; } } // Make second call fRet = ::LookupAccountSid( NULL, pSid, pszAccountName, &dwAccountNameSize, pszDomainName, &dwDomainNameSize, &snuAccountType ); if ( fRet == TRUE ) { chstrName = pszAccountName; chstrDomain = pszDomainName; } if ( NULL != pszAccountName ) { free ( pszAccountName ); pszAccountName = NULL; } if ( NULL != pszDomainName ) { free ( pszDomainName ); pszDomainName = NULL; } } // If ERROR_INSUFFICIENT_BUFFER } // try catch(...) { if ( NULL != pszAccountName ) { free ( pszAccountName ); pszAccountName = NULL; } if ( NULL != pszDomainName ) { free ( pszDomainName ); pszDomainName = NULL; } throw; } return fRet; }