566 lines
13 KiB
C++
566 lines
13 KiB
C++
// Copyright (c) 1997-2001 Microsoft Corporation
|
|
//
|
|
// File: FileInstallationUnit.cpp
|
|
//
|
|
// Synopsis: Defines a FileInstallationUnit
|
|
// This object has the knowledge for installing the
|
|
// quotas on disk usage and such
|
|
//
|
|
// History: 02/06/2001 JeffJon Created
|
|
|
|
#include "pch.h"
|
|
#include "resource.h"
|
|
|
|
#include "FileInstallationUnit.h"
|
|
#include "state.h"
|
|
#include "InstallationUnitProvider.h"
|
|
|
|
#define INITGUIDS // This has to be present so the the GUIDs defined
|
|
// in dskquota.h can be linked
|
|
#include <dskquota.h>
|
|
|
|
|
|
// REVIEW_JEFFJON : are there equivalents that could just be included???
|
|
#define CYS_KB 1024
|
|
#define CYS_MB 1048576
|
|
#define CYS_GB 1073741824
|
|
|
|
|
|
// Finish page help
|
|
static PCWSTR CYS_FILE_FINISH_PAGE_HELP = L"cys.chm::/cys_configuring_file_server.htm";
|
|
|
|
|
|
FileInstallationUnit::FileInstallationUnit() :
|
|
spaceQuotaSize(QUOTA_SIZE_KB),
|
|
levelQuotaSize(QUOTA_SIZE_KB),
|
|
spaceQuotaValue(1),
|
|
levelQuotaValue(1),
|
|
setDefaultQuotas(false),
|
|
denyUsersOverQuota(false),
|
|
eventDiskSpaceLimit(false),
|
|
eventWarningLevel(false),
|
|
InstallationUnit(
|
|
IDS_FILE_SERVER_TYPE,
|
|
IDS_FILE_SERVER_DESCRIPTION,
|
|
CYS_FILE_FINISH_PAGE_HELP,
|
|
FILESERVER_INSTALL)
|
|
{
|
|
LOG_CTOR(FileInstallationUnit);
|
|
}
|
|
|
|
|
|
FileInstallationUnit::~FileInstallationUnit()
|
|
{
|
|
LOG_DTOR(FileInstallationUnit);
|
|
}
|
|
|
|
|
|
InstallationReturnType
|
|
FileInstallationUnit::InstallService(HANDLE logfileHandle, HWND /*hwnd*/)
|
|
{
|
|
LOG_FUNCTION(FileInstallationUnit::InstallService);
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_FILE_SERVER));
|
|
|
|
InstallationReturnType result = INSTALL_SUCCESS;
|
|
|
|
bool bChangeMade = false;
|
|
|
|
// Set the default disk quotas if chosen by the user
|
|
|
|
if (setDefaultQuotas)
|
|
{
|
|
LOG(L"Setting default disk quotas");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_FILE_SERVER_SET_QUOTAS));
|
|
|
|
WriteDiskQuotas(logfileHandle);
|
|
bChangeMade = true;
|
|
}
|
|
|
|
// Turn on or off the indexing service as chosen by the user
|
|
|
|
HRESULT indexingResult = S_OK;
|
|
|
|
if (IsIndexingServiceOn() &&
|
|
!GetInstallIndexingService())
|
|
{
|
|
indexingResult = StopIndexingService();
|
|
if (SUCCEEDED(indexingResult))
|
|
{
|
|
LOG(L"Stop indexing service succeeded");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_INDEXING_STOP_SUCCEEDED));
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Stop indexing server failed");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_INDEXING_STOP_FAILED));
|
|
|
|
// REVIEW_JEFFJON : need to log error values
|
|
}
|
|
bChangeMade = true;
|
|
}
|
|
else if (!IsIndexingServiceOn() &&
|
|
GetInstallIndexingService())
|
|
{
|
|
indexingResult = StartIndexingService();
|
|
if (SUCCEEDED(indexingResult))
|
|
{
|
|
LOG(L"Start indexing service succeeded");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_INDEXING_START_SUCCEEDED));
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Start indexing server failed");
|
|
|
|
CYS_APPEND_LOG(String::load(IDS_LOG_INDEXING_START_FAILED));
|
|
|
|
// REVIEW_JEFFJON : need to log error values
|
|
}
|
|
bChangeMade = true;
|
|
}
|
|
|
|
if (!bChangeMade)
|
|
{
|
|
result = INSTALL_NO_CHANGES;
|
|
}
|
|
else
|
|
{
|
|
if (FAILED(indexingResult))
|
|
{
|
|
result = INSTALL_FAILURE;
|
|
}
|
|
}
|
|
|
|
LOG_INSTALL_RETURN(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
FileInstallationUnit::IsServiceInstalled()
|
|
{
|
|
LOG_FUNCTION(FileInstallationUnit::IsServiceInstalled);
|
|
|
|
bool result = false;
|
|
|
|
if (!State::GetInstance().HasNTFSDrive() &&
|
|
InstallationUnitProvider::GetInstance().GetSharePointInstallationUnit().IsServiceInstalled())
|
|
{
|
|
// There are no NTFS partitions and SharePoint is installed
|
|
// so we can't set disk quotas or turn off the indexing service
|
|
|
|
result = true;
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
FileInstallationUnit::GetFinishText(String& message)
|
|
{
|
|
LOG_FUNCTION(FileInstallationUnit::GetFinishText);
|
|
|
|
bool result = true;
|
|
|
|
bool quotasTextSet = false;
|
|
if (GetDefaultQuotas())
|
|
{
|
|
message += String::load(IDS_FILE_FINISH_DISK_QUOTAS);
|
|
quotasTextSet = true;
|
|
}
|
|
|
|
bool indexingTextSet = false;
|
|
if (IsIndexingServiceOn() &&
|
|
!GetInstallIndexingService())
|
|
{
|
|
message += String::load(IDS_FILE_FINISH_INDEXING_OFF);
|
|
indexingTextSet = true;
|
|
}
|
|
else if (!IsIndexingServiceOn() &&
|
|
GetInstallIndexingService())
|
|
{
|
|
message += String::load(IDS_FILE_FINISH_INDEXING_ON);
|
|
indexingTextSet = true;
|
|
}
|
|
else
|
|
{
|
|
// nothing needs to be done since they are leaving it in the same state
|
|
|
|
indexingTextSet = false;
|
|
}
|
|
|
|
if (!quotasTextSet &&
|
|
!indexingTextSet)
|
|
{
|
|
message += String::load(IDS_FINISH_NO_CHANGES);
|
|
result = false;
|
|
}
|
|
|
|
LOG_BOOL(result);
|
|
return result;
|
|
}
|
|
|
|
String
|
|
FileInstallationUnit::GetServiceDescription()
|
|
{
|
|
LOG_FUNCTION(FileInstallationUnit::GetServiceDescription);
|
|
|
|
// Dynamically determine the string based on the availability
|
|
// of services
|
|
|
|
bool isSharePointInstalled =
|
|
InstallationUnitProvider::GetInstance().GetSharePointInstallationUnit().IsServiceInstalled();
|
|
|
|
unsigned int resourceID = static_cast<unsigned int>(-1);
|
|
|
|
if (State::GetInstance().HasNTFSDrive())
|
|
{
|
|
if (isSharePointInstalled)
|
|
{
|
|
resourceID = IDS_FILESERVER_QUOTAS_SHAREPOINT;
|
|
}
|
|
else
|
|
{
|
|
resourceID = IDS_FILESERVER_QUOTAS_NO_SHAREPOINT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (isSharePointInstalled)
|
|
{
|
|
resourceID = IDS_FILESERVER_NO_QUOTAS_SHAREPOINT;
|
|
}
|
|
else
|
|
{
|
|
resourceID = IDS_FILESERVER_NO_QUOTAS_NO_SHAREPOINT;
|
|
}
|
|
}
|
|
|
|
ASSERT(resourceID != static_cast<unsigned int>(-1));
|
|
|
|
description = String::load(resourceID);
|
|
|
|
return description;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetSpaceQuotaSize(QuotaSizeType size)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetSpaceQuotaSize,
|
|
String::format(L"%1!d!", size));
|
|
|
|
spaceQuotaSize = size;
|
|
}
|
|
|
|
void
|
|
FileInstallationUnit::SetLevelQuotaSize(QuotaSizeType size)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetLevelQuotaSize,
|
|
String::format(L"%1!d!", size));
|
|
|
|
levelQuotaSize = size;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetSpaceQuotaValue(LONGLONG value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetSpaceQuotaValue,
|
|
String::format(L"%1!I64d!", value));
|
|
|
|
spaceQuotaValue = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetLevelQuotaValue(LONGLONG value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetLevelQuotaValue,
|
|
String::format(L"%1!I64d!", value));
|
|
|
|
levelQuotaValue = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetDefaultQuotas(bool value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetDefaultQuotas,
|
|
value ? L"true" : L"false");
|
|
|
|
setDefaultQuotas = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetDenyUsersOverQuota(bool value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetDenyUsersOverQuota,
|
|
value ? L"true" : L"false");
|
|
|
|
denyUsersOverQuota = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetEventDiskSpaceLimit(bool value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetEventDiskSpaceLimit,
|
|
value ? L"true" : L"false");
|
|
|
|
eventDiskSpaceLimit = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::SetEventWarningLevel(bool value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetEventWarningLevel,
|
|
value ? L"true" : L"false");
|
|
|
|
eventWarningLevel = value;
|
|
}
|
|
|
|
void
|
|
FileInstallationUnit::SetInstallIndexingService(bool value)
|
|
{
|
|
LOG_FUNCTION2(
|
|
FileInstallationUnit::SetInstallIndexingService,
|
|
value ? L"true" : L"false");
|
|
|
|
installIndexingService = value;
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::WriteDiskQuotas(HANDLE logfileHandle)
|
|
{
|
|
LOG_FUNCTION(FileInstallationUnit::WriteDiskQuotas);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
bool wasSomethingSet = false;
|
|
|
|
do
|
|
{
|
|
|
|
// Calculate the new values
|
|
|
|
LONGLONG newSpaceQuota = 0;
|
|
ConvertValueBySizeType(spaceQuotaValue, spaceQuotaSize, newSpaceQuota);
|
|
|
|
LONGLONG newLevelQuota = 0;
|
|
ConvertValueBySizeType(levelQuotaValue, levelQuotaSize, newLevelQuota);
|
|
|
|
DWORD logFlags = 0;
|
|
logFlags |= eventDiskSpaceLimit ? DISKQUOTA_LOGFLAG_USER_LIMIT : 0;
|
|
logFlags |= eventWarningLevel ? DISKQUOTA_LOGFLAG_USER_THRESHOLD : 0;
|
|
|
|
DWORD quotaState = denyUsersOverQuota ? DISKQUOTA_STATE_ENFORCE : DISKQUOTA_STATE_TRACK;
|
|
|
|
|
|
// Get a list of the valid drives
|
|
|
|
StringVector dl;
|
|
hr = FS::GetValidDrives(std::back_inserter(dl));
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(L"Failed to GetValidDrives: hr = %1!x!", hr));
|
|
break;
|
|
}
|
|
|
|
// Loop through the list
|
|
|
|
ASSERT(dl.size());
|
|
for (
|
|
StringVector::iterator i = dl.begin();
|
|
i != dl.end();
|
|
++i)
|
|
{
|
|
// For each drive that supports disk quotas set the new values
|
|
|
|
// Create a Disk Quota Control
|
|
// Multiple initializations of this object are not allowed so
|
|
// I have to create a new instance each time through the loop
|
|
|
|
SmartInterface<IDiskQuotaControl> diskQuotaControl;
|
|
hr = diskQuotaControl.AcquireViaCreateInstance(
|
|
CLSID_DiskQuotaControl,
|
|
0,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IDiskQuotaControl);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Failed to create a disk quota control: hr = %1!x!",
|
|
hr));
|
|
break;
|
|
}
|
|
|
|
hr = diskQuotaControl->Initialize(
|
|
i->c_str(),
|
|
TRUE);
|
|
if (FAILED(hr))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"Setting quotas on drive %1",
|
|
i->c_str()));
|
|
|
|
// Turn on the disk quotas
|
|
|
|
hr = diskQuotaControl->SetQuotaState(quotaState);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Disk quota set on drive %1",
|
|
i->c_str()));
|
|
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_DRIVE_FORMAT),
|
|
i->c_str()));
|
|
|
|
if(denyUsersOverQuota)
|
|
{
|
|
LOG(L"Disk space denied to users exceeding limit");
|
|
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_DENY_FORMAT),
|
|
newSpaceQuota));
|
|
}
|
|
else
|
|
{
|
|
LOG(L"Disk space is not denied to users exceeding limit");
|
|
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_NOT_DENY_FORMAT),
|
|
newSpaceQuota));
|
|
}
|
|
wasSomethingSet = true;
|
|
}
|
|
|
|
// Set the default quota limit
|
|
|
|
hr = diskQuotaControl->SetDefaultQuotaLimit(newSpaceQuota);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Disk space limited to %1!I64d!",
|
|
newSpaceQuota));
|
|
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_LIMIT_FORMAT),
|
|
newSpaceQuota));
|
|
|
|
wasSomethingSet = true;
|
|
}
|
|
|
|
// Set the warning level threshold
|
|
|
|
hr = diskQuotaControl->SetDefaultQuotaThreshold(newLevelQuota);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LOG(String::format(
|
|
L"Disk threshold set to %1!I64d!",
|
|
newLevelQuota));
|
|
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_THRESHOLD_FORMAT),
|
|
newLevelQuota));
|
|
|
|
wasSomethingSet = true;
|
|
}
|
|
|
|
// Set the event flags
|
|
|
|
hr = diskQuotaControl->SetQuotaLogFlags(logFlags);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (eventDiskSpaceLimit)
|
|
{
|
|
LOG(L"An event is logged when a user exceeds disk space limit");
|
|
|
|
CYS_APPEND_LOG(
|
|
String::load(IDS_LOG_DISK_QUOTA_LOG_LIMIT));
|
|
}
|
|
|
|
if (eventWarningLevel)
|
|
{
|
|
|
|
LOG(L"An event is logged when a user exceeds the warning limit");
|
|
|
|
CYS_APPEND_LOG(
|
|
String::load(IDS_LOG_DISK_QUOTA_LOG_WARNING));
|
|
}
|
|
wasSomethingSet = true;
|
|
}
|
|
}
|
|
} while (false);
|
|
|
|
if (FAILED(hr) && !wasSomethingSet)
|
|
{
|
|
CYS_APPEND_LOG(
|
|
String::format(
|
|
String::load(IDS_LOG_DISK_QUOTA_FAILED),
|
|
hr));
|
|
}
|
|
|
|
LOG(String::format(
|
|
L"hr = %1!x!",
|
|
hr));
|
|
|
|
}
|
|
|
|
|
|
void
|
|
FileInstallationUnit::ConvertValueBySizeType(
|
|
LONGLONG value,
|
|
QuotaSizeType sizeType,
|
|
LONGLONG& newValue)
|
|
{
|
|
int multiplier = 0;
|
|
switch (sizeType)
|
|
{
|
|
case QUOTA_SIZE_KB :
|
|
multiplier = CYS_KB;
|
|
break;
|
|
|
|
case QUOTA_SIZE_MB :
|
|
multiplier = CYS_MB;
|
|
break;
|
|
|
|
case QUOTA_SIZE_GB :
|
|
multiplier = CYS_GB;
|
|
break;
|
|
|
|
default :
|
|
ASSERT(false);
|
|
break;
|
|
}
|
|
|
|
newValue = value * multiplier;
|
|
}
|