#include "precomp.h" #pragma hdrstop /*++ Copyright (c) 1990 Microsoft Corporation Module Name: det_vol.c Abstract: Disk/volume related detect operations for Win32 PDK Setup. This module has no external dependencies and is not statically linked to any part of Setup. Author: Ted Miller (tedm) June-August 1991 --*/ #define SPACE_FREE 1 #define SPACE_TOTAL 2 #define DRIVE_TYPE_REMOVABLE "RMV" #define DRIVE_TYPE_FIXED "FIX" #define DRIVE_TYPE_REMOTE "REM" #define DRIVE_TYPE_CDROM "CDR" #define DRIVE_TYPE_RAMDISK "RAM" #define DRIVE_TYPE_UNKNOWN "?" #define GET_TIME_CREATION 1 #define GET_TIME_LASTACCESS 2 #define GET_TIME_LASTWRITE 3 CB GetTimeOfFile(RGSZ,USHORT,SZ,CB,DWORD); CB GetDrivesWorker(RGSZ,USHORT,SZ,CB,DWORD); DWORD AreDrivesACertainType(DWORD,BOOL *); VOID ConstructDiskList(BOOL *,LPSTR); CB GetSpaceWorker(SZ,CB,DWORD); // // Routine to get a drive type. Like GetDriveType() win32 api except // it attempts to differentiate between removable hard drives and floppies. // Removeable hard drives will returned as DRIVE_FIXED so we can use // DRIVE_REMOVABLE as a symonym for "floppy." // UINT MyGetDriveType( IN PSTR DriveName ) { CHAR DriveNameNt[MAX_PATH]; UINT rc; // // First, get the win32 drive type. If it tells us DRIVE_REMOVABLE, // then we need to see whether it's a floppy or hard disk. Otherwise // just believe the api. // if((rc = GetDriveType(DriveName)) == DRIVE_REMOVABLE) { if(DosPathToNtPathWorker(DriveName,DriveNameNt)) { CharLower(DriveNameNt); if(!strstr(DriveNameNt,"floppy")) { rc = DRIVE_FIXED; } } } return(rc); } // // Gets unused drives // CB GetUnusedDrives( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { SZ sz; RGSZ rgsz; DWORD Disk; CHAR szRoot[4] = "?:\\"; CHAR szDrive[3] = "?:"; CB cbRet; Unused( Args ); Unused( cArgs ); Unused( cbReturnBuffer ); rgsz = RgszAlloc(1); for( Disk = 26; Disk > 0; Disk-- ) { szRoot[0] = (CHAR)(Disk - 1) + (CHAR)'A'; if ( MyGetDriveType( szRoot ) == 1 ) { szDrive[0] = szRoot[0]; RgszAdd( &rgsz, SzDup( szDrive ) ); } } sz = SzListValueFromRgsz( rgsz ); lstrcpy( ReturnBuffer, sz ); cbRet = lstrlen( sz ); SFree( sz ); RgszFree( rgsz ); return( cbRet + 1 ); } // // Gets the type of a drive // CB GetTypeOfDrive( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { SZ szType; CHAR szRoot[ MAX_PATH]; SZ sz; Unused( cbReturnBuffer ); if ( (cArgs >= 1) && (*(Args[0]) != '\0') ) { lstrcpy( szRoot, Args[0] ); sz = szRoot + strlen(szRoot) -1; if ( *sz != '\\' ) { strcat( szRoot, "\\" ); } switch (MyGetDriveType( szRoot )) { case 0: case 1: return 0; case DRIVE_REMOVABLE: szType = DRIVE_TYPE_REMOVABLE; break; case DRIVE_FIXED: szType = DRIVE_TYPE_FIXED; break; case DRIVE_REMOTE: szType = DRIVE_TYPE_REMOTE; break; case DRIVE_CDROM: szType = DRIVE_TYPE_CDROM; break; case DRIVE_RAMDISK: szType = DRIVE_TYPE_RAMDISK; break; default: szType = DRIVE_TYPE_UNKNOWN; break; } } else { szType= DRIVE_TYPE_UNKNOWN; } lstrcpy( ReturnBuffer, szType ); return lstrlen( ReturnBuffer )+1; } // // Determines the existence of a directory // CB DoesDirExist( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { DWORD Attr; Unused( cbReturnBuffer ); if ( cArgs == 0 ) { ReturnBuffer[0] = '\0'; return 0; } else { Attr = GetFileAttributes( Args[0] ); if ((Attr != -1) && ( Attr & FILE_ATTRIBUTE_DIRECTORY )) { lstrcpy( ReturnBuffer, "YES" ); } else { lstrcpy( ReturnBuffer, "NO" ); } } return lstrlen(ReturnBuffer)+1; } // // Determines the existence of a file // CB DoesFileExist( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { DWORD Attr; Unused( cbReturnBuffer ); if ( cArgs == 0 ) { ReturnBuffer[0] = '\0'; return 0; } else { Attr = GetFileAttributes( Args[0] ); if ((Attr != -1) && !( Attr & FILE_ATTRIBUTE_DIRECTORY )) { lstrcpy( ReturnBuffer, "YES" ); } else { lstrcpy( ReturnBuffer, "NO" ); } } return lstrlen(ReturnBuffer)+1; } // // Get file size // CB GetSizeOfFile( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { HANDLE hff; WIN32_FIND_DATA ffd; DWORD Size = 0; #define ZERO_SIZE "0" Unused( cbReturnBuffer ); ReturnBuffer[0] = '\0'; if (cArgs > 0) { // // get find file information and get the size information out of // that // if ((hff = FindFirstFile(Args[0], &ffd)) != INVALID_HANDLE_VALUE) { Size = ffd.nFileSizeLow; _ltoa(Size, ReturnBuffer, 10); FindClose(hff); return lstrlen(ReturnBuffer)+1; } } // // If file not specified or file not found default return 0 size // lstrcpy( ReturnBuffer, ZERO_SIZE ); return lstrlen(ReturnBuffer)+1; } // // Obtains creation time of a file // CB GetFileCreationTime( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_CREATION ); } // // Obtains last access time of a file // CB GetFileLastAccessTime( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_LASTACCESS ); } // // Obtains last write time of a file // CB GetFileLastWriteTime( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_LASTWRITE ); } // // Obtains any time of a file // CB GetTimeOfFile( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer, IN DWORD WhatTime ) { HANDLE Handle; FILETIME TimeCreation; FILETIME TimeLastAccess; FILETIME TimeLastWrite; FILETIME WantedTime; Unused( cbReturnBuffer ); ReturnBuffer[0] = '\0'; if ( ( cArgs > 0) && (WhatTime >= GET_TIME_CREATION) && (WhatTime <= GET_TIME_LASTWRITE) ) { Handle = CreateFile( Args[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ( Handle != INVALID_HANDLE_VALUE ) { if ( GetFileTime( Handle, &TimeCreation, &TimeLastAccess, &TimeLastWrite ) ) { switch( WhatTime ) { case GET_TIME_CREATION: WantedTime = TimeCreation; break; case GET_TIME_LASTACCESS: WantedTime = TimeLastAccess; break; case GET_TIME_LASTWRITE: WantedTime = TimeLastWrite; break; default: break; } } CloseHandle( Handle ); wsprintf( ReturnBuffer, "{\"%lu\",\"%lu\"}", WantedTime.dwLowDateTime, WantedTime.dwHighDateTime ); return lstrlen(ReturnBuffer)+1; } } return 0; } /* Return a list of floppy drive letters */ CB GetFloppyDriveLetters( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { return(GetDrivesWorker(Args, cArgs, ReturnBuffer, cbReturnBuffer, DRIVE_REMOVABLE ) ); } /* Return a list of hard drive letters */ CB GetHardDriveLetters( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { return(GetDrivesWorker(Args, cArgs, ReturnBuffer, cbReturnBuffer, DRIVE_FIXED ) ); } /* Return a list of filesystems on all hard drive volumes. */ CB GetHardDriveFileSystems( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { BOOL HardDisk[26]; DWORD Disk; LPSTR InsertPoint = ReturnBuffer; char DiskName[4] = { 'x',':','\\','\0' }; char FileSys[MAX_PATH]; DWORD SizeSoFar; UINT ErrorMode; Unused(Args); Unused(cArgs); AreDrivesACertainType(DRIVE_FIXED,HardDisk); *InsertPoint++ = '{'; SizeSoFar = 2; ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX ); for(Disk=0; Disk<26; Disk++) { if(HardDisk[Disk]) { DiskName[0] = (char)Disk + (char)'A'; if(!GetVolumeInformation(DiskName,NULL,0,NULL,NULL,NULL,FileSys,sizeof(FileSys))) { *FileSys = '\0'; } else if(!lstrcmpi(FileSys,"raw")) { *FileSys = '\0'; } SizeSoFar += lstrlen(FileSys)+3; // 3 is for "", if(SizeSoFar > cbReturnBuffer) { SetErrorMode( ErrorMode ); return(SizeSoFar); } *InsertPoint++ = '"'; lstrcpy(InsertPoint,FileSys); InsertPoint = strchr(InsertPoint,0); *InsertPoint++ = '"'; *InsertPoint++ = ','; } } if(*(InsertPoint-1) == ',') { *(InsertPoint-1) = '}'; // overwrite final comma } else { if(++SizeSoFar > cbReturnBuffer) { SetErrorMode( ErrorMode ); return(SizeSoFar); } *InsertPoint++ = '}'; } *InsertPoint = '\0'; SetErrorMode( ErrorMode ); return(lstrlen(ReturnBuffer)+1); } /* Return a list of ASCII representations of free space on all hard disk volumes */ CB GetHardDriveFreeSpace( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { CB Size; UINT ErrorMode; Unused(Args); Unused(cArgs); ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX ); Size = GetSpaceWorker(ReturnBuffer,cbReturnBuffer,SPACE_FREE); SetErrorMode( ErrorMode ); return(Size); } /* Return a list of ASCII representations of total space on all hard disk volumes */ CB GetHardDriveTotalSpace( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer ) { CB Size; UINT ErrorMode; Unused(Args); Unused(cArgs); ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX ); Size = GetSpaceWorker(ReturnBuffer,cbReturnBuffer,SPACE_TOTAL); SetErrorMode( ErrorMode ); return(Size); } /****************************************************************** Subroutines */ CB GetDrivesWorker( IN RGSZ Args, IN USHORT cArgs, OUT SZ ReturnBuffer, IN CB cbReturnBuffer, IN DWORD TypeOfDrive ) { char DriveName[4] = { 'x',':','\\','\0' }; BOOL IsValid[26]; DWORD NumMatches; DWORD SpaceRequired; Unused(Args); Unused(cArgs); NumMatches = AreDrivesACertainType(TypeOfDrive,IsValid); SpaceRequired = (NumMatches * 5) + 3 - 1; if(cbReturnBuffer < SpaceRequired) { return(SpaceRequired); } else { ConstructDiskList(IsValid,ReturnBuffer); return(lstrlen(ReturnBuffer)+1); } } DWORD AreDrivesACertainType( IN DWORD TypeWereLookingFor, IN BOOL *Results ) { char DriveLetter; char DriveName[4] = { 'x',':','\\','\0' }; DWORD NumMatches = 0; DWORD DriveNumber = 0; for(DriveLetter='A'; DriveLetter <= 'Z'; DriveLetter++) { DriveName[0] = DriveLetter; Results[DriveNumber] = (MyGetDriveType(DriveName) == TypeWereLookingFor); if(Results[DriveNumber]) { NumMatches++; } DriveNumber++; } return(NumMatches); } VOID ConstructDiskList( IN BOOL *ValidDisk, IN LPSTR TextOut ) { DWORD DriveNumber; LPSTR InsertPoint = TextOut; *InsertPoint++ = '{'; for(DriveNumber=0; DriveNumber<26; DriveNumber++) { if(ValidDisk[DriveNumber]) { *InsertPoint++ = '"'; *InsertPoint++ = (char)DriveNumber + (char)'A'; *InsertPoint++ = ':'; *InsertPoint++ = '"'; *InsertPoint++ = ','; } } if(*(InsertPoint-1) == ',') { *(InsertPoint-1) = '}'; // overwrite final comma } else { *InsertPoint++ = '}'; } *InsertPoint = '\0'; } CB GetSpaceWorker( OUT SZ ReturnBuffer, IN CB cbReturnBuffer, IN DWORD TypeOfSpace ) { BOOL HardDisk[26]; DWORD Disk; LPSTR InsertPoint = ReturnBuffer; char DiskName[4] = { 'x',':','\\','\0' }; DWORD SizeSoFar; DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters; DWORD Space; char SpaceSTR[15]; AreDrivesACertainType(DRIVE_FIXED,HardDisk); *InsertPoint++ = '{'; SizeSoFar = 2; for(Disk=0; Disk<26; Disk++) { if(HardDisk[Disk]) { DiskName[0] = (char)Disk + (char)'A'; if(GetDiskFreeSpace(DiskName, &SectorsPerCluster, &BytesPerSector, &FreeClusters, &TotalClusters)) { Space = SectorsPerCluster * BytesPerSector * (TypeOfSpace == SPACE_FREE ? FreeClusters : TotalClusters) / (1024*1024); // converts # to megabytes } else { // assume unformatted Space = GetPartitionSize(DiskName); } wsprintf(SpaceSTR,"%lu",Space); SizeSoFar += lstrlen(SpaceSTR)+3; // 3 is for "", if(SizeSoFar > cbReturnBuffer) { return(SizeSoFar); } *InsertPoint++ = '"'; lstrcpy(InsertPoint,SpaceSTR); InsertPoint = strchr(InsertPoint,0); *InsertPoint++ = '"'; *InsertPoint++ = ','; } } if(*(InsertPoint-1) == ',') { *(InsertPoint-1) = '}'; // overwrite final comma } else { if(++SizeSoFar > cbReturnBuffer) { return(SizeSoFar); } *InsertPoint++ = '}'; } *InsertPoint = '\0'; return(lstrlen(ReturnBuffer)+1); }