|
|
/*++
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; }
|