382 lines
8.6 KiB
C++
382 lines
8.6 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1998 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
sisdrive.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
SIS Groveler SIS drive checker class
|
||
|
|
||
|
Authors:
|
||
|
|
||
|
John Douceur, 1998
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User Mode
|
||
|
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "all.hxx"
|
||
|
|
||
|
SISDrives::SISDrives()
|
||
|
{
|
||
|
num_partitions = 0;
|
||
|
num_lettered_partitions = 0;
|
||
|
partition_guid_names = 0;
|
||
|
partition_mount_names = 0;
|
||
|
|
||
|
buffer_size = 0;
|
||
|
buffer_index = 0;
|
||
|
buffer = 0;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
SISDrives::open()
|
||
|
{
|
||
|
num_partitions = 0;
|
||
|
num_lettered_partitions = 0;
|
||
|
partition_mount_names = 0;
|
||
|
|
||
|
int name_array_size = 1;
|
||
|
partition_guid_names = new int[name_array_size];
|
||
|
|
||
|
buffer_size = 256;
|
||
|
buffer_index = 0;
|
||
|
buffer = new _TCHAR[buffer_size];
|
||
|
|
||
|
SERVICE_CHECKPOINT();
|
||
|
Volumes volumes;
|
||
|
bool done = false;
|
||
|
|
||
|
//
|
||
|
// Enumerate all existing volumes getting their GUID names
|
||
|
//
|
||
|
|
||
|
while (!done)
|
||
|
{
|
||
|
DWORD error_code =
|
||
|
volumes.find(&buffer[buffer_index], buffer_size - buffer_index);
|
||
|
while (error_code != NO_ERROR)
|
||
|
{
|
||
|
if (error_code != ERROR_INSUFFICIENT_BUFFER &&
|
||
|
error_code != ERROR_BUFFER_OVERFLOW &&
|
||
|
error_code != ERROR_FILENAME_EXCED_RANGE)
|
||
|
{
|
||
|
done = true;
|
||
|
break;
|
||
|
}
|
||
|
resize_buffer();
|
||
|
SERVICE_CHECKPOINT();
|
||
|
error_code =
|
||
|
volumes.find(&buffer[buffer_index], buffer_size - buffer_index);
|
||
|
}
|
||
|
if (!done)
|
||
|
{
|
||
|
if (num_partitions >= name_array_size)
|
||
|
{
|
||
|
name_array_size *= 2;
|
||
|
int *new_name_array = new int[name_array_size];
|
||
|
memcpy(new_name_array,partition_guid_names,num_partitions * sizeof(int));
|
||
|
delete[] partition_guid_names;
|
||
|
partition_guid_names = new_name_array;
|
||
|
}
|
||
|
partition_guid_names[num_partitions] = buffer_index;
|
||
|
num_partitions++;
|
||
|
buffer_index += _tcslen(&buffer[buffer_index]) + 1;
|
||
|
}
|
||
|
SERVICE_CHECKPOINT();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Setup to scan for DRIVE LETTERS and MOUNT POINTS and correlate
|
||
|
// them with the drive letters.
|
||
|
//
|
||
|
|
||
|
partition_mount_names = new int[num_partitions];
|
||
|
int *next_indices = new int[num_partitions + 3];
|
||
|
int *work_list = &next_indices[num_partitions + 1];
|
||
|
int *scan_list = &next_indices[num_partitions + 2];
|
||
|
|
||
|
*scan_list = 0;
|
||
|
for (int index = 0; index < num_partitions; index++)
|
||
|
{
|
||
|
partition_mount_names[index] = -1;
|
||
|
next_indices[index] = index + 1;
|
||
|
}
|
||
|
next_indices[num_partitions - 1] = -1;
|
||
|
|
||
|
*work_list = num_partitions;
|
||
|
next_indices[num_partitions] = -1;
|
||
|
int work_list_end = num_partitions;
|
||
|
|
||
|
//
|
||
|
// Now that we have the GUID names, this will correlate the GUID names
|
||
|
// with the MOUNT names, this does both direct drive letters and
|
||
|
// mount point names.
|
||
|
//
|
||
|
|
||
|
while (*scan_list != -1 && *work_list != -1)
|
||
|
{
|
||
|
_TCHAR *mount_name = 0;
|
||
|
int mount_size = 0;
|
||
|
if (*work_list < num_partitions)
|
||
|
{
|
||
|
mount_name = &buffer[partition_mount_names[*work_list]];
|
||
|
mount_size = _tcslen(mount_name);
|
||
|
while (buffer_size - buffer_index <= mount_size)
|
||
|
{
|
||
|
resize_buffer();
|
||
|
}
|
||
|
_tcscpy(&buffer[buffer_index], mount_name);
|
||
|
}
|
||
|
|
||
|
VolumeMountPoints mount_points(mount_name);
|
||
|
|
||
|
//
|
||
|
// We have the next name, scan the list looking for that name
|
||
|
//
|
||
|
|
||
|
done = false;
|
||
|
while (!done)
|
||
|
{
|
||
|
DWORD error_code = mount_points.find(
|
||
|
&buffer[buffer_index + mount_size],
|
||
|
buffer_size - buffer_index - mount_size);
|
||
|
while (error_code != NO_ERROR)
|
||
|
{
|
||
|
if (error_code != ERROR_INSUFFICIENT_BUFFER &&
|
||
|
error_code != ERROR_BUFFER_OVERFLOW &&
|
||
|
error_code != ERROR_FILENAME_EXCED_RANGE)
|
||
|
{
|
||
|
done = true;
|
||
|
break;
|
||
|
}
|
||
|
resize_buffer();
|
||
|
SERVICE_CHECKPOINT();
|
||
|
error_code = mount_points.find(
|
||
|
&buffer[buffer_index + mount_size],
|
||
|
buffer_size - buffer_index - mount_size);
|
||
|
}
|
||
|
if (!done)
|
||
|
{
|
||
|
_TCHAR volume_guid_name[MAX_PATH + 1];
|
||
|
|
||
|
BOOL ok = GetVolumeNameForVolumeMountPoint(
|
||
|
&buffer[buffer_index], volume_guid_name, MAX_PATH + 1);
|
||
|
if (!ok)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
int scan_index = *scan_list;
|
||
|
int prev_index = num_partitions + 2;
|
||
|
while (scan_index >= 0)
|
||
|
{
|
||
|
_TCHAR *scan_name =
|
||
|
&buffer[partition_guid_names[scan_index]];
|
||
|
if (_tcscmp(scan_name, volume_guid_name) == 0)
|
||
|
{
|
||
|
partition_mount_names[scan_index] = buffer_index;
|
||
|
buffer_index += _tcslen(&buffer[buffer_index]) + 1;
|
||
|
next_indices[prev_index] = next_indices[scan_index];
|
||
|
next_indices[scan_index] = -1;
|
||
|
next_indices[work_list_end] = scan_index;
|
||
|
work_list_end = scan_index;
|
||
|
if (mount_name) {
|
||
|
_tcscpy(&buffer[buffer_index], mount_name); //get ready for next time through the loop
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
prev_index = scan_index;
|
||
|
scan_index = next_indices[scan_index];
|
||
|
SERVICE_CHECKPOINT();
|
||
|
}
|
||
|
}
|
||
|
SERVICE_CHECKPOINT();
|
||
|
}
|
||
|
*work_list = next_indices[*work_list];
|
||
|
SERVICE_CHECKPOINT();
|
||
|
}
|
||
|
delete[] next_indices;
|
||
|
next_indices = 0;
|
||
|
|
||
|
//
|
||
|
// We are now going to sort all of the drive letter entries to the front
|
||
|
// this does keep the driver letter/guid name correlation intact.
|
||
|
//
|
||
|
|
||
|
index = 0;
|
||
|
while (index < num_partitions)
|
||
|
{
|
||
|
if (partition_mount_names[index] < 0 ||
|
||
|
!is_sis_drive(&buffer[partition_guid_names[index]]))
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// The given entry either doesn't have a name or SIS is
|
||
|
// not currently running on the volume. Move it to the end
|
||
|
// of the list.
|
||
|
|
||
|
int temp = partition_guid_names[index];
|
||
|
partition_guid_names[index] =
|
||
|
partition_guid_names[num_partitions - 1];
|
||
|
partition_guid_names[num_partitions - 1] = temp;
|
||
|
temp = partition_mount_names[index];
|
||
|
partition_mount_names[index] =
|
||
|
partition_mount_names[num_partitions - 1];
|
||
|
partition_mount_names[num_partitions - 1] = temp;
|
||
|
num_partitions--;
|
||
|
continue;
|
||
|
}
|
||
|
if (buffer[partition_mount_names[index] + 3] == _T('\0'))
|
||
|
{
|
||
|
//
|
||
|
// If this is a drive letter (not a mount point) then
|
||
|
// it will be moved to the front of the list
|
||
|
//
|
||
|
|
||
|
int temp = partition_guid_names[index];
|
||
|
partition_guid_names[index] =
|
||
|
partition_guid_names[num_lettered_partitions];
|
||
|
partition_guid_names[num_lettered_partitions] = temp;
|
||
|
temp = partition_mount_names[index];
|
||
|
partition_mount_names[index] =
|
||
|
partition_mount_names[num_lettered_partitions];
|
||
|
partition_mount_names[num_lettered_partitions] = temp;
|
||
|
num_lettered_partitions++;
|
||
|
}
|
||
|
index++;
|
||
|
SERVICE_CHECKPOINT();
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
TRACE_PRINTF(TC_sisdrive,2,
|
||
|
(_T("Num Partitions=%d\nNum Lettered_partitions=%d\n"),
|
||
|
num_partitions,
|
||
|
num_lettered_partitions));
|
||
|
|
||
|
for (index=0;index < num_partitions;index++)
|
||
|
{
|
||
|
TRACE_PRINTF(TC_sisdrive,2,
|
||
|
(_T("Name=\"%s\" GuidName=\"%s\"\n"),
|
||
|
&buffer[partition_mount_names[index]],
|
||
|
&buffer[partition_guid_names[index]]));
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
SISDrives::~SISDrives()
|
||
|
{
|
||
|
if (partition_guid_names != 0)
|
||
|
{
|
||
|
delete[] partition_guid_names;
|
||
|
partition_guid_names = 0;
|
||
|
}
|
||
|
if (partition_mount_names != 0)
|
||
|
{
|
||
|
delete[] partition_mount_names;
|
||
|
partition_mount_names = 0;
|
||
|
}
|
||
|
if (buffer != 0)
|
||
|
{
|
||
|
delete[] buffer;
|
||
|
buffer = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int SISDrives::partition_count() const
|
||
|
{
|
||
|
return num_partitions;
|
||
|
}
|
||
|
|
||
|
int SISDrives::lettered_partition_count() const
|
||
|
{
|
||
|
return num_lettered_partitions;
|
||
|
}
|
||
|
|
||
|
_TCHAR * SISDrives::partition_guid_name(
|
||
|
int partition_index) const
|
||
|
{
|
||
|
if (partition_index < num_partitions)
|
||
|
{
|
||
|
return &buffer[partition_guid_names[partition_index]];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
_TCHAR * SISDrives::partition_mount_name(
|
||
|
int partition_index) const
|
||
|
{
|
||
|
if (partition_index < num_partitions)
|
||
|
{
|
||
|
return &buffer[partition_mount_names[partition_index]];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
SISDrives::is_sis_drive(
|
||
|
_TCHAR *drive_name)
|
||
|
{
|
||
|
UINT drive_type = GetDriveType(drive_name);
|
||
|
if (drive_type != DRIVE_FIXED)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
_TCHAR fs_name[8];
|
||
|
BOOL ok = GetVolumeInformation(drive_name, 0, 0, 0, 0, 0, fs_name, 8);
|
||
|
if (!ok)
|
||
|
{
|
||
|
DWORD err = GetLastError();
|
||
|
PRINT_DEBUG_MSG((_T("GROVELER: GetVolumeInformation() failed with error %d\n"),
|
||
|
err));
|
||
|
return false;
|
||
|
}
|
||
|
if (_tcsicmp(fs_name, _T("NTFS")) != 0)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
int drive_name_len = _tcslen(drive_name);
|
||
|
_TCHAR *sis_directory =
|
||
|
new _TCHAR[SIS_CSDIR_STRING_NCHARS + drive_name_len];
|
||
|
_tcscpy(sis_directory, drive_name);
|
||
|
_tcscpy(&sis_directory[drive_name_len - 1], SIS_CSDIR_STRING);
|
||
|
ok = SetCurrentDirectory(sis_directory);
|
||
|
delete[] sis_directory;
|
||
|
sis_directory = 0;
|
||
|
if (!ok)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
BOOL sis_installed = Groveler::is_sis_installed(drive_name);
|
||
|
if (!sis_installed)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void SISDrives::resize_buffer()
|
||
|
{
|
||
|
buffer_size *= 2;
|
||
|
_TCHAR *new_buffer = new _TCHAR[buffer_size];
|
||
|
|
||
|
memcpy(new_buffer, buffer, buffer_index * sizeof(_TCHAR));
|
||
|
|
||
|
delete[] buffer;
|
||
|
buffer = new_buffer;
|
||
|
}
|