mirror of
				https://github.com/bobranten/Ext4Fsd.git
				synced 2025-10-30 21:38:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			5513 lines
		
	
	
		
			139 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			5513 lines
		
	
	
		
			139 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
 | |
| #include "stdafx.h"
 | |
| #include "mountmgr.h"
 | |
| 
 | |
| /* global management information */
 | |
| 
 | |
| BOOL g_bAutoMount = 0;
 | |
| 
 | |
| ULONG g_nFlps     = 0;
 | |
| ULONG g_nDisks    = 0;
 | |
| ULONG g_nCdroms   = 0;
 | |
| ULONG g_nVols     = 0;
 | |
| 
 | |
| EXT2_LETTER drvLetters[26];
 | |
| EXT2_LETTER drvDigits[10];
 | |
| 
 | |
| ULONGLONG Ext2DrvLetters[2] = {-1, -1};
 | |
| 
 | |
| PEXT2_DISK      gDisks  = NULL;
 | |
| PEXT2_CDROM     gCdroms = NULL;
 | |
| PEXT2_VOLUME    gVols = NULL;
 | |
| 
 | |
| /* information string array */
 | |
| 
 | |
| typedef struct {
 | |
|   int PartitionType;
 | |
|   char *type;
 | |
| } PARTITION_LIST;
 | |
| 
 | |
| typedef struct {
 | |
|   UINT DriveType;
 | |
|   char *type;
 | |
| } DRIVE_LIST;
 | |
| 
 | |
| typedef struct {
 | |
|   DEVICE_TYPE DeviceType;
 | |
|   char *type;
 | |
| } DEVICE_LIST;
 | |
| 
 | |
| typedef struct {
 | |
|   STORAGE_BUS_TYPE BusType;
 | |
|   char *type;
 | |
| } BUSTYPE_LIST;
 | |
| 
 | |
| CHAR *
 | |
| IrpMjStrings[] = {
 | |
|     "IRP_MJ_CREATE",
 | |
|     "IRP_MJ_CREATE_NAMED_PIPE",
 | |
|     "IRP_MJ_CLOSE",
 | |
|     "IRP_MJ_READ",
 | |
|     "IRP_MJ_WRITE",
 | |
|     "IRP_MJ_QUERY_INFORMATION",
 | |
|     "IRP_MJ_SET_INFORMATION",
 | |
|     "IRP_MJ_QUERY_EA",
 | |
|     "IRP_MJ_SET_EA",
 | |
|     "IRP_MJ_FLUSH_BUFFERS",
 | |
|     "IRP_MJ_QUERY_VOLUME_INFORMATION",
 | |
|     "IRP_MJ_SET_VOLUME_INFORMATION",
 | |
|     "IRP_MJ_DIRECTORY_CONTROL",
 | |
|     "IRP_MJ_FILE_SYSTEM_CONTROL",
 | |
|     "IRP_MJ_DEVICE_CONTROL",
 | |
|     "IRP_MJ_INTERNAL_DEVICE_CONTROL",
 | |
|     "IRP_MJ_SHUTDOWN",
 | |
|     "IRP_MJ_LOCK_CONTROL",
 | |
|     "IRP_MJ_CLEANUP",
 | |
|     "IRP_MJ_CREATE_MAILSLOT",
 | |
|     "IRP_MJ_QUERY_SECURITY",
 | |
|     "IRP_MJ_SET_SECURITY",
 | |
|     "IRP_MJ_POWER",
 | |
|     "IRP_MJ_SYSTEM_CONTROL",
 | |
|     "IRP_MJ_DEVICE_CHANGE",
 | |
|     "IRP_MJ_QUERY_QUOTA",
 | |
|     "IRP_MJ_SET_QUOTA",
 | |
|     "IRP_MJ_PNP"
 | |
| };
 | |
| 
 | |
| CHAR *
 | |
| PerfStatStrings[] = {
 | |
|         "IRP_CONTEXT",
 | |
|         "VCB",
 | |
|         "FCB",
 | |
|         "CCB",
 | |
|         "MCB",
 | |
|         "EXTENT",
 | |
|         "RW_CONTEXT",
 | |
|         "VPB",
 | |
|         "FCB_NAME",
 | |
|         "MCB_NAME",
 | |
|         "FILE_NAME",
 | |
|         "DIR_ENTRY",
 | |
|         "DIR_PATTERN",
 | |
|         "DISK_EVENT",
 | |
|         "DISK_BUFFER",
 | |
|         "BLOCK_DATA",
 | |
|         "inode",
 | |
|         "dentry",
 | |
|         "buffer head",
 | |
|         NULL
 | |
|     };
 | |
| 
 | |
| PARTITION_LIST PartitionList[] = {
 | |
|     {PARTITION_ENTRY_UNUSED ,   "Empty"},
 | |
|     {PARTITION_FAT_12 ,         "FAT12"},   /* 01 */
 | |
|     {PARTITION_XENIX_1 ,        "Xenix-1"}, /* 02 */
 | |
|     {PARTITION_XENIX_2 ,        "Xenix-2"},
 | |
|     {PARTITION_FAT_16 ,         "FAT16"},   /* 04 */
 | |
|     {PARTITION_EXTENDED ,       "Extended"},
 | |
|     {PARTITION_HUGE ,           "FAT16 HUGE"}, /* 06*/
 | |
|     {PARTITION_IFS ,            "HPFS/NTFS"},     /* 07 */
 | |
| 
 | |
|     {PARTITION_OS2BOOTMGR,      "OS/2"},    /* 0A */
 | |
|     {PARTITION_FAT32 ,          "FAT32"},   /* 0B */
 | |
|     {PARTITION_FAT32_XINT13 ,   "FAT32X"},  /* 0C*/
 | |
|     {PARTITION_XINT13 ,         "XINT13"},  /* 0E */
 | |
|     {PARTITION_XINT13_EXTENDED ,"EXINT13"}, /* 0F */
 | |
|     {0x11 ,                     "Hidden FAT12"},
 | |
|     {0x14 ,                     "Hidden FAT16"},
 | |
|     {0x16 ,                     "Hidden FAT16"},
 | |
|     {0x17 ,                     "Hidden HPFS/NTFS"},
 | |
| 
 | |
|     {0x1B ,                     "Hidden FAT32"},
 | |
|     {0x1C ,                     "Hidden FAT32X"},
 | |
| 
 | |
|     {PARTITION_PREP ,           "OS/2"},    /* 41 */
 | |
|     {PARTITION_LDM ,            "LDM"},     /* 42 */
 | |
| 
 | |
|     {0x52 ,                     "CP/M"},
 | |
| 
 | |
|     {PARTITION_UNIX ,           "UNIX"},    /* 63 */
 | |
| 
 | |
|     {PARTITION_NTFT ,           "NTFT"},    /* 80 */
 | |
|     {0x81,                      "Minix"},
 | |
|     {0x82,                      "Linux swap"},
 | |
|     {0x83,                      "Linux"},
 | |
| 
 | |
|     {0x85,                      "Linux extend"},
 | |
| 
 | |
|     {0x8e,                      "Linux LVM"},
 | |
| 
 | |
|     {0xa5,                      "FreeBSD"},
 | |
|     {0xa6,                      "OpenBSD"},
 | |
| 
 | |
|     {0xa8,                      "Darwin UFS"},
 | |
|     {0xa9,                      "NetBSD"},
 | |
| 
 | |
|     {0xbe,                      "Solaris Boot"},
 | |
|     {0xbf,                      "Solaris"},
 | |
| 
 | |
|     {VALID_NTFT ,               "VNTFT"},   /* C0 */
 | |
|     {-1 ,"UNKNOWN"}
 | |
| };
 | |
| 
 | |
| DRIVE_LIST DriveList[] = {
 | |
|     {DRIVE_UNKNOWN,     "Unkown"},
 | |
|     {DRIVE_NO_ROOT_DIR, "NoRoot"},
 | |
|     {DRIVE_REMOVABLE,   "Removable"},
 | |
|     {DRIVE_FIXED,       "Fixed"},
 | |
|     {DRIVE_REMOTE,      "Remote"},
 | |
|     {DRIVE_CDROM,       "CDROM"},
 | |
|     {DRIVE_RAMDISK,     "RAMdisk"},
 | |
|     {(UINT)-1,          "Invalid"}
 | |
| };
 | |
| 
 | |
| BUSTYPE_LIST BusTypeList[] = {
 | |
|     {BusTypeUnknown,    "Unkown"},
 | |
|     {BusTypeScsi,       "SCSI"},
 | |
|     {BusTypeAtapi,      "ATAPI"},
 | |
|     {BusTypeAta,        "ATA"},
 | |
|     {BusType1394,       "1394"},
 | |
|     {BusTypeSsa,        "Ssa"},
 | |
|     {BusTypeFibre,      "Fibre"},
 | |
|     {BusTypeUsb,        "USB"},
 | |
|     {BusTypeRAID,       "RAID"},
 | |
|     {(STORAGE_BUS_TYPE)-1, "Invalid"}
 | |
| };
 | |
| 
 | |
| 
 | |
| DEVICE_LIST DeviceList[] = {
 | |
|     {FILE_DEVICE_8042_PORT          ,"8042_PORT"},
 | |
|     {FILE_DEVICE_ACPI               ,"ACPI"},
 | |
|     {FILE_DEVICE_BATTERY            ,"BATTERY"},
 | |
|     {FILE_DEVICE_BEEP               ,"BEEP"},
 | |
|     {FILE_DEVICE_BUS_EXTENDER       ,"BUS_EXTENDER"},
 | |
|     {FILE_DEVICE_CD_ROM             ,"CD_ROM"},
 | |
|     {FILE_DEVICE_CD_ROM_FILE_SYSTEM ,"CD_ROM_FILE_SYSTEM"},
 | |
|     {FILE_DEVICE_CHANGER            ,"CHANGER"},
 | |
|     {FILE_DEVICE_CONTROLLER         ,"CONTROLLER"},
 | |
|     {FILE_DEVICE_DATALINK           ,"DATALINK"},
 | |
|     {FILE_DEVICE_DFS                ,"DFS"},
 | |
|     {FILE_DEVICE_DFS_FILE_SYSTEM    ,"DFS_FILE_SYSTEM"},
 | |
|     {FILE_DEVICE_DFS_VOLUME         ,"DFS_VOLUME"},
 | |
|     {FILE_DEVICE_DISK               ,"DISK"},
 | |
|     {FILE_DEVICE_DISK_FILE_SYSTEM   ,"DISK_FILE_SYSTEM"},
 | |
|     {FILE_DEVICE_DVD                ,"DVD"},
 | |
|     {FILE_DEVICE_FILE_SYSTEM        ,"FILE_SYSTEM"},
 | |
|     {0x0000003a /*FILE_DEVICE_FIPS*/ ,"FIPS"},
 | |
|     {FILE_DEVICE_FULLSCREEN_VIDEO   ,"FULLSCREEN_VIDEO"},
 | |
|     {FILE_DEVICE_INPORT_PORT        ,"INPORT_PORT"},
 | |
|     {FILE_DEVICE_KEYBOARD           ,"KEYBOARD"},
 | |
|     {FILE_DEVICE_KS                 ,"KS"},
 | |
|     {FILE_DEVICE_KSEC               ,"KSEC"},
 | |
|     {FILE_DEVICE_MAILSLOT           ,"MAILSLOT"},
 | |
|     {FILE_DEVICE_MASS_STORAGE       ,"MASS_STORAGE"},
 | |
|     {FILE_DEVICE_MIDI_IN            ,"MIDI_IN"},
 | |
|     {FILE_DEVICE_MIDI_OUT           ,"MIDI_OUT"},
 | |
|     {FILE_DEVICE_MODEM              ,"MODEM"},
 | |
|     {FILE_DEVICE_MOUSE              ,"MOUSE"},
 | |
|     {FILE_DEVICE_MULTI_UNC_PROVIDER ,"MULTI_UNC_PROVIDER"},
 | |
|     {FILE_DEVICE_NAMED_PIPE         ,"NAMED_PIPE"},
 | |
|     {FILE_DEVICE_NETWORK            ,"NETWORK"},
 | |
|     {FILE_DEVICE_NETWORK_BROWSER    ,"NETWORK_BROWSER"},
 | |
|     {FILE_DEVICE_NETWORK_FILE_SYSTEM,"NETWORK_FILE_SYSTEM"},
 | |
|     {FILE_DEVICE_NETWORK_REDIRECTOR ,"NETWORK_REDIRECTOR"},
 | |
|     {FILE_DEVICE_NULL               ,"NULL"},
 | |
|     {FILE_DEVICE_PARALLEL_PORT      ,"PARALLEL_PORT"},
 | |
|     {FILE_DEVICE_PHYSICAL_NETCARD   ,"PHYSICAL_NETCARD"},
 | |
|     {FILE_DEVICE_PRINTER            ,"PRINTER"},
 | |
|     {FILE_DEVICE_SCANNER            ,"SCANNER"},
 | |
|     {FILE_DEVICE_SCREEN             ,"SCREEN"},
 | |
|     {FILE_DEVICE_SERENUM            ,"SERENUM"},
 | |
|     {FILE_DEVICE_SERIAL_MOUSE_PORT  ,"SERIAL_MOUSE_PORT"},
 | |
|     {FILE_DEVICE_SERIAL_PORT        ,"SERIAL_PORT"},
 | |
|     {FILE_DEVICE_SMARTCARD          ,"SMARTCARD"},
 | |
|     {FILE_DEVICE_SMB                ,"SMB"},
 | |
|     {FILE_DEVICE_SOUND              ,"SOUND"},
 | |
|     {FILE_DEVICE_STREAMS            ,"STREAMS"},
 | |
|     {FILE_DEVICE_TAPE               ,"TAPE"},
 | |
|     {FILE_DEVICE_TAPE_FILE_SYSTEM   ,"TAPE_FILE_SYSTEM"},
 | |
|     {FILE_DEVICE_TERMSRV            ,"TERMSRV"},
 | |
|     {FILE_DEVICE_TRANSPORT          ,"TRANSPORT"},
 | |
|     {FILE_DEVICE_UNKNOWN            ,"UNKNOWN"},
 | |
|     {FILE_DEVICE_VDM                ,"VDM"},
 | |
|     {FILE_DEVICE_VIDEO              ,"VIDEO"},
 | |
|     {FILE_DEVICE_VIRTUAL_DISK       ,"VIRTUAL_DISK"},
 | |
|     {FILE_DEVICE_WAVE_IN            ,"WAVE_IN"},
 | |
|     {FILE_DEVICE_WAVE_OUT           ,"WAVE_OUT"},
 | |
|     {(DEVICE_TYPE)-1                ,"UNKNOWN"}
 | |
| };
 | |
| 
 | |
| char *PartitionString(int type)
 | |
| {
 | |
|     PARTITION_LIST *p = PartitionList;
 | |
| 
 | |
|     while ( p->PartitionType != -1 ) {
 | |
|         if ( type == p->PartitionType ) {
 | |
|             return p->type;
 | |
|         }
 | |
|         p++;
 | |
|     }
 | |
|     return p->type;
 | |
| }
 | |
| 
 | |
| char *DriveTypeString(UINT media)
 | |
| {
 | |
|     DRIVE_LIST *p = DriveList;
 | |
| 
 | |
|     while ( p->DriveType != (UINT)-1 ) {
 | |
|         if ( media == p->DriveType ) {
 | |
|             return p->type;
 | |
|         }
 | |
|         p++;
 | |
|     }
 | |
|     return p->type;
 | |
| }
 | |
| 
 | |
| char *DeviceTypeString(DEVICE_TYPE media)
 | |
| {
 | |
|     DEVICE_LIST *p = DeviceList;
 | |
| 
 | |
|     while ( p->DeviceType != (DEVICE_TYPE)-1 ) {
 | |
|         if ( media == p->DeviceType ) {
 | |
|             return p->type;
 | |
|         }
 | |
|         p++;
 | |
|     }
 | |
|     return p->type;
 | |
| }
 | |
| 
 | |
| char *BusTypeString(STORAGE_BUS_TYPE BusType)
 | |
| {
 | |
|     BUSTYPE_LIST *p = BusTypeList;
 | |
| 
 | |
|     while ( p->BusType != (STORAGE_BUS_TYPE)-1 ) {
 | |
|         if ( BusType == p->BusType ) {
 | |
|             return p->type;
 | |
|         }
 | |
|         p++;
 | |
|     }
 | |
| 
 | |
|     return p->type;
 | |
| }
 | |
| 
 | |
| /* Ext2Fsd supported codepages */
 | |
| 
 | |
| CHAR * gCodepages[] =
 | |
|   {
 | |
|     "default",
 | |
|     "cp936",
 | |
|     "gb2312",
 | |
|     "utf8",
 | |
|     "cp1251",
 | |
|     "cp1255",
 | |
|     "cp437",
 | |
|     "cp737",
 | |
|     "cp775",
 | |
|     "cp850",
 | |
|     "cp852",
 | |
|     "cp855",
 | |
|     "cp857",
 | |
|     "cp860",
 | |
|     "cp861",
 | |
|     "cp862",
 | |
|     "cp863",
 | |
|     "cp864",
 | |
|     "cp865",
 | |
|     "cp866",
 | |
|     "cp869",
 | |
|     "cp874",
 | |
|     "tis-620",
 | |
|     "cp932",
 | |
|     "euc-jp",
 | |
|     "sjis",
 | |
|     "cp949",
 | |
|     "euc-kr",
 | |
|     "cp950",
 | |
|     "big5",
 | |
|     "iso8859-1",
 | |
|     "iso8859-13",
 | |
|     "iso8859-14",
 | |
|     "iso8859-15",
 | |
|     "iso8859-2",
 | |
|     "iso8859-3",
 | |
|     "iso8859-4",
 | |
|     "iso8859-5",
 | |
|     "iso8859-6",
 | |
|     "iso8859-7",
 | |
|     "iso8859-8",
 | |
|     "iso8859-9",
 | |
|     "koi8-r",
 | |
|     "koi8-u",
 | |
|     "koi8-ru",
 | |
|     "cp1250",
 | |
|     "acsii",
 | |
|     NULL
 | |
|   };
 | |
| 
 | |
| /* routines */
 | |
| 
 | |
| BOOL g_isWow64 = FALSE;
 | |
| BOOL g_isX64 = FALSE;
 | |
| 
 | |
| #define PROCESSOR_ARCHITECTURE_AMD64            9
 | |
| 
 | |
| typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
 | |
| LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
 | |
| 
 | |
| typedef void (WINAPI *LPFN_GETNATIVESYSINFO)(
 | |
|                   LPSYSTEM_INFO lpSystemInfo);
 | |
| 
 | |
| LPFN_GETNATIVESYSINFO fnGetNativeSystemInfo = NULL;
 | |
| BOOL Ext2IsWow64()
 | |
| {
 | |
|     if (NULL != fnIsWow64Process) {
 | |
|         if (!fnIsWow64Process(GetCurrentProcess(), &g_isWow64)) {
 | |
|         }
 | |
|     }
 | |
|     return g_isWow64;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL Ext2IsX64System()
 | |
| {
 | |
|     SYSTEM_INFO sysInfo;
 | |
|     fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
 | |
|         GetModuleHandle("kernel32"), "IsWow64Process");
 | |
| 
 | |
|     fnGetNativeSystemInfo = (LPFN_GETNATIVESYSINFO)GetProcAddress(
 | |
|         GetModuleHandle("kernel32"), "GetNativeSystemInfo");
 | |
| 
 | |
|     if (fnGetNativeSystemInfo) {
 | |
|         fnGetNativeSystemInfo(&sysInfo);
 | |
| 
 | |
|         if (sysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 &&
 | |
|             Ext2IsWow64()) {
 | |
|             g_isWow64 = TRUE;
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| BOOL IsVistaOrAbove()
 | |
| {
 | |
|     OSVERSIONINFO   OsVerInfo;
 | |
| 
 | |
|     OsVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 | |
|  
 | |
|     if (GetVersionEx(&OsVerInfo)) {
 | |
| 
 | |
|        if (OsVerInfo.dwMajorVersion == 6 && OsVerInfo.dwBuildNumber > 3790)
 | |
|            return TRUE;
 | |
| 
 | |
|        if (OsVerInfo.dwMajorVersion > 6)
 | |
|             return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| BOOL CanDoLocalMount()
 | |
| {
 | |
|     return !IsWindowsVistaOrGreater();
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| IsWindows2000()
 | |
| {
 | |
|     OSVERSIONINFO OsVer;
 | |
|     memset(&OsVer, 0, sizeof(OsVer));
 | |
|     OsVer.dwOSVersionInfoSize = sizeof(OsVer);
 | |
| 
 | |
|     if (GetVersionEx(&OsVer)) {
 | |
|         if (OsVer.dwPlatformId == VER_PLATFORM_WIN32_NT &&
 | |
|             OsVer.dwMajorVersion <= 5 && 
 | |
|             OsVer.dwMinorVersion == 0) {
 | |
|             return TRUE;
 | |
|         }
 | |
|     } else {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| BOOL Ext2DismountVolume(CHAR *voldev)
 | |
| {
 | |
| 
 | |
| 	HANDLE	device;
 | |
| 	ULONG	bytes;
 | |
|     BOOL    rc = FALSE;
 | |
| 
 | |
| 	device = CreateFile(voldev, GENERIC_READ | GENERIC_WRITE,
 | |
|                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
 | |
| 		                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 | |
| 
 | |
| 	if (device == INVALID_HANDLE_VALUE) {
 | |
| 		goto errorout;
 | |
| 	}
 | |
| 
 | |
| 	if (!DeviceIoControl(device, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0,
 | |
|                           &bytes, NULL)) {
 | |
| 	}
 | |
| 
 | |
|     rc = DeviceIoControl(device, FSCTL_DISMOUNT_VOLUME,	NULL, 0, NULL, 0,
 | |
|                          &bytes, NULL);
 | |
| 	CloseHandle(device);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
| 	return rc;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Ext2LockVolume
 | |
|  *     Lock the volume ...
 | |
|  *
 | |
|  * ARGUMENTS:
 | |
|  *     VolumeHandle:    Volume handle.
 | |
|  *
 | |
|  * RETURNS: 
 | |
|  *     Success or Fail
 | |
|  *
 | |
|  * NOTES: 
 | |
|  *     N/A
 | |
|  */
 | |
| 
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2LockVolume(HANDLE Handle)
 | |
| {
 | |
|     NT::NTSTATUS status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
|     status = NT::ZwFsControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0);
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2UnLockVolume(HANDLE Handle)
 | |
| {
 | |
|     NT::NTSTATUS status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
|     status = NT::ZwFsControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2DisMountVolume(HANDLE Handle)
 | |
| {
 | |
|     NT::NTSTATUS status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
|     status = NT::ZwFsControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| PDRIVE_LAYOUT_INFORMATION_EXT
 | |
| Ext2QueryDriveLayout(
 | |
|     HANDLE Handle,
 | |
|     PUCHAR NumOfParts
 | |
|     )
 | |
| {
 | |
|     NT::IO_STATUS_BLOCK       ioSb;
 | |
|     NT::NTSTATUS              status;
 | |
| 
 | |
|     PDRIVE_LAYOUT_INFORMATION_EXT driveLayout = NULL;
 | |
|     ULONG                     dataSize = 512;
 | |
|     ULONG                     retSize = 0;
 | |
| 
 | |
| QueryDrive:
 | |
| 
 | |
|     status = STATUS_SUCCESS;
 | |
|     driveLayout = (PDRIVE_LAYOUT_INFORMATION_EXT) malloc(dataSize);
 | |
|     if(!driveLayout) {
 | |
|         goto errorout;
 | |
|     }
 | |
|     memset(driveLayout, 0, dataSize);
 | |
| 
 | |
|     if (IsWindows2000()) {
 | |
| 
 | |
|         PDRIVE_LAYOUT_INFORMATION oldLayout = 
 | |
|               (PDRIVE_LAYOUT_INFORMATION ) malloc(dataSize);
 | |
|         if (!oldLayout) {
 | |
|             goto errorout;
 | |
|         }
 | |
|         
 | |
|         status = NT::ZwDeviceIoControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     IOCTL_DISK_GET_DRIVE_LAYOUT,
 | |
|                     NULL, 0, (PVOID)oldLayout, dataSize
 | |
|                     );
 | |
| 
 | |
|         if (NT_SUCCESS(status)) {
 | |
| 
 | |
|             ULONG newLayoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry);
 | |
|             newLayoutSize += sizeof(PARTITION_INFORMATION_EX) * oldLayout->PartitionCount;
 | |
| 
 | |
|             if (dataSize >= newLayoutSize) {
 | |
| 
 | |
|                 driveLayout->PartitionStyle = PARTITION_STYLE_MBR;
 | |
|                 driveLayout->PartitionCount = oldLayout->PartitionCount;
 | |
|                 driveLayout->Mbr.Signature = oldLayout->Signature;
 | |
| 
 | |
|                 for (DWORD i=0; i < oldLayout->PartitionCount; i++) {
 | |
|                     driveLayout->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
 | |
| 
 | |
|                     driveLayout->PartitionEntry[i].StartingOffset = 
 | |
|                             oldLayout->PartitionEntry[i].StartingOffset;
 | |
|                     driveLayout->PartitionEntry[i].PartitionLength =
 | |
|                             oldLayout->PartitionEntry[i].PartitionLength;
 | |
|                     driveLayout->PartitionEntry[i].PartitionNumber =
 | |
|                             oldLayout->PartitionEntry[i].PartitionNumber;
 | |
|                     driveLayout->PartitionEntry[i].RewritePartition =
 | |
|                             oldLayout->PartitionEntry[i].RewritePartition;
 | |
|                     driveLayout->PartitionEntry[i].Mbr.PartitionType =
 | |
|                             oldLayout->PartitionEntry[i].PartitionType;
 | |
|                     driveLayout->PartitionEntry[i].Mbr.BootIndicator =
 | |
|                             oldLayout->PartitionEntry[i].BootIndicator;
 | |
|                     driveLayout->PartitionEntry[i].Mbr.RecognizedPartition =
 | |
|                             oldLayout->PartitionEntry[i].RecognizedPartition;
 | |
|                     driveLayout->PartitionEntry[i].Mbr.HiddenSectors = 
 | |
|                             oldLayout->PartitionEntry[i].HiddenSectors;
 | |
|                 }
 | |
| 
 | |
|             } else {
 | |
|                 dataSize = newLayoutSize;
 | |
|                 status = STATUS_BUFFER_TOO_SMALL;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         free(oldLayout);
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         status = NT::ZwDeviceIoControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     IOCTL_DISK_GET_DRIVE_LAYOUT_EXT,
 | |
|                     NULL, 0, (PVOID)driveLayout, dataSize
 | |
|                     );
 | |
|     }
 | |
| 
 | |
|     if (status == STATUS_BUFFER_TOO_SMALL) {
 | |
|         free(driveLayout); driveLayout = NULL;
 | |
|         dataSize *= 2;
 | |
|         goto QueryDrive;
 | |
|     }
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         free(driveLayout); driveLayout = NULL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     retSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EXT, PartitionEntry);
 | |
|     retSize += sizeof(PARTITION_INFORMATION) *  driveLayout->PartitionCount;
 | |
| 
 | |
|     if (driveLayout->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
| 
 | |
|         PPARTITION_INFORMATION_EXT  Part;
 | |
|         UCHAR i = 0, cnt = 0;
 | |
| 
 | |
|         /* Now walk the Drive_Layout to count the partitions */
 | |
|         while (i < (UCHAR)driveLayout->PartitionCount) {
 | |
|             Part = &driveLayout->PartitionEntry[i++];
 | |
|             if (Part->Mbr.PartitionType != PARTITION_ENTRY_UNUSED && 
 | |
|                 Part->Mbr.PartitionType != PARTITION_EXTENDED && 
 | |
|                 Part->Mbr.PartitionType != PARTITION_XINT13_EXTENDED) {
 | |
|                 cnt++;
 | |
|             }
 | |
|         }
 | |
|         *NumOfParts = cnt;
 | |
|     } else if (driveLayout->PartitionStyle == PARTITION_STYLE_GPT) {
 | |
|         *NumOfParts = (UCHAR)driveLayout->PartitionCount;
 | |
|     } else {
 | |
|         *NumOfParts = 0;
 | |
|          free(driveLayout); driveLayout = NULL;
 | |
|     }
 | |
| 
 | |
|     if (*NumOfParts == 0) {
 | |
|          free(driveLayout); driveLayout = NULL;
 | |
|     }
 | |
| 
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return driveLayout;
 | |
| }
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2SetDriveLayout(
 | |
|     HANDLE  Handle,
 | |
|     PDRIVE_LAYOUT_INFORMATION_EXT Layout
 | |
|     )
 | |
| {
 | |
|     NT::IO_STATUS_BLOCK       ioSb;
 | |
|     NT::NTSTATUS              status = STATUS_SUCCESS;
 | |
|     ULONG                     dataSize;
 | |
| 
 | |
|     dataSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EXT, PartitionEntry);
 | |
|     dataSize += sizeof(PARTITION_INFORMATION_EXT) * Layout->PartitionCount;
 | |
| 
 | |
|     if (IsWindows2000()) {
 | |
| 
 | |
|         if (Layout->PartitionStyle != PARTITION_STYLE_MBR) {
 | |
|             return STATUS_UNSUCCESSFUL;
 | |
|         }
 | |
| 
 | |
|         ULONG newLayoutSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION, PartitionEntry);
 | |
|         newLayoutSize += sizeof(PARTITION_INFORMATION) * Layout->PartitionCount;
 | |
| 
 | |
|         PDRIVE_LAYOUT_INFORMATION oldLayout = 
 | |
|               (PDRIVE_LAYOUT_INFORMATION ) malloc(newLayoutSize);
 | |
|         if (!oldLayout) {
 | |
|             goto errorout;
 | |
|         }
 | |
|         
 | |
|         oldLayout->PartitionCount = Layout->PartitionCount;
 | |
|         oldLayout->Signature = Layout->Mbr.Signature;
 | |
| 
 | |
|         for (DWORD i=0; i < oldLayout->PartitionCount; i++) {
 | |
| 
 | |
|             oldLayout->PartitionEntry[i].StartingOffset = 
 | |
|                     Layout->PartitionEntry[i].StartingOffset;
 | |
|             oldLayout->PartitionEntry[i].PartitionLength =
 | |
|                     Layout->PartitionEntry[i].PartitionLength;
 | |
|             oldLayout->PartitionEntry[i].PartitionNumber =
 | |
|                     Layout->PartitionEntry[i].PartitionNumber;
 | |
|             oldLayout->PartitionEntry[i].RewritePartition =
 | |
|                     Layout->PartitionEntry[i].RewritePartition;
 | |
|             oldLayout->PartitionEntry[i].PartitionType =
 | |
|                     Layout->PartitionEntry[i].Mbr.PartitionType;
 | |
|             oldLayout->PartitionEntry[i].BootIndicator =
 | |
|                     Layout->PartitionEntry[i].Mbr.BootIndicator;
 | |
|             oldLayout->PartitionEntry[i].RecognizedPartition =
 | |
|                     Layout->PartitionEntry[i].Mbr.RecognizedPartition;
 | |
|             oldLayout->PartitionEntry[i].HiddenSectors =
 | |
|                     Layout->PartitionEntry[i].Mbr.HiddenSectors;
 | |
|         }
 | |
| 
 | |
|         status = NT::ZwDeviceIoControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     IOCTL_DISK_SET_DRIVE_LAYOUT,
 | |
|                     (PVOID)oldLayout, newLayoutSize,
 | |
|                     NULL, 0
 | |
|                     );
 | |
| 
 | |
|         free(oldLayout);
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         status = NT::ZwDeviceIoControlFile(
 | |
|                     Handle, NULL, NULL, NULL, &ioSb,
 | |
|                     IOCTL_DISK_SET_DRIVE_LAYOUT_EXT,
 | |
|                     (PVOID)Layout, dataSize,NULL, 0
 | |
|                     );
 | |
|     }
 | |
| 
 | |
|     return status;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return STATUS_UNSUCCESSFUL;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2IsDeviceValid(CHAR *Device)
 | |
| {
 | |
|     HANDLE  handle = NULL;
 | |
|     NT::NTSTATUS status;
 | |
| 
 | |
|     status = Ext2Open(Device, &handle, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (handle) {
 | |
|         Ext2Close(&handle);
 | |
|     }
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2SetPartitionType(
 | |
|     PEXT2_PARTITION Part,
 | |
|     BYTE            Type
 | |
|     )
 | |
| {
 | |
|     BOOL rc = FALSE;
 | |
|     HANDLE  Handle = NULL;
 | |
|     NT::NTSTATUS status;
 | |
| 
 | |
|     UCHAR  NumParts = 0;
 | |
|     PDRIVE_LAYOUT_INFORMATION_EXT Layout = NULL;
 | |
| 
 | |
|     DWORD i;
 | |
| 
 | |
|     status = Ext2Open(Part->Disk->Name, &Handle,
 | |
|                       EXT2_DESIRED_ACCESS | GENERIC_WRITE);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     Layout = Part->Disk->Layout;
 | |
| 
 | |
|     if (!Layout) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (Layout->PartitionStyle != PARTITION_STYLE_MBR) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     for (i=0; i < Layout->PartitionCount; i++) {
 | |
| 
 | |
|         if ((Layout->PartitionEntry[i].StartingOffset.QuadPart == 
 | |
|              Part->Entry->StartingOffset.QuadPart) &&
 | |
|             (Layout->PartitionEntry[i].PartitionLength.QuadPart ==
 | |
|              Part->Entry->PartitionLength.QuadPart) &&
 | |
|             (Layout->PartitionEntry[i].PartitionNumber ==
 | |
|              Part->Entry->PartitionNumber) ) {
 | |
| 
 | |
|             Layout->PartitionEntry[i].Mbr.PartitionType = Type;
 | |
|             Layout->PartitionEntry[i].RewritePartition = TRUE;
 | |
| 
 | |
|             rc = TRUE;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = Ext2SetDriveLayout(Handle, Layout);
 | |
|     rc = NT_SUCCESS(status);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&Handle);
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2FlushVolume(CHAR *Device)
 | |
| {
 | |
|     HANDLE  handle = NULL;
 | |
|     NT::NTSTATUS status;
 | |
|     NT::IO_STATUS_BLOCK iosb;
 | |
| 
 | |
|     status = Ext2Open(Device, &handle, EXT2_DESIRED_ACCESS | GENERIC_WRITE);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwFlushBuffersFile(handle, &iosb);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (handle) {
 | |
|         Ext2Close(&handle);
 | |
|     }
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| PEXT2_PARTITION
 | |
| Ext2QueryVolumePartition(
 | |
|     PEXT2_VOLUME    Volume
 | |
|     )
 | |
| {
 | |
|     PEXT2_PARTITION Part = NULL;
 | |
|     DWORD i, j;
 | |
| 
 | |
|     for (i=0; i < g_nDisks; i++) {
 | |
|         for (j=0; j < (int)gDisks[i].NumParts; j++) {
 | |
|             if (gDisks[i].DataParts[j].Volume == Volume) {
 | |
|                 Part = &gDisks[i].DataParts[j];
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return Part;
 | |
| }
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2QueryProperty(
 | |
|     HANDLE                      Handle, 
 | |
|     STORAGE_PROPERTY_ID         Id,
 | |
|     PVOID                       DescBuf,
 | |
|     ULONG                       DescSize
 | |
|     )
 | |
| {
 | |
| 	STORAGE_PROPERTY_QUERY	    SPQ;
 | |
|     NT::NTSTATUS                status;
 | |
|     NT::IO_STATUS_BLOCK         ioSb;
 | |
| 
 | |
| 	SPQ.PropertyId = Id;
 | |
| 	SPQ.QueryType  = PropertyStandardQuery;
 | |
| 
 | |
|     memset(DescBuf, 0, DescSize);
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &ioSb,
 | |
|                 IOCTL_STORAGE_QUERY_PROPERTY,
 | |
|                 &SPQ, sizeof(STORAGE_PROPERTY_QUERY),
 | |
|                 DescBuf,  DescSize
 | |
|             );
 | |
| 
 | |
| 	return status;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Ext2QueryDisk
 | |
|  *     Get volume gemmetry information ...
 | |
|  *
 | |
|  * ARGUMENTS:
 | |
|  *     VolumeHandle:    Volume handle.
 | |
|  *
 | |
|  * RETURNS: 
 | |
|  *     Success or Fail
 | |
|  *
 | |
|  * NOTES: 
 | |
|  *     N/A
 | |
|  */
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2QueryDisk(
 | |
|     HANDLE                  Handle,
 | |
|     PDISK_GEOMETRY          DiskGeometry
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS        status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &ioSb,
 | |
|                 IOCTL_DISK_GET_DRIVE_GEOMETRY,
 | |
|                 DiskGeometry, sizeof(DISK_GEOMETRY),
 | |
|                 DiskGeometry, sizeof(DISK_GEOMETRY));
 | |
| 
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| PVOLUME_DISK_EXTENTS
 | |
| Ext2QueryVolumeExtents(HANDLE hVolume)
 | |
| {
 | |
| 	ULONG	dataSize = 1024;
 | |
| 	PVOLUME_DISK_EXTENTS dskExtents = NULL;
 | |
| 
 | |
|     NT::NTSTATUS        status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
| QueryExtent:
 | |
| 
 | |
|     dskExtents = (PVOLUME_DISK_EXTENTS)malloc(dataSize);
 | |
|     if (NULL == dskExtents) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hVolume, NULL, NULL, NULL, &ioSb,
 | |
|                 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
 | |
|                 NULL, 0, dskExtents, dataSize );
 | |
| 
 | |
|     if (status == STATUS_BUFFER_TOO_SMALL) {
 | |
|         free(dskExtents); dskExtents = NULL;
 | |
|         dataSize += 1024;
 | |
|         goto QueryExtent;
 | |
|     }
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         free(dskExtents); dskExtents = NULL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return dskExtents;
 | |
| }
 | |
| 
 | |
| PSTORAGE_DEVICE_NUMBER
 | |
| Ext2QueryDeviceNumber(HANDLE hVolume)
 | |
| {
 | |
| 	ULONG	            dataSize;
 | |
| 	PSTORAGE_DEVICE_NUMBER SDN = NULL;
 | |
| 
 | |
|     NT::NTSTATUS        status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
| 
 | |
|     dataSize = sizeof(STORAGE_DEVICE_NUMBER);
 | |
| 
 | |
| QuerySDN:
 | |
| 
 | |
|     SDN = (PSTORAGE_DEVICE_NUMBER)malloc(dataSize);
 | |
|     if (NULL == SDN) {
 | |
|         goto errorout;
 | |
|     }
 | |
|     memset(SDN, 0, dataSize);
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hVolume, NULL, NULL, NULL, &ioSb,
 | |
|                 IOCTL_STORAGE_GET_DEVICE_NUMBER,
 | |
|                 NULL, 0, SDN, dataSize );
 | |
| 
 | |
|     if (status == STATUS_BUFFER_TOO_SMALL) {
 | |
|         free(SDN); SDN = NULL;
 | |
|         dataSize += sizeof(STORAGE_DEVICE_NUMBER);
 | |
|         goto QuerySDN;
 | |
|     }
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         free(SDN); SDN = NULL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return SDN;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2QueryDrvLetter(
 | |
|     PEXT2_LETTER    drvLetter
 | |
|     )
 | |
| {
 | |
| 	HANDLE	        hVolume;
 | |
|     NT::NTSTATUS    status = STATUS_SUCCESS;
 | |
|     DWORD           rc = 0; 
 | |
| 
 | |
|     drvLetter->DrvType = Ext2QueryDrive(drvLetter->Letter,
 | |
|                                         drvLetter->SymLink);
 | |
| 
 | |
|     if (drvLetter->DrvType == DRIVE_NO_ROOT_DIR) {
 | |
|         drvLetter->bUsed = FALSE;
 | |
|         goto errorout;
 | |
|     } else {
 | |
|         drvLetter->bUsed = TRUE;
 | |
|     }
 | |
| 
 | |
|     if (drvLetter->Letter == 'A' || 
 | |
|         drvLetter->Letter == 'B' ) {
 | |
|         drvLetter->bUsed = TRUE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (drvLetter->DrvType == DRIVE_REMOVABLE ||
 | |
|         drvLetter->DrvType == DRIVE_FIXED) {
 | |
| 
 | |
| 	    status = Ext2Open(drvLetter->SymLink, &hVolume, EXT2_DESIRED_ACCESS);
 | |
| 	    if (!NT_SUCCESS(status) && status != STATUS_ACCESS_DENIED) {
 | |
|             drvLetter->bInvalid = TRUE;
 | |
|             goto errorout;
 | |
| 	    }
 | |
| 
 | |
|   	    drvLetter->Extent = Ext2QueryVolumeExtents(hVolume);
 | |
|         if (drvLetter->DrvType == DRIVE_REMOVABLE) {
 | |
|             drvLetter->SDN = Ext2QueryDeviceNumber(hVolume);
 | |
|         }
 | |
| 
 | |
| 	    Ext2Close(&hVolume);
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| 
 | |
| PEXT2_LETTER Ext2GetFirstUnusedDrvLetter()
 | |
| {
 | |
|     PEXT2_LETTER    drvLetter = NULL;
 | |
|     CHAR            devPath[] = "C:";
 | |
|     int             i;
 | |
| 
 | |
|     for (i = 5; i < 24; i++) {
 | |
|         drvLetter = &drvLetters[i];
 | |
|         if (drvLetter->DrvType == DRIVE_NO_ROOT_DIR) {
 | |
|             drvLetter->DrvType = Ext2QueryDrive(drvLetter->Letter,
 | |
|                                                 drvLetter->SymLink);
 | |
|             if (drvLetter->DrvType == DRIVE_NO_ROOT_DIR) {
 | |
|                 /* we got it */
 | |
|                 break;
 | |
|             } else {
 | |
|                 /* we need do a new refresh */
 | |
|             }
 | |
|         }
 | |
|         drvLetter = NULL;
 | |
|     }
 | |
| 
 | |
|     return drvLetter;
 | |
| }
 | |
| 
 | |
| 
 | |
| CHAR Ext2MountVolume(CHAR *voldev)
 | |
| {
 | |
|     PEXT2_LETTER drvLetter;
 | |
|     CHAR         rc = 0;
 | |
|    
 | |
|     /* query drive letter to check whether it's mounted */
 | |
|     drvLetter = Ext2GetFirstUnusedDrvLetter();
 | |
|     if (!drvLetter) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (Ext2AssignDrvLetter(drvLetter, voldev, FALSE)) {
 | |
|         rc = drvLetter->Letter;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| CHAR Ext2MountVolumeAs(CHAR *voldev, CHAR DrvLetter)
 | |
| {
 | |
|     PEXT2_LETTER drvLetter;
 | |
|     CHAR         rc = 0;
 | |
|    
 | |
|             
 | |
|     if (DrvLetter >= '0' && DrvLetter <= '9') {
 | |
|         drvLetter = &drvDigits[DrvLetter - '0'];
 | |
|     } else if (DrvLetter >= 'A' && DrvLetter <= 'Z') {
 | |
|         drvLetter = &drvLetters[DrvLetter - 'A'];
 | |
|     } else if (DrvLetter >= 'a' && DrvLetter <= 'z') {
 | |
|         drvLetter = &drvLetters[DrvLetter - 'a'];
 | |
|     }
 | |
| 
 | |
|     if (!drvLetter || drvLetter->bUsed) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (Ext2AssignDrvLetter(drvLetter, voldev, FALSE)) {
 | |
|         rc = drvLetter->Letter;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2QueryMediaType(
 | |
|     HANDLE                  Handle,
 | |
|     PDWORD                  MediaType
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS        status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
|     PGET_MEDIA_TYPES    mediaTypes;
 | |
|     UCHAR               buffer[1024];
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &ioSb,
 | |
|                 IOCTL_STORAGE_GET_MEDIA_TYPES_EX,
 | |
|                 NULL, 0, buffer, 1024 );
 | |
| 
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     mediaTypes = (PGET_MEDIA_TYPES) buffer;
 | |
|     *MediaType = mediaTypes->DeviceType;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Ext2Read
 | |
|  *     Read data from disk or file ...
 | |
|  *
 | |
|  * ARGUMENTS:
 | |
|  *     VolumeHandle: Volume Handle
 | |
|  *     Offset      : Disk Offset
 | |
|  *     Length      : Data Length to be read
 | |
|  *     Buffer      : ...
 | |
|  *
 | |
|  * RETURNS: 
 | |
|  *     Success: STATUS_SUCCESS
 | |
|  *     Fail:  ...
 | |
|  *
 | |
|  * NOTES: 
 | |
|  *     Both Length and Offset should be SECTOR_SIZE aligned.
 | |
|  */
 | |
| NT::NTSTATUS 
 | |
| Ext2Read(
 | |
|     IN  HANDLE          Handle,
 | |
|     IN  BOOL         IsFile,
 | |
|     IN  ULONG           SectorSize,
 | |
|     IN  ULONGLONG       Offset,
 | |
|     IN  ULONG           Length,
 | |
|     IN  PVOID           Buffer
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS        status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
|     LARGE_INTEGER   address;
 | |
|     ULONG               aLength = 0;
 | |
|     PVOID               aBuffer = NULL;
 | |
| 
 | |
|     if (SectorSize == 0 || SectorSize == 1)
 | |
|         IsFile = TRUE;
 | |
| 
 | |
|     ASSERT(Buffer != NULL);
 | |
| 
 | |
|     if (IsFile) {
 | |
| 
 | |
|         address.QuadPart = Offset;
 | |
|         status = NT::ZwReadFile(
 | |
|                     Handle, 0, NULL, NULL, &ioSb,
 | |
|                     Buffer, Length, &address, NULL
 | |
|                     );
 | |
|     } else {
 | |
| 
 | |
|         address.QuadPart = Offset & (~((ULONGLONG)SectorSize - 1));
 | |
|         aLength  = (Length + SectorSize - 1)&(~(SectorSize - 1));
 | |
|         aLength += ((ULONG)(Offset - address.QuadPart) + SectorSize - 1)
 | |
|                     & (~(SectorSize - 1));
 | |
| 
 | |
|         aBuffer = malloc(aLength);
 | |
|         if (!aBuffer) {
 | |
|             status = STATUS_INSUFFICIENT_RESOURCES;
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         status = NT::ZwReadFile(
 | |
|                     Handle, 0, NULL, NULL, &ioSb,
 | |
|                     aBuffer, aLength, &address, NULL
 | |
|                     );
 | |
| 
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         memmove( Buffer, (PUCHAR)aBuffer + 
 | |
|                  (ULONG)(Offset - address.QuadPart), Length);
 | |
|     }
 | |
|  
 | |
| errorout:
 | |
| 
 | |
|     if (aBuffer)
 | |
|         free(aBuffer);
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Ext2Write
 | |
|  *     Write data to disk or file ...
 | |
|  *
 | |
|  * ARGUMENTS:
 | |
|  *     VolumeHandle: Volume Handle
 | |
|  *     Offset      : Disk Offset
 | |
|  *     Length      : Data Length to be written
 | |
|  *     Buffer      : Data to be written ...
 | |
|  *
 | |
|  * RETURNS: 
 | |
|  *     Success: STATUS_SUCCESS
 | |
|  *     Fail:  ...
 | |
|  *
 | |
|  * NOTES: 
 | |
|  *     Both Length and Offset should be SECTOR_SIZE aligned.
 | |
|  */
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2WriteDisk(
 | |
|     HANDLE          Handle,
 | |
|     BOOL         IsFile,
 | |
|     ULONG           SectorSize,
 | |
|     ULONGLONG       Offset,
 | |
|     ULONG           Length,
 | |
|     PVOID           Buffer
 | |
|     )
 | |
| {
 | |
|     LARGE_INTEGER           address;
 | |
|     NT::NTSTATUS            status;
 | |
|     NT::IO_STATUS_BLOCK     ioSb;
 | |
| 
 | |
|     ULONG                   aLength = 0;
 | |
|     PVOID                   aBuffer = NULL;
 | |
| 
 | |
|     if (SectorSize == 0 || SectorSize == 1)
 | |
|         IsFile = TRUE;
 | |
| 
 | |
|     ASSERT(Buffer != NULL);
 | |
| 
 | |
|     if (IsFile) {
 | |
| 
 | |
|         address.QuadPart = Offset;
 | |
|         status = NT::ZwWriteFile(
 | |
|                     Handle, 0, NULL, NULL, &ioSb,
 | |
|                     Buffer, Length, &address, NULL
 | |
|                     );
 | |
|     } else  {
 | |
| 
 | |
|         address.QuadPart = Offset & (~((ULONGLONG)SectorSize - 1));
 | |
|         aLength = (Length + SectorSize - 1)&(~(SectorSize - 1));
 | |
|         aLength += ((ULONG)(Offset - address.QuadPart) + SectorSize - 1)
 | |
|                          & (~(SectorSize - 1));
 | |
| 
 | |
|         aBuffer = malloc(aLength);
 | |
|         if (!aBuffer) {
 | |
|             status = STATUS_INSUFFICIENT_RESOURCES;
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         if ( (aLength != Length) || 
 | |
|              (address.QuadPart != (LONGLONG)Offset)) {
 | |
|             status = NT::ZwReadFile(
 | |
|                         Handle, 0, NULL, NULL, &ioSb,
 | |
|                         aBuffer, aLength, &address, NULL
 | |
|                         );
 | |
| 
 | |
|             if (!NT_SUCCESS(status)) {
 | |
|                 goto errorout;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         memmove((PUCHAR)aBuffer + (ULONG)(Offset - address.QuadPart),
 | |
|                 Buffer, Length);
 | |
|         status = NT::ZwWriteFile(
 | |
|                     Handle, 0, NULL, NULL, &ioSb,
 | |
|                     aBuffer, aLength, &address, NULL
 | |
|                     );
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (aBuffer)
 | |
|         free(aBuffer);
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| NT::NTSTATUS
 | |
| Ext2Open(
 | |
|     PCHAR                   FileName,
 | |
|     PHANDLE                 Handle,
 | |
|     ULONG                   DesiredAccess
 | |
|     )
 | |
| {
 | |
|     NT::IO_STATUS_BLOCK     iosb;
 | |
|     NT::NTSTATUS            status;
 | |
|     NT::ANSI_STRING         AnsiFilespec;
 | |
|     NT::UNICODE_STRING      UnicodeFilespec;
 | |
|     NT::OBJECT_ATTRIBUTES   ObjectAttributes;
 | |
| 
 | |
|     SHORT                   UnicodeName[MAX_PATH];
 | |
|     CHAR                    AnsiName[MAX_PATH];
 | |
|     USHORT                  NameLength = 0;
 | |
| 
 | |
|     memset(UnicodeName, 0, sizeof(SHORT) * MAX_PATH);
 | |
|     memset(AnsiName, 0, sizeof(UCHAR) * MAX_PATH);
 | |
| 
 | |
|     NameLength = strlen(FileName);
 | |
|     ASSERT(NameLength < MAX_PATH);
 | |
| 
 | |
|     if (FileName[0] == '\\')  {
 | |
|         memmove(AnsiName, FileName, NameLength);
 | |
|     } else {
 | |
|         memmove(&AnsiName[0], "\\DosDevices\\", 12);
 | |
|         memmove(&AnsiName[12], FileName, NameLength);
 | |
|         NameLength += 12;
 | |
|     }
 | |
| 
 | |
|     AnsiFilespec.MaximumLength = AnsiFilespec.Length = NameLength;
 | |
|     AnsiFilespec.Buffer = AnsiName;
 | |
| 
 | |
|     UnicodeFilespec.MaximumLength = MAX_PATH * 2;
 | |
|     UnicodeFilespec.Length = 0;
 | |
|     UnicodeFilespec.Buffer = (PWSTR)UnicodeName;
 | |
| 
 | |
|     NT::RtlAnsiStringToUnicodeString(&UnicodeFilespec, &AnsiFilespec, FALSE);
 | |
| 
 | |
|     //
 | |
|     // Setup the name in an object attributes structure.
 | |
|     // Note that we create a name that is case INsensitive
 | |
|     //
 | |
| 
 | |
|     ObjectAttributes.Length = sizeof(NT::OBJECT_ATTRIBUTES);
 | |
|     ObjectAttributes.RootDirectory = NULL;
 | |
|     ObjectAttributes.Attributes = 0; /*OBJ_CASE_INSENSITIVE;*/
 | |
|     ObjectAttributes.ObjectName = &UnicodeFilespec;
 | |
|     ObjectAttributes.SecurityDescriptor = NULL;
 | |
|     ObjectAttributes.SecurityQualityOfService = NULL;
 | |
| 
 | |
|     //
 | |
|     // Do the create.  In this particular case, we'll have the I/O Manager
 | |
|     // make our write requests syncrhonous for our convenience.
 | |
|     //
 | |
|     status = NT::ZwCreateFile(
 | |
|                 Handle,                           // returned file handle
 | |
|                 (DesiredAccess | SYNCHRONIZE),    // desired access
 | |
|                 &ObjectAttributes,                // ptr to object attributes
 | |
|                 &iosb,                            // ptr to I/O status block
 | |
|                 0,                                // allocation size
 | |
|                 FILE_ATTRIBUTE_NORMAL,            // file attributes
 | |
|                 FILE_SHARE_WRITE | FILE_SHARE_READ, // share access
 | |
|                 FILE_OPEN  /*FILE_SUPERSEDE*/,    // create disposition
 | |
|                 FILE_SYNCHRONOUS_IO_NONALERT |    // create options
 | |
|                 ((DesiredAccess & GENERIC_WRITE) ? 
 | |
|                  FILE_NO_INTERMEDIATE_BUFFERING : 0),
 | |
|                 NULL,                             // ptr to extended attributes
 | |
|                 0);                               // length of ea buffer
 | |
| 
 | |
|     //
 | |
|     // Check the system service status
 | |
|     //
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         return status;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Check the returned status too...
 | |
|     //
 | |
|     if (!NT_SUCCESS(iosb.Status)) {
 | |
|         return iosb.Status;
 | |
|     }
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2Close(HANDLE * Handle)
 | |
| {
 | |
|     NT::NTSTATUS status = 0;
 | |
|     if (Handle != NULL && *Handle != 0 && *Handle != INVALID_HANDLE_VALUE) {
 | |
|         status = NT::ZwClose(*Handle); 
 | |
|         if (NT_SUCCESS(status)) {
 | |
|             *Handle = 0;
 | |
|         } else {
 | |
|             ::MessageBox(NULL, "Failed to close handle", "Ext2Close", MB_OK);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2QuerySysConfig()
 | |
| {
 | |
|     NT::NTSTATUS status;
 | |
|     NT::_SYSTEM_CONFIGURATION_INFORMATION ConfigInfo;
 | |
| 
 | |
|     status = NT::ZwQuerySystemInformation(
 | |
|                     NT::SystemConfigurationInformation,
 | |
| 					&ConfigInfo, sizeof(ConfigInfo), 0);
 | |
|     if (NT_SUCCESS(status)) {
 | |
|         g_nDisks  = ConfigInfo.DiskCount;
 | |
|         g_nFlps   = ConfigInfo.FloppyCount;
 | |
|         g_nCdroms = ConfigInfo.CdRomCount;
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2LoadDisks()
 | |
| {
 | |
|     ULONG           i = 0, j = 0;
 | |
|     NT::NTSTATUS    status;
 | |
|     CHAR            drvName[MAX_PATH];
 | |
| 
 | |
|     if (g_nDisks == 0) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     gDisks = (PEXT2_DISK) malloc(sizeof(EXT2_DISK) * g_nDisks);
 | |
|     if (gDisks == NULL) {
 | |
|         return FALSE;
 | |
|     }
 | |
|     memset(gDisks, 0, sizeof(EXT2_DISK) * g_nDisks);
 | |
| 
 | |
|     while (i < g_nDisks && j < 256) {
 | |
| 
 | |
|         HANDLE  Handle = NULL;
 | |
| 
 | |
|         gDisks[i].Magic = EXT2_DISK_MAGIC;
 | |
|         gDisks[i].Null  = EXT2_DISK_NULL_MAGIC;
 | |
|         gDisks[i].OrderNo = (UCHAR) j;
 | |
|         gDisks[i].bLoaded = FALSE;
 | |
|         sprintf(drvName, "PhysicalDrive%d\0", j);
 | |
|         if (QueryDosDevice(drvName, gDisks[i].Name, MAX_PATH) == 0) {
 | |
|             sprintf(gDisks[i].Name, "\\DosDevices\\PhysicalDrive%d\0", j);
 | |
|         }
 | |
|         j++;
 | |
| 
 | |
|         status = Ext2Open(gDisks[i].Name, &Handle, EXT2_DESIRED_ACCESS);
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryDisk(Handle, &gDisks[i].DiskGeometry);
 | |
|         if (NT_SUCCESS(status)) {
 | |
|             gDisks[i].bEjected = FALSE;
 | |
|         } else {
 | |
|             if (STATUS_NO_MEDIA_IN_DEVICE == status) {
 | |
|                 gDisks[i].bEjected = TRUE;
 | |
|             } else {
 | |
|                 goto Next;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryProperty( Handle, StorageDeviceProperty,
 | |
|                                     (PVOID)&gDisks[i].SDD,
 | |
|                                     sizeof(STORAGE_DEVICE_DESCRIPTOR)
 | |
|                                   );
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             goto Next;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryProperty( Handle, StorageAdapterProperty,
 | |
|                                     (PVOID)&gDisks[i].SAD,
 | |
|                                     sizeof(STORAGE_ADAPTER_DESCRIPTOR)
 | |
|                                   );
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             goto Next;
 | |
|         }
 | |
| 
 | |
|         if (!gDisks[i].bEjected) {
 | |
|             gDisks[i].Layout = Ext2QueryDriveLayout(
 | |
|                         Handle, &gDisks[i].NumParts);
 | |
|         }
 | |
| 
 | |
|         gDisks[i].bLoaded = TRUE;
 | |
| 
 | |
| Next:
 | |
| 
 | |
|         Ext2Close(&Handle);
 | |
|         i++;
 | |
|     }
 | |
| 
 | |
|     g_nDisks = i;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| CString
 | |
| Ext2PartInformation(PEXT2_PARTITION part)
 | |
| {
 | |
|     CString     s, ret="";
 | |
| 
 | |
|     s.Format("\r\n    Partition No: %d\r\n\r\n", part->Number);
 | |
|     if (!part->Entry) {
 | |
|         return ret;
 | |
|     } 
 | |
| 
 | |
|     s = "      Partition Type: ";
 | |
|     if (part->Entry->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
|         s += PartitionString(part->Entry->Mbr.PartitionType);
 | |
|     } else if (part->Entry->PartitionStyle == PARTITION_STYLE_GPT){
 | |
|         s += "GPT";
 | |
|         if (part->Entry->Gpt.Name && wcslen(part->Entry->Gpt.Name)) {
 | |
|             s += ":";
 | |
|             for (size_t i = 0; i < wcslen(part->Entry->Gpt.Name); i++)
 | |
|                 s += (CHAR)part->Entry->Gpt.Name[i];
 | |
|         }
 | |
|     } else {
 | |
|         s += "GPT";
 | |
|     }
 | |
|     ret += s;
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     s.Format("      StartingOffset: %I64u\r\n", part->Entry->StartingOffset.QuadPart);
 | |
|     ret += s;
 | |
| 
 | |
|     s.Format("      PartitionLength: %I64u\r\n", part->Entry->PartitionLength.QuadPart);
 | |
|     ret += s;
 | |
| 
 | |
|     /* mount points */
 | |
|     ret += "      MountPoints: ";
 | |
|     ret += Ext2QueryVolumeLetterStrings(part->DrvLetters, NULL);
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     if (!part->Volume) {
 | |
|         return ret;
 | |
|     }
 | |
| 
 | |
|     if (part->Volume->bRecognized) {
 | |
| 
 | |
|         ULONGLONG   totalSize, freeSize;
 | |
| 
 | |
|         s.Format("      Filesystem: %s\r\n", part->Volume->FileSystem);
 | |
|         ret += s;
 | |
| 
 | |
|         if ((part->Volume->EVP.bExt2 || part->Volume->EVP.bExt3)) {
 | |
|             s = "      codepage:";
 | |
|             s += part->Volume->EVP.Codepage;
 | |
|             if (part->Volume->EVP.bReadonly) {
 | |
|                 s += ",Readonly";
 | |
|             }
 | |
|         }
 | |
|         ret += s;
 | |
|         ret += "\r\n";
 | |
| 
 | |
|         totalSize = part->Volume->FssInfo.TotalAllocationUnits.QuadPart;
 | |
|         freeSize  = part->Volume->FssInfo.AvailableAllocationUnits.QuadPart;
 | |
|         totalSize = totalSize * part->Volume->FssInfo.BytesPerSector *
 | |
|                     part->Volume->FssInfo.SectorsPerAllocationUnit;
 | |
|         freeSize  = freeSize * part->Volume->FssInfo.BytesPerSector *
 | |
|                     part->Volume->FssInfo.SectorsPerAllocationUnit;
 | |
|         s.Format("      Size: %I64u\r\n", totalSize);
 | |
|         ret += s;
 | |
| 
 | |
|         s.Format("      Free: %I64u\r\n", freeSize);
 | |
|         ret += s;
 | |
|     } 
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| CString
 | |
| Ext2DiskInformation(PEXT2_DISK  disk)
 | |
| {
 | |
|     CString     s, ret="";
 | |
| 
 | |
|     s.Format("\r\nDisk %d: %s\r\n\r\n", disk->OrderNo, disk->Name);
 | |
|     ret += s;
 | |
| 
 | |
|     if (disk->SDD.VendorIdOffset) {
 | |
|         ret += "\r\n  VendorId: ";
 | |
|         ret += (PCHAR)&disk->SDD + disk->SDD.VendorIdOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     if (disk->SDD.ProductIdOffset) {
 | |
|         ret += "    ProductId: ";
 | |
|         ret += (PCHAR)&disk->SDD + disk->SDD.ProductIdOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     if (disk->SDD.SerialNumberOffset) {
 | |
|         ret += "    SerialNumber: ";
 | |
|         ret += (PCHAR)&disk->SDD + disk->SDD.SerialNumberOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     ret += "    BusType: ";
 | |
|     ret += BusTypeString(disk->SDD.BusType);
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     ret += "    Media Type: ";
 | |
|     if (disk->SDD.RemovableMedia) {
 | |
|         ret += " Removable\r\n";
 | |
|     } else {
 | |
|         s = "RAW";
 | |
|         if (disk->Layout) {
 | |
|             if (disk->Layout->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
|                 if (disk->Layout->PartitionEntry->Mbr.PartitionType
 | |
|                     == PARTITION_LDM) {
 | |
|                     s.LoadString(IDS_DISK_TYPE_DYN);
 | |
|                 } else {
 | |
|                     s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|                 }
 | |
|             } else if (disk->Layout->PartitionStyle == PARTITION_STYLE_GPT) {
 | |
|                  s = "GPT";
 | |
|             }
 | |
|         }
 | |
|         s   += "\r\n";
 | |
|         ret += s;
 | |
|     }
 | |
| 
 | |
|     if (disk->bEjected) {
 | |
|         ret += "    No media\r\n";
 | |
|     } else {
 | |
|         /* geometry information */
 | |
|         ret +=   "    DiskGeometry Layout:\r\n";
 | |
|         s.Format("      BytesPerSector = %u\r\n", disk->DiskGeometry.BytesPerSector);
 | |
|         ret += s;
 | |
|         s.Format("      SectorsPerTrack = %u\r\n", disk->DiskGeometry.SectorsPerTrack);
 | |
|         ret += s;
 | |
|         s.Format("      TracksPerCylinder = %u\r\n", disk->DiskGeometry.TracksPerCylinder);
 | |
|         ret += s;
 | |
|         s.Format("      Cylinderst = %I64u\r\n", disk->DiskGeometry.Cylinders.QuadPart);
 | |
|         ret += s;
 | |
| 
 | |
|         switch (disk->DiskGeometry.MediaType) {
 | |
| 		        case FixedMedia: s="Fixed"; break;
 | |
| 		        case RemovableMedia: s="Removable"; break;
 | |
| 		        case CD_ROM: s="CDROM"; break;
 | |
| 		        case CD_R: s="CDR"; break;
 | |
| 		        case CD_RW: s="CDRW"; break;
 | |
| 		        case DVD_ROM: s="DVD"; break;
 | |
| 		        case DVD_R: s="DVDR"; break;
 | |
| 		        case DVD_RW: s="DVDRW"; break;
 | |
| 		        default: s="Unkown";
 | |
|         }
 | |
| 
 | |
|         ret += "    MediaType: ";
 | |
|         ret += s;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
|  
 | |
|     ret += "\r\n";
 | |
|     if (disk->Layout) {
 | |
|         s.Format("    Partition Numbers: %d\r\n", disk->NumParts);
 | |
|         ret += s;
 | |
| 
 | |
|         for (UCHAR i=0; i < disk->NumParts; i++) {
 | |
|             ret += Ext2PartInformation(&disk->DataParts[i]);
 | |
|             ret += "\r\n";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| CString
 | |
| Ext2CdromInformation(PEXT2_CDROM cdrom)
 | |
| {
 | |
|     CString     s, ret="";
 | |
| 
 | |
|     s.Format("\r\nCdrom %d: %s\r\n\r\n", cdrom->OrderNo, cdrom->Name);
 | |
|     ret += s;
 | |
| 
 | |
|     if (cdrom->SDD.VendorIdOffset) {
 | |
|         ret += "    VendorId: ";
 | |
|         ret += (PCHAR)&cdrom->SDD + cdrom->SDD.VendorIdOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     if (cdrom->SDD.ProductIdOffset) {
 | |
|         ret += "    ProductId: ";
 | |
|         ret += (PCHAR)&cdrom->SDD + cdrom->SDD.ProductIdOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     if (cdrom->SDD.SerialNumberOffset) {
 | |
|         ret += "    SerialNumber: ";
 | |
|         ret += (PCHAR)&cdrom->SDD + cdrom->SDD.SerialNumberOffset;
 | |
|         ret += "\r\n";
 | |
|     }
 | |
| 
 | |
|     ret += "    BusType: ";
 | |
|     ret += BusTypeString(cdrom->SDD.BusType);
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     if (cdrom->bLoaded) {
 | |
|         ret += "    Media Type: ";
 | |
|         if (cdrom->bIsDVD) {
 | |
|             s = "DVD\r\n";
 | |
|         } else {
 | |
|             s = "CDROM\r\n";
 | |
|         }
 | |
|         ret += s;
 | |
| 
 | |
|         ret +=   "    DiskGeometry Layout:\r\n";
 | |
|         s.Format("      BytesPerSector = %u\r\n", cdrom->DiskGeometry.BytesPerSector);
 | |
|         ret += s;
 | |
|         s.Format("      SectorsPerTrack = %u\r\n", cdrom->DiskGeometry.SectorsPerTrack);
 | |
|         ret += s;
 | |
|         s.Format("      TracksPerCylinder = %u\r\n", cdrom->DiskGeometry.TracksPerCylinder);
 | |
|         ret += s;
 | |
|         s.Format("      Cylinderst = %I64u\r\n", cdrom->DiskGeometry.Cylinders.QuadPart);
 | |
|         ret += s;
 | |
|     } else {
 | |
|         s = "    No media\r\n";
 | |
|         ret += s;
 | |
|     }
 | |
| 
 | |
|     if (cdrom->bLoaded) {
 | |
|         if (cdrom->bEjected) {
 | |
| 	        ret += "    Media ejected\r\n";
 | |
|         } else {
 | |
|             ret += "    File system: ";
 | |
|             if (cdrom->EVP.bExt2) {
 | |
|                 s = "EXT";
 | |
|                 s += (CHAR)('2' + cdrom->EVP.bExt3);
 | |
|             } else {
 | |
|                 s = "CDFS";
 | |
|             }
 | |
|             ret += s;
 | |
|             ret += "\r\n";
 | |
| 
 | |
|             s = "    Online,";
 | |
| 	        switch (cdrom->DiskGeometry.MediaType) {
 | |
| 		        case FixedMedia: s +="Fixed"; break;
 | |
| 		        case RemovableMedia: s += "Media Removable"; break;
 | |
| 		        case CD_ROM: s +=" CDROM"; break;
 | |
| 		        case CD_R: s += "CDR"; break;
 | |
| 		        case CD_RW: s += "CDRW"; break;
 | |
| 		        case DVD_ROM: s += "DVD"; break;
 | |
| 		        case DVD_R: s += "DVDR"; break;
 | |
| 		        case DVD_RW: s += "DVDRW"; break;
 | |
| 		        default: s += "Unkown";
 | |
|             }
 | |
|             ret += s;
 | |
|             ret += "\r\n";
 | |
|         }
 | |
|     } else {
 | |
|         ret += "    Device stopped\r\n";
 | |
|     }
 | |
| 
 | |
|     ret += "    Mountpoints: ";
 | |
|     ret += Ext2QueryVolumeLetterStrings(cdrom->DrvLetters, NULL);
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| CString
 | |
| Ext2VolumeInformation(PEXT2_VOLUME vol)
 | |
| {
 | |
|     CString s, ret = "";
 | |
| 
 | |
|     s.Format("\r\nVolume: %s:\r\n\r\n", vol->Name);
 | |
|     ret += s;
 | |
| 
 | |
|     ret += "    Filesystem: ";
 | |
|     ret += vol->FileSystem;
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     /* mount points */
 | |
|     ret += "    Mountpoints: ";
 | |
|     ret += Ext2QueryVolumeLetterStrings(vol->DrvLetters, NULL);
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     /* set volume status */
 | |
|     s = "    Volume status: Online";
 | |
|     if (vol->bRecognized && (vol->EVP.bExt2 || vol->EVP.bExt3)) {
 | |
|         s += ",codepage:";
 | |
|         s += vol->EVP.Codepage;
 | |
|         if (vol->EVP.bReadonly) {
 | |
|             s += ",Readonly";
 | |
|         }
 | |
|     }
 | |
|     ret += s;
 | |
|     ret += "\r\n";
 | |
| 
 | |
|     {
 | |
|         ULONGLONG   totalSize, freeSize;
 | |
|         totalSize = vol->FssInfo.TotalAllocationUnits.QuadPart;
 | |
|         freeSize  = vol->FssInfo.AvailableAllocationUnits.QuadPart;
 | |
|         totalSize = totalSize * vol->FssInfo.BytesPerSector *
 | |
|                     vol->FssInfo.SectorsPerAllocationUnit;
 | |
|         freeSize  = freeSize * vol->FssInfo.BytesPerSector *
 | |
|                     vol->FssInfo.SectorsPerAllocationUnit;
 | |
|         s.Format("    size: %I64u\r\n", totalSize);
 | |
|         ret += s;
 | |
| 
 | |
|         s.Format("    free space: %I64u\r\n", freeSize);
 | |
|         ret += s;
 | |
|     }
 | |
| 
 | |
|     if (vol->Extent) {
 | |
|         for (DWORD i=0; i < vol->Extent->NumberOfDiskExtents; i++) {
 | |
|             s.Format("    Extent: %d\r\n", i);
 | |
|             ret += s;
 | |
|             s.Format("      DiskNumber: %d\r\n", vol->Extent->Extents[i].DiskNumber);
 | |
|             ret += s;
 | |
|             s.Format("      StartingOffset: %I64u\r\n", vol->Extent->Extents[i].StartingOffset.QuadPart);
 | |
|             ret += s;
 | |
|             s.Format("      ExtentLength: %I64u\r\n", vol->Extent->Extents[i].ExtentLength.QuadPart);
 | |
|             ret += s;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| CString
 | |
| Ext2SysInformation()
 | |
| {
 | |
|     ULONG   i = 0;
 | |
|     CString s;
 | |
|     PEXT2_VOLUME  chain = gVols;
 | |
| 
 | |
|     s = "\r\nDisk devices:\r\n";
 | |
|     for (i=0; i < g_nDisks; i++) {
 | |
|         s += Ext2DiskInformation(&gDisks[i]);
 | |
|     }
 | |
| 
 | |
|     s += "\r\nCdrom/DVD devices:\r\n";
 | |
| 
 | |
|     for (i=0; i < g_nCdroms; i++) {
 | |
|         s += Ext2CdromInformation(&gCdroms[i]);
 | |
|     }
 | |
| 
 | |
|     while (chain) {
 | |
|         s += Ext2VolumeInformation(chain);
 | |
|         chain = chain->Next;
 | |
|     }
 | |
| 
 | |
|     return s;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2CleanupDisks()
 | |
| {
 | |
|     ULONG   i = 0;
 | |
| 
 | |
|     for (i=0; i < g_nDisks; i++) {
 | |
|         if (gDisks[i].bLoaded) {
 | |
|             if (gDisks[i].Layout) {
 | |
|                 free(gDisks[i].Layout);
 | |
|                 gDisks[i].Layout = NULL;
 | |
|             }
 | |
|             gDisks[i].bLoaded = FALSE;
 | |
|             if (gDisks[i].DataParts) {
 | |
|                 free(gDisks[i].DataParts);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     g_nDisks = 0;
 | |
|     if (gDisks) {
 | |
|         free(gDisks); gDisks = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2LoadCdroms()
 | |
| {
 | |
|     ULONG           i = 0, j = 0;
 | |
|     NT::NTSTATUS    status;
 | |
|     DWORD           mediaType;
 | |
| 
 | |
|     if (g_nCdroms == 0) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     gCdroms = (PEXT2_CDROM) malloc(sizeof(EXT2_CDROM) * g_nCdroms);
 | |
|     if (gCdroms == NULL) {
 | |
|         return FALSE;
 | |
|     }
 | |
|     memset(gCdroms, 0, sizeof(EXT2_CDROM) * g_nCdroms);
 | |
| 
 | |
|     while (i < g_nCdroms && j < 256) {
 | |
| 
 | |
|         HANDLE          Handle = NULL;
 | |
| 
 | |
|         gCdroms[i].Magic[0] = EXT2_CDROM_DEVICE_MAGIC;
 | |
|         gCdroms[i].Magic[1] = EXT2_CDROM_VOLUME_MAGIC;
 | |
|         gCdroms[i].OrderNo = (UCHAR) j;
 | |
|         gCdroms[i].bLoaded = FALSE;
 | |
|         sprintf(gCdroms[i].Name, "\\Device\\Cdrom%d\0", j);
 | |
| 
 | |
|         j++;
 | |
| 
 | |
|         status = Ext2Open(gCdroms[i].Name, &Handle, EXT2_DESIRED_ACCESS);
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryProperty( Handle, StorageDeviceProperty,
 | |
|                                     (PVOID)&gCdroms[i].SDD,
 | |
|                                     sizeof(STORAGE_DEVICE_DESCRIPTOR)
 | |
|                                   );
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             goto Next;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryProperty( Handle, StorageAdapterProperty,
 | |
|                                     (PVOID)&gCdroms[i].SAD,
 | |
|                                     sizeof(STORAGE_ADAPTER_DESCRIPTOR)
 | |
|                                   );
 | |
|         if (!NT_SUCCESS(status)) {
 | |
|             goto Next;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryDisk(Handle, &gCdroms[i].DiskGeometry);
 | |
|         if (NT_SUCCESS(status)) {
 | |
|             gCdroms[i].bEjected = FALSE;
 | |
|         } else {
 | |
|             // (status == STATUS_NO_MEDIA_IN_DEVICE) {
 | |
|             gCdroms[i].bEjected = TRUE;
 | |
|         }
 | |
| 
 | |
|         status = Ext2QueryMediaType(Handle, &mediaType);
 | |
|         if (NT_SUCCESS(status) && mediaType == FILE_DEVICE_DVD) {
 | |
|             gCdroms[i].bIsDVD = TRUE;
 | |
|         } else {
 | |
|             gCdroms[i].bIsDVD = FALSE;
 | |
|         }
 | |
| 
 | |
|         if (!gCdroms[i].bEjected) {
 | |
|             Ext2QueryExt2Property(Handle, &gCdroms[i].EVP);
 | |
|         }
 | |
| 
 | |
|         gCdroms[i].bLoaded = TRUE;
 | |
| 
 | |
| Next:
 | |
| 
 | |
|         Ext2Close(&Handle);
 | |
|         i++;
 | |
|     }
 | |
| 
 | |
|     g_nCdroms = i;
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2LoadCdromDrvLetters()
 | |
| {
 | |
|     for (ULONG i = 0; i < g_nCdroms; i++) {
 | |
|         gCdroms[i].DrvLetters = Ext2QueryCdromDrvLetters(&gCdroms[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| Ext2CleanupCdroms()
 | |
| {
 | |
|     ULONG   i = 0;
 | |
| 
 | |
|     for (i=0; i < g_nCdroms; i++) {
 | |
|         if (gCdroms[i].bLoaded) {
 | |
|             gCdroms[i].bLoaded = FALSE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     g_nCdroms = 0;
 | |
|     if (gCdroms) {
 | |
|         free(gCdroms); gCdroms = NULL;
 | |
|     }
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2CompareExtents(
 | |
|     PVOLUME_DISK_EXTENTS ext1,
 | |
|     PVOLUME_DISK_EXTENTS ext2
 | |
|     )
 | |
| {
 | |
|     DWORD nExt;
 | |
| 
 | |
|     if (ext1->NumberOfDiskExtents != ext2->NumberOfDiskExtents) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     for (nExt = 0; nExt < ext1->NumberOfDiskExtents; nExt++) {
 | |
|         if ((ext1->Extents[nExt].DiskNumber != ext2->Extents[nExt].DiskNumber) ||
 | |
|             (ext1->Extents[nExt].StartingOffset.QuadPart != ext2->Extents[nExt].StartingOffset.QuadPart) ||
 | |
|             (ext1->Extents[nExt].ExtentLength.QuadPart != ext2->Extents[nExt].ExtentLength.QuadPart) ) {
 | |
|             return FALSE;
 | |
|         }
 | |
|     }
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| ULONGLONG
 | |
| Ext2EjectedDiskLetters(
 | |
|     PEXT2_DISK   Disk
 | |
|     )
 | |
| {
 | |
|     ULONGLONG letters = 0;
 | |
|     int i;
 | |
| 
 | |
|     /* checking the digits ltters */
 | |
|     for (i=0; i < 10; i++) {
 | |
|         if (drvDigits[i].bUsed && drvDigits[i].SDN) {
 | |
|             if (drvDigits[i].SDN->DeviceNumber == Disk->OrderNo) {
 | |
|                 letters |= (((ULONGLONG) 1) << (32 + i));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i=0; i <26; i++) {
 | |
|         if (drvLetters[i].bUsed && drvLetters[i].SDN) {
 | |
|             if (drvLetters[i].SDN->DeviceNumber == Disk->OrderNo) {
 | |
|                 letters |= (((ULONGLONG) 1) << i);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return letters;
 | |
| }
 | |
| 
 | |
| ULONGLONG
 | |
| Ext2QueryVolumeDrvLetters(PEXT2_VOLUME Volume)
 | |
| {
 | |
|     ULONGLONG letters = 0;
 | |
|     int i;
 | |
| 
 | |
|     UCHAR   drvChar = Ext2QueryMountPoint(Volume->Name);
 | |
|     if (drvChar) {
 | |
|         letters |= (((ULONGLONG) 1) << (drvChar - 'A'));
 | |
|     }
 | |
| 
 | |
|     if (!Volume->Extent) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* checking the digits ltters */
 | |
|     for (i=0; i < 10; i++) {
 | |
|         if (drvDigits[i].bUsed && drvDigits[i].Extent) {
 | |
|             if (Ext2CompareExtents(drvDigits[i].Extent, Volume->Extent)) {
 | |
|                 letters |= (((ULONGLONG) 1) << (32 + i));
 | |
|                 if (drvChar != drvDigits[i].Letter) {
 | |
|                     drvDigits[i].bTemporary = TRUE;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i=0; i <26; i++) {
 | |
|         if (drvLetters[i].bUsed && drvLetters[i].Extent) {
 | |
|             if (Ext2CompareExtents(drvLetters[i].Extent, Volume->Extent)) {
 | |
|                 letters |= (((ULONGLONG) 1) << i);
 | |
|                 if (drvChar != drvLetters[i].Letter) {
 | |
|                     drvLetters[i].bTemporary = TRUE;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return letters;
 | |
| }
 | |
| 
 | |
| ULONGLONG
 | |
| Ext2QueryCdromDrvLetters(PEXT2_CDROM Cdrom)
 | |
| {
 | |
|     ULONGLONG letters = 0;
 | |
|     UCHAR   drvChar;
 | |
|     int i;
 | |
| 
 | |
|     if (!Cdrom) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     drvChar = Ext2QueryMountPoint(Cdrom->Name);
 | |
|     if (drvChar) {
 | |
|         letters |= (((ULONGLONG) 1) << (drvChar - 'A'));
 | |
|     }
 | |
| 
 | |
|     /* checking the digits ltters */
 | |
|     for (i=0; i < 10; i++) {
 | |
|         if (drvDigits[i].bUsed && drvDigits[i].DrvType == DRIVE_CDROM) {
 | |
|             if (!_stricmp(drvDigits[i].SymLink, Cdrom->Name)) {
 | |
|                 letters |= (((ULONGLONG) 1) << (i + 32));
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i=0; i <26; i++) {
 | |
|         if (drvLetters[i].bUsed &&  drvLetters[i].DrvType == DRIVE_CDROM) {
 | |
|             if (!_stricmp(drvLetters[i].SymLink, Cdrom->Name)) {
 | |
|                 letters |= (((ULONGLONG) 1) << i);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return letters;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2QueryVolumeFS(
 | |
|     HANDLE          Handle,
 | |
|     PEXT2_VOLUME    volume
 | |
|     )
 | |
| {
 | |
|     struct ext2_super_block *sb = NULL;
 | |
| 	union swap_header*	swap = NULL;
 | |
|     PUCHAR  buffer = NULL;
 | |
| 
 | |
| 
 | |
|     NT::NTSTATUS          status;
 | |
| 
 | |
|     buffer = (PUCHAR)malloc(PAGE_SIZE);
 | |
|     if (!buffer) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     swap = (union swap_header*)&buffer[SWAP_HEADER_OFFSET];
 | |
|     sb = (struct ext2_super_block *)&buffer[SUPER_BLOCK_OFFSET];
 | |
| 
 | |
|     status = Ext2Read( Handle, FALSE, volume->FssInfo.BytesPerSector, 
 | |
|                        (ULONGLONG)0,PAGE_SIZE, (PUCHAR) buffer);
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         free(buffer);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (sb->s_magic == EXT2_SUPER_MAGIC) {
 | |
| 
 | |
|         volume->FsaInfo.FileSystemNameLength = 8;
 | |
|         volume->FsaInfo.FileSystemName[0] = (WCHAR)'E';
 | |
|         volume->FsaInfo.FileSystemName[1] = (WCHAR)'X';
 | |
|         volume->FsaInfo.FileSystemName[2] = (WCHAR)'T';
 | |
|         volume->FsaInfo.FileSystemName[4] = 0;
 | |
|         
 | |
|         if ((sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) ||
 | |
|             (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) ||
 | |
|             (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) ) {
 | |
|             volume->FsaInfo.FileSystemName[3] = (WCHAR)'3';
 | |
|             volume->EVP.bExt3 = TRUE;
 | |
|         } else {
 | |
|             volume->FsaInfo.FileSystemName[3] = (WCHAR)'2';
 | |
|             volume->EVP.bExt2 = TRUE;
 | |
|         }
 | |
|         memcpy(&volume->EVP.UUID[0], &sb->s_uuid[0], 16);
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if ((memcmp(swap->magic.magic, SWAP_HEADER_MAGIC_V1, 10) == 0) ||
 | |
|         (memcmp(swap->magic.magic, SWAP_HEADER_MAGIC_V2, 10) == 0)) {
 | |
|         volume->FsaInfo.FileSystemNameLength = 8;
 | |
|         volume->FsaInfo.FileSystemName[0] = (WCHAR)'S';
 | |
|         volume->FsaInfo.FileSystemName[1] = (WCHAR)'W';
 | |
|         volume->FsaInfo.FileSystemName[2] = (WCHAR)'A';
 | |
|         volume->FsaInfo.FileSystemName[3] = (WCHAR)'P';
 | |
|         volume->FsaInfo.FileSystemName[4] = 0;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     free(buffer);
 | |
|     return (volume->EVP.bExt2 || volume->EVP.bExt3);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2QueryExt2Property (
 | |
|     HANDLE                      Handle,
 | |
|     PEXT2_VOLUME_PROPERTY3      EVP
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS                status;
 | |
|     NT::IO_STATUS_BLOCK         iosb;
 | |
| 
 | |
|     BOOLEAN                     bExt2, bExt3;
 | |
|     CHAR                        UUID[16];
 | |
| 
 | |
|     if (!Ext2IsServiceStarted()) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     bExt2 = EVP->bExt2;
 | |
|     bExt3 = EVP->bExt3;
 | |
|     memcpy(&UUID[0], &EVP->UUID[0], 16);
 | |
|     memset(EVP, 0, sizeof(EXT2_VOLUME_PROPERTY2));
 | |
|     memcpy(&EVP->UUID[0], &UUID[0], 16);
 | |
|     EVP->bExt2 = bExt2;
 | |
|     EVP->bExt3 = bExt3;
 | |
|     EVP->Magic = EXT2_VOLUME_PROPERTY_MAGIC;
 | |
|     EVP->Command = APP_CMD_QUERY_PROPERTY3;
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_APP_VOLUME_PROPERTY,
 | |
|                 EVP, sizeof(EXT2_VOLUME_PROPERTY3),
 | |
|                 EVP, sizeof(EXT2_VOLUME_PROPERTY3)
 | |
|             );
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2QueryPerfStat (
 | |
|     HANDLE                      Handle,
 | |
|     PEXT2_QUERY_PERFSTAT        Stat,
 | |
|     PEXT2_PERF_STATISTICS_V1   *PerfV1,
 | |
|     PEXT2_PERF_STATISTICS_V2   *PerfV2
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS                status;
 | |
|     NT::IO_STATUS_BLOCK         iosb;
 | |
| 
 | |
|     memset(Stat, 0, sizeof(EXT2_QUERY_PERFSTAT));
 | |
|     Stat->Magic = EXT2_VOLUME_PROPERTY_MAGIC;
 | |
|     Stat->Command = IOCTL_APP_QUERY_PERFSTAT;
 | |
| 
 | |
|     *PerfV1 = NULL;
 | |
|     *PerfV2 = NULL;
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_APP_QUERY_PERFSTAT,
 | |
|                 Stat, sizeof(EXT2_QUERY_PERFSTAT),
 | |
|                 Stat, sizeof(EXT2_QUERY_PERFSTAT)
 | |
|             );
 | |
|     if (!NT_SUCCESS(!status))
 | |
|         return FALSE;
 | |
| 
 | |
|     if (iosb.Information == EXT2_QUERY_PERFSTAT_SZV2 && 
 | |
|         (Stat->Flags & EXT2_QUERY_PERFSTAT_VER2) != 0) {
 | |
| 
 | |
|         if (Stat->PerfStatV2.Magic == EXT2_PERF_STAT_MAGIC && 
 | |
|             Stat->PerfStatV2.Length == sizeof(EXT2_PERF_STATISTICS_V2) &&
 | |
|             Stat->PerfStatV2.Version == EXT2_PERF_STAT_VER2) {
 | |
|             *PerfV2 = &Stat->PerfStatV2;
 | |
|         }
 | |
| 
 | |
|     } else if (iosb.Information >= EXT2_QUERY_PERFSTAT_SZV1)  {
 | |
| 
 | |
|         *PerfV1 = &Stat->PerfStatV1;
 | |
|     }
 | |
| 
 | |
|     if (PerfV1 || PerfV2)
 | |
|         return TRUE;
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2StorePropertyinRegistry(PEXT2_VOLUME_PROPERTY3 EVP)
 | |
| {
 | |
|     CHAR    UUID[50], ID[16];
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     LONG    status;
 | |
|     CString data = "";
 | |
| 
 | |
|     int     i;
 | |
|     int     len = 0;
 | |
| 
 | |
|     memset(UUID, 0, 50);
 | |
|     for (i=0; i < 16; i++) {
 | |
|         if (i == 0) {
 | |
|             sprintf(&UUID[len], "{%2.2X", EVP->UUID[i]);
 | |
|             len += 3;
 | |
|         } else if (i == 15) {
 | |
|             sprintf(&UUID[len], "-%2.2X}", EVP->UUID[i]);
 | |
|             len +=4;
 | |
|         } else {
 | |
|             sprintf(&UUID[len], "-%2.2X", EVP->UUID[i]);
 | |
|             len += 3;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Create or open ext2fsd volumes key */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Volumes") ;
 | |
|     status = ::RegCreateKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             0,
 | |
|                             REG_OPTION_NON_VOLATILE,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             NULL,
 | |
|                             &hKey,
 | |
|                             NULL);
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
| #define READING_ONLY        "Readonly"
 | |
| #define WRITING_SUPPORT     "WritingSupport"
 | |
| #define EXT3_FORCEWRITING   "Ext3ForceWriting"
 | |
| #define CODEPAGE_NAME       "CodePage"
 | |
| #define HIDING_PREFIX       "HidingPrefix"
 | |
| #define HIDING_SUFFIX       "HidingSuffix"
 | |
| #define MOUNT_POINT         "MountPoint"
 | |
| #define UID                 "uid"
 | |
| #define GID                 "gid"
 | |
| #define EUID                "euid"
 | |
| #define EGID                "egid"
 | |
| 
 | |
| 
 | |
|     if (EVP->bReadonly) {
 | |
|         data += READING_ONLY";";
 | |
|     } else if (EVP->bExt3 && EVP->bExt3Writable) {
 | |
|         data += EXT3_FORCEWRITING";";
 | |
|     }
 | |
| 
 | |
|     if (EVP->DrvLetter) {
 | |
|         if ((EVP->DrvLetter & 0x7F) == 0 || EVP->DrvLetter == 0xFF) {
 | |
|             data += MOUNT_POINT";";
 | |
|         } else {
 | |
|             data += MOUNT_POINT"=";
 | |
|             data += (CHAR)(EVP->DrvLetter & 0x7F);
 | |
|             data += ":;";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (strlen((CHAR*)EVP->Codepage) > 0) {
 | |
|         data += CODEPAGE_NAME"=";
 | |
|         data += &EVP->Codepage[0];
 | |
|         data += ";";
 | |
|     }
 | |
| 
 | |
|     if (EVP->bHidingPrefix) {
 | |
|         data += HIDING_PREFIX"=";
 | |
|         data += EVP->sHidingPrefix;
 | |
|         data += ";";
 | |
|     }
 | |
| 
 | |
|     if (EVP->bHidingSuffix) {
 | |
|         data += HIDING_SUFFIX"=";
 | |
|         data += EVP->sHidingSuffix;
 | |
|         data += ";";
 | |
|     }
 | |
| 
 | |
|     if (EVP->Flags2 & EXT2_VPROP3_USERIDS) {
 | |
|         sprintf(ID, "%u", EVP->uid);
 | |
|         data += UID"=";
 | |
|         data += ID;
 | |
|         data += ";";
 | |
| 
 | |
|         sprintf(ID, "%u", EVP->gid);
 | |
|         data += GID"=";
 | |
|         data += ID;
 | |
|         data += ";";
 | |
| 
 | |
|         if (EVP->EIDS) {
 | |
|             sprintf(ID, "%u", EVP->euid);
 | |
|             data += EUID"=";
 | |
|             data += ID;
 | |
|             data += ";";
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* set volume parameters */
 | |
|     status = RegSetValueEx( hKey, UUID, 0, REG_SZ, (BYTE *)
 | |
|                             data.GetBuffer(data.GetLength()),
 | |
|                             data.GetLength());
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| }
 | |
| 
 | |
| BOOL Ext2IsNullUuid (__u8 * uuid)
 | |
| {
 | |
|     int i;
 | |
|     for (i = 0; i < 16; i++) {
 | |
|         if (uuid[i]) {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return (i >= 16);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2CheckVolumeRegistryProperty(PEXT2_VOLUME_PROPERTY3 EVP)
 | |
| {
 | |
|     CHAR    UUID[50];
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     CHAR    content[MAX_PATH];
 | |
|     LONG    status, type = 0;
 | |
| 
 | |
|     int     i;
 | |
|     int     len = 0;
 | |
|     BOOL rc = TRUE;
 | |
| 
 | |
|     if (Ext2IsNullUuid(&EVP->UUID[0])) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     memset(UUID, 0, 50);
 | |
|     for (i=0; i < 16; i++) {
 | |
|         if (i == 0) {
 | |
|             sprintf(&UUID[len], "{%2.2X", EVP->UUID[i]);
 | |
|             len += 3;
 | |
|         } else if (i == 15) {
 | |
|             sprintf(&UUID[len], "-%2.2X}", EVP->UUID[i]);
 | |
|             len +=4;
 | |
|         } else {
 | |
|             sprintf(&UUID[len], "-%2.2X", EVP->UUID[i]);
 | |
|             len += 3;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* Create or open ext2fsd volumes key */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Volumes") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* Query volume parameters */
 | |
|     len = MAX_PATH;
 | |
|     status = RegQueryValueEx(hKey,
 | |
|                             &UUID[0],
 | |
|                             0,
 | |
|                             (LPDWORD)&type,
 | |
|                             (BYTE *)&content[0],
 | |
|                             (LPDWORD)&len);
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|     }
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
| errorout:
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2SetDefaultVolumeRegistryProperty(PEXT2_VOLUME_PROPERTY3 EVP)
 | |
| {
 | |
|     ULONG   StartMode;
 | |
|     BOOL AutoMount = 0;
 | |
| 
 | |
|     if (Ext2IsNullUuid(&EVP->UUID[0])) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* query global parameters */
 | |
|     Ext2QueryGlobalProperty(
 | |
|             &StartMode,
 | |
|             (BOOL *)&EVP->bReadonly,
 | |
|             (BOOL *)&EVP->bExt3Writable,
 | |
|             (CHAR *)EVP->Codepage,
 | |
|             (CHAR *)NULL,
 | |
|             (CHAR *)NULL,
 | |
|             (BOOL *)&AutoMount
 | |
|             );
 | |
| 
 | |
|     if (EVP->bExt3 && !EVP->bExt3Writable)
 | |
|         EVP->bReadonly = TRUE;
 | |
| 
 | |
|     EVP->DrvLetter = 0x80;
 | |
|     EVP->Flags2 |= EXT2_VPROP3_AUTOMOUNT;
 | |
|     Ext2StorePropertyinRegistry(EVP);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetExt2Property (
 | |
|     HANDLE                Handle,
 | |
|     PEXT2_VOLUME_PROPERTY3 EVP
 | |
|     )
 | |
| {
 | |
|     NT::NTSTATUS                status;
 | |
|     NT::IO_STATUS_BLOCK         iosb;
 | |
| 
 | |
|     ASSERT(EVP->Magic == EXT2_VOLUME_PROPERTY_MAGIC);
 | |
|     EVP->Command = APP_CMD_SET_PROPERTY3;
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 Handle, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_APP_VOLUME_PROPERTY,
 | |
|                 EVP, sizeof(EXT2_VOLUME_PROPERTY3),
 | |
|                 EVP, sizeof(EXT2_VOLUME_PROPERTY3)
 | |
|             );
 | |
| 
 | |
|     if (NT_SUCCESS(status)) {
 | |
|         return TRUE;
 | |
|     } else {
 | |
|         CString s;
 | |
|         s.Format("Status = %xh\n", status);
 | |
|         AfxMessageBox(s);
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2QueryGlobalProperty(
 | |
|     ULONG *     ulStartup,
 | |
|     BOOL *   bReadonly,
 | |
|     BOOL *   bExt3Writable,
 | |
|     CHAR *      Codepage,
 | |
|     CHAR *      sPrefix,
 | |
|     CHAR *      sSuffix,
 | |
|     BOOL *   bAutoMount
 | |
|     )
 | |
| {
 | |
|     int     rc = TRUE;
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     DWORD   data = 0;
 | |
|     LONG    status, type, len;
 | |
| 
 | |
|     /* Open ext2fsd sevice key */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* Query Start type */
 | |
|     len = sizeof(DWORD);
 | |
|     status = RegQueryValueEx( hKey,
 | |
|                             "Start",
 | |
|                             0,
 | |
|                             (LPDWORD)&type,
 | |
|                             (BYTE *)&data,
 | |
|                             (LPDWORD)&len);
 | |
|     if (status == ERROR_SUCCESS) {
 | |
|         *ulStartup = data;
 | |
|     }
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     /* Open ext2fsd parameters key */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Parameters") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* Query WritingSupport */
 | |
|     len = sizeof(DWORD);
 | |
|     status = RegQueryValueEx( hKey,
 | |
|                             "WritingSupport",
 | |
|                             0,
 | |
|                             (LPDWORD)&type,
 | |
|                             (BYTE *)&data,
 | |
|                             (LPDWORD)&len);
 | |
|     if (status == ERROR_SUCCESS) {
 | |
|         *bReadonly = (data == 0);
 | |
|     }
 | |
| 
 | |
|     /* query Ext3ForceWriting */
 | |
|     len = sizeof(DWORD);
 | |
|     status = RegQueryValueEx( hKey,
 | |
|                             "Ext3ForceWriting",
 | |
|                             0,
 | |
|                             (LPDWORD)&type,
 | |
|                             (BYTE *)&data,
 | |
|                             (LPDWORD)&len);
 | |
| 
 | |
|     if (status == ERROR_SUCCESS) {
 | |
|         *bExt3Writable = (data != 0);
 | |
|     }
 | |
| 
 | |
|     /* query AutoMount */
 | |
|     len = sizeof(DWORD);
 | |
|     status = RegQueryValueEx( hKey,
 | |
|                             "AutoMount",
 | |
|                             0,
 | |
|                             (LPDWORD)&type,
 | |
|                             (BYTE *)&data,
 | |
|                             (LPDWORD)&len);
 | |
| 
 | |
|     if (status == ERROR_SUCCESS) {
 | |
|         *bAutoMount = (data != 0);
 | |
|     }
 | |
| 
 | |
|     if (Codepage) {
 | |
|         /* query codepage */
 | |
|         len = CODEPAGE_MAXLEN;
 | |
|         status = RegQueryValueEx( hKey,
 | |
|                                 "CodePage",
 | |
|                                 0,
 | |
|                                 (LPDWORD)&type,
 | |
|                                 (BYTE *)Codepage,
 | |
|                                 (LPDWORD)&len);
 | |
|     }
 | |
| 
 | |
|     if (sPrefix) {
 | |
|         /* querying hidding filter patterns */
 | |
|         len = CODEPAGE_MAXLEN;
 | |
|         status = RegQueryValueEx( hKey,
 | |
|                                 "HidingPrefix",
 | |
|                                 0,
 | |
|                                 (LPDWORD)&type,
 | |
|                                 (BYTE *)sPrefix,
 | |
|                                 (LPDWORD)&len);
 | |
|     }
 | |
| 
 | |
|     if (sSuffix) {
 | |
|         len = CODEPAGE_MAXLEN;
 | |
|         status = RegQueryValueEx( hKey,
 | |
|                                 "HidingSuffix",
 | |
|                                 0,
 | |
|                                 (LPDWORD)&type,
 | |
|                                 (BYTE *)sSuffix,
 | |
|                                 (LPDWORD)&len);
 | |
|     }
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| INT
 | |
| Ext2QueryDrvVersion(
 | |
|     CHAR *      Version,
 | |
|     CHAR *      Date,
 | |
|     CHAR *      Time
 | |
|     )
 | |
| {
 | |
|     EXT2_VOLUME_PROPERTY_VERSION EVPV;
 | |
|     NT::NTSTATUS                 status;
 | |
|     HANDLE                       handle = NULL;
 | |
|     NT::IO_STATUS_BLOCK          iosb;
 | |
|     INT                          rc = 0;
 | |
| 
 | |
|     memset(&EVPV, 0, sizeof(EXT2_VOLUME_PROPERTY_VERSION));
 | |
|     EVPV.Magic = EXT2_VOLUME_PROPERTY_MAGIC;
 | |
|     EVPV.Command = APP_CMD_QUERY_VERSION;
 | |
|     EVPV.Flags |= EXT2_FLAG_VP_SET_GLOBAL;
 | |
| 
 | |
|     status = Ext2Open("\\DosDevices\\Ext2Fsd", 
 | |
|                       &handle, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         rc = -1;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 handle, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_APP_VOLUME_PROPERTY,
 | |
|                 &EVPV, sizeof(EXT2_VOLUME_PROPERTY_VERSION),
 | |
|                 &EVPV, sizeof(EXT2_VOLUME_PROPERTY_VERSION)
 | |
|             );
 | |
| 
 | |
|     if (NT_SUCCESS(status)) {
 | |
|         strncpy(Version,  EVPV.Version, 0x1B);
 | |
|         strncpy(Date,     EVPV.Date,    0x1F);
 | |
|         strncpy(Time,     EVPV.Time,    0x1F);
 | |
|     }
 | |
| 
 | |
|     rc = NT_SUCCESS(status);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&handle);
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetGlobalProperty (
 | |
|     ULONG       ulStartup,
 | |
|     BOOLEAN     bReadonly,
 | |
|     BOOLEAN     bExt3Writable,
 | |
|     CHAR *      Codepage,
 | |
|     CHAR *      sPrefix,
 | |
|     CHAR *      sSuffix,
 | |
|     BOOL     bAutoMount
 | |
|     )
 | |
| {
 | |
|     EXT2_VOLUME_PROPERTY3 EVP;
 | |
| 
 | |
|     NT::NTSTATUS         status;
 | |
|     HANDLE  Handle = NULL;
 | |
|     int     rc = TRUE;
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH] ;
 | |
| 
 | |
|     ULONG   data = 0;
 | |
| 
 | |
|     memset(&EVP, 0, sizeof(EXT2_VOLUME_PROPERTY3));
 | |
|     EVP.Magic = EXT2_VOLUME_PROPERTY_MAGIC;
 | |
|     EVP.Command = APP_CMD_SET_PROPERTY3;
 | |
|     EVP.Flags |= EXT2_FLAG_VP_SET_GLOBAL;
 | |
|     EVP.bReadonly = bReadonly;
 | |
|     EVP.bExt3Writable = bExt3Writable;
 | |
|     strcpy((CHAR *)EVP.Codepage, Codepage);
 | |
| 
 | |
|     if (strlen(sPrefix)) {
 | |
|         strcpy(EVP.sHidingPrefix, sPrefix);
 | |
|         EVP.bHidingPrefix = TRUE;
 | |
|     }
 | |
| 
 | |
|     if (strlen(sSuffix)) {
 | |
|         strcpy(EVP.sHidingSuffix, sSuffix);
 | |
|         EVP.bHidingSuffix = TRUE;
 | |
|     }
 | |
| 
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* set Start type */
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "Start",
 | |
|                             0,
 | |
|                             REG_DWORD,
 | |
|                             (BYTE *)&ulStartup,
 | |
|                             sizeof(DWORD));
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Parameters") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* set WritingSupport */
 | |
|     data = !bReadonly;
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "WritingSupport",
 | |
|                             0,
 | |
|                             REG_DWORD,
 | |
|                             (BYTE *)&data,
 | |
|                             sizeof(ULONG));
 | |
| 
 | |
|     /* set Ext3ForceWriting */
 | |
|     data = bExt3Writable;
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "Ext3ForceWriting",
 | |
|                             0,
 | |
|                             REG_DWORD,
 | |
|                             (BYTE *)&data,
 | |
|                             sizeof(ULONG));
 | |
|     /* set AutoMount */
 | |
|     data = bAutoMount;
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "AutoMount",
 | |
|                             0,
 | |
|                             REG_DWORD,
 | |
|                             (BYTE *)&data,
 | |
|                             sizeof(ULONG));
 | |
| 
 | |
| 
 | |
|     /* set codepage */
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "CodePage",
 | |
|                             0,
 | |
|                             REG_SZ,
 | |
|                             (BYTE *)Codepage,
 | |
|                             strlen(Codepage));
 | |
| 
 | |
|     /* set hiding filter patterns */
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "HidingPrefix",
 | |
|                             0,
 | |
|                             REG_SZ,
 | |
|                             (BYTE *)sPrefix,
 | |
|                             strlen(sPrefix));
 | |
| 
 | |
|     status = RegSetValueEx( hKey,
 | |
|                             "HidingSuffix",
 | |
|                             0,
 | |
|                             REG_SZ,
 | |
|                             (BYTE *)sSuffix,
 | |
|                             strlen(sSuffix));
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     status = Ext2Open("\\DosDevices\\Ext2Fsd", &Handle, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     EVP.Flags2 = EXT2_VPROP3_AUTOMOUNT;
 | |
|     EVP.AutoMount = g_bAutoMount;
 | |
| 
 | |
|     rc = Ext2SetExt2Property(Handle, &EVP);
 | |
|     if (!rc) {
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&Handle);
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetService(PCHAR Target, PCHAR Name, PCHAR Desc, BOOL bInstall)
 | |
| {
 | |
|     SC_HANDLE   hService;
 | |
|     SC_HANDLE   hManager;
 | |
| 
 | |
|     // open Service Control Manager
 | |
|     hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 | |
|     if (hManager == NULL) {
 | |
|         // AfxMessageBox("Ext2Mgr: cannot open Service Control Manager",
 | |
|         //               MB_ICONEXCLAMATION | MB_OK);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (bInstall) {
 | |
| 
 | |
|         // now create service entry
 | |
|         hService = CreateService(
 | |
|                 hManager,                   // SCManager database
 | |
|                 Name,                       // name of service
 | |
|                 Desc,                       // name to display
 | |
|                 SERVICE_ALL_ACCESS,	        // desired access
 | |
|                 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
 | |
|                                             // service type
 | |
|                 SERVICE_AUTO_START,	        // start type
 | |
|                 SERVICE_ERROR_NORMAL,       // error control type
 | |
| 				Target,	                    // service's binary
 | |
|                 NULL,                       // no load ordering group
 | |
|                 NULL,                       // no tag identifier
 | |
|                 NULL,			            // dependencies
 | |
|                 NULL,						// LocalSystem account
 | |
|                 NULL);                      // no password
 | |
| 
 | |
|         if (hService == NULL) {
 | |
|             DWORD error = GetLastError();
 | |
|             if (error == ERROR_SERVICE_EXISTS) {
 | |
|                 // AfxMessageBox("Service is already registered.",
 | |
|                 //               MB_ICONEXCLAMATION | MB_OK);
 | |
|             } else {
 | |
|                 // AfxMessageBox("Service couldn't be registered.",
 | |
|                 //               MB_ICONEXCLAMATION | MB_OK);
 | |
|             }
 | |
|         } else {
 | |
| 
 | |
|             CloseServiceHandle(hService);
 | |
|         }
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         /* open the service */
 | |
|         hService = OpenService(
 | |
|                 hManager,
 | |
|                 Name,
 | |
|                 SERVICE_ALL_ACCESS
 | |
|                 );
 | |
| 
 | |
|         if (hService != NULL) {
 | |
| 
 | |
|             // remove the service from the SCM
 | |
|             if (DeleteService(hService)) {
 | |
|             } else {
 | |
|                 DWORD error = GetLastError();
 | |
|                 if (error == ERROR_SERVICE_MARKED_FOR_DELETE) {
 | |
|                     // AfxMessageBox("Service is already unregistered",
 | |
|                     //               MB_ICONEXCLAMATION | MB_OK);
 | |
|                 } else {
 | |
|                     // AfxMessageBox("Service could not be unregistered",
 | |
|                     //                MB_ICONEXCLAMATION | MB_OK);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             CloseServiceHandle(hService);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     CloseServiceHandle(hManager);
 | |
| 
 | |
| 	return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL ExtSaveResourceToFile(UINT id, CHAR *target)
 | |
| {
 | |
| 	HANDLE	handle;
 | |
| 	ULONG	bytes = 0;
 | |
|     BOOL rc = FALSE;
 | |
| 
 | |
|     HRSRC   hr = FindResource(NULL, MAKEINTRESOURCE(id), RT_RCDATA);
 | |
|     ULONG   size = SizeofResource(NULL, hr);
 | |
|     HGLOBAL hg = LoadResource(NULL, hr);
 | |
|     PVOID   data = LockResource(hg);
 | |
| 
 | |
|     if (!data)
 | |
|         goto errorout;
 | |
| 
 | |
| 	handle = CreateFile(target, GENERIC_READ | GENERIC_WRITE,
 | |
|                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
 | |
| 		                CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
 | |
| 	if (handle == INVALID_HANDLE_VALUE) {
 | |
| 		goto errorout;
 | |
| 	}
 | |
| 
 | |
|     rc = WriteFile(handle, data, size, &bytes, NULL);
 | |
|     if (rc)
 | |
|         rc = (bytes == size);
 | |
| 
 | |
| 	CloseHandle(handle);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
| 	return rc;
 | |
| }
 | |
| 
 | |
| TCHAR *Ext2StrLastA(TCHAR *t, TCHAR *s);
 | |
| 
 | |
| BOOL Ext2InstallExt2Srv()
 | |
| {
 | |
|     TCHAR   cmd[512] = {0}, *p;
 | |
|     BOOL    rc = FALSE;
 | |
| 
 | |
|     if (GetWindowsDirectory(cmd, 512)) {
 | |
|         if (g_isWow64)
 | |
|             strcat(cmd, "\\SysWOW64\\Ext2Srv.EXE");
 | |
|         else
 | |
|             strcat(cmd, "\\System32\\Ext2Srv.EXE");
 | |
|         rc = ExtSaveResourceToFile(IDR_RCDAT_SRV, cmd);
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         GetModuleFileName(NULL, cmd, 510);
 | |
|         p = Ext2StrLastA(cmd, ".EXE");
 | |
|         if (p && p > &cmd[3]) {
 | |
|             p[-3] = 'S';
 | |
|             p[-2] = 'r';
 | |
|             p[-1] = 'v';
 | |
|         } else {
 | |
|             strcat(cmd, "-Srv.EXE");
 | |
|         }
 | |
|         rc = ExtSaveResourceToFile(IDR_RCDAT_SRV, cmd);
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         GetTempPath(50, cmd);
 | |
|         strcat(cmd, "\\Ext2Srv.EXE");
 | |
|         rc = ExtSaveResourceToFile(IDR_RCDAT_SRV, cmd);
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         return rc;
 | |
|     }
 | |
| 
 | |
|     rc = Ext2SetService(cmd, "Ext2Srv", "Ext2Fsd Service Manager", TRUE);
 | |
|     if (!rc) {
 | |
|         return rc;
 | |
|     }
 | |
| 
 | |
|     return Ext2StartService("Ext2Srv");
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2StartService(CHAR *service)
 | |
| {
 | |
|     BOOL     rc = FALSE;
 | |
|     SC_HANDLE   scmHandle = NULL;
 | |
|     SC_HANDLE   drvHandle = NULL;
 | |
| 
 | |
|     scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 | |
|     if (!scmHandle) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     drvHandle = OpenService(scmHandle,
 | |
|                             service,
 | |
|                             SERVICE_ALL_ACCESS);
 | |
|     if (!drvHandle) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     rc = (0 != StartService(drvHandle, 0, NULL));
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (drvHandle)
 | |
|         CloseServiceHandle(drvHandle);
 | |
| 
 | |
|     if (scmHandle) {
 | |
|         CloseServiceHandle(scmHandle);
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2StartExt2Srv()
 | |
| {
 | |
|     BOOL rc = Ext2StartService("Ext2Srv");
 | |
|     if (!rc)
 | |
|         rc = Ext2InstallExt2Srv();
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2StartExt2Fsd()
 | |
| {
 | |
|     if (Ext2IsServiceStarted()) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return Ext2StartService("ext2fsd");
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2IsServiceStarted()
 | |
| {
 | |
|     NT::NTSTATUS         status;
 | |
|     HANDLE               Handle = NULL;
 | |
| 
 | |
|     status = Ext2Open("\\DosDevices\\Ext2Fsd",
 | |
|                       &Handle, EXT2_DESIRED_ACCESS);
 | |
| 
 | |
|     Ext2Close(&Handle);
 | |
|     if (NT_SUCCESS(status)) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2IsRemovable(PEXT2_VOLUME volume)
 | |
| {
 | |
|     STORAGE_BUS_TYPE busType = BusTypeAta;
 | |
|     BOOL bRemovableMedia = FALSE;
 | |
| 
 | |
|     if (volume && volume->Part) {
 | |
|         busType = volume->Part->Disk->SDD.BusType;
 | |
|         bRemovableMedia = volume->Part->Disk->SDD.RemovableMedia;
 | |
|     }
 | |
| 
 | |
|     if (busType == BusType1394 ||
 | |
|         busType == BusTypeUsb ||
 | |
|         bRemovableMedia  ) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2RemoveDriveLetter(CHAR DrvLetter)
 | |
| {
 | |
|     PEXT2_LETTER drvLetter = NULL;
 | |
|     BOOL rc = FALSE;
 | |
| 
 | |
|     if (DrvLetter >= '0' && DrvLetter <= '9') {
 | |
|         drvLetter = &drvDigits[DrvLetter - '0'];
 | |
|     } else if (DrvLetter >= 'A' && DrvLetter <= 'Z') {
 | |
|         drvLetter = &drvLetters[DrvLetter - 'A'];
 | |
|     } else if (DrvLetter >= 'a' && DrvLetter <= 'z') {
 | |
|         drvLetter = &drvLetters[DrvLetter - 'a'];
 | |
|     }
 | |
| 
 | |
|     if (drvLetter && drvLetter->bUsed) {
 | |
|         rc = Ext2RemoveDrvLetter(drvLetter);
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2InitializeVolume(
 | |
|     PCHAR           NameString,
 | |
|     PEXT2_VOLUME *  Volume
 | |
|     )
 | |
| {
 | |
|     BOOL rc = FALSE;
 | |
|     HANDLE hVolume = NULL;
 | |
|     NT::NTSTATUS status;
 | |
|     NT::IO_STATUS_BLOCK ioSb;
 | |
|     PEXT2_VOLUME        volume = NULL;
 | |
| 
 | |
|     volume = (PEXT2_VOLUME) malloc(sizeof(EXT2_VOLUME));
 | |
|     if (!volume) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = Ext2Open(NameString, &hVolume, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         free(volume); volume = NULL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     memset(volume, 0, sizeof(EXT2_VOLUME));
 | |
|     volume->Magic = EXT2_VOLUME_MAGIC;
 | |
|     strcpy(volume->Name, NameString);
 | |
| 
 | |
|     status = NT::ZwQueryVolumeInformationFile(
 | |
|                         hVolume, &ioSb, &volume->FsaInfo,
 | |
|                         MAX_PATH, NT::FileFsAttributeInformation
 | |
|                         );
 | |
| 
 | |
|     if (NT_SUCCESS(status)) {
 | |
| 
 | |
|         NT::UNICODE_STRING uniString;
 | |
|         NT::ANSI_STRING    aniString;
 | |
| 
 | |
|         NT::ZwQueryVolumeInformationFile(
 | |
|                         hVolume, &ioSb, &volume->FsdInfo,
 | |
|                         sizeof(NT::FILE_FS_DEVICE_INFORMATION),
 | |
|                         NT::FileFsDeviceInformation
 | |
|                         );
 | |
| 
 | |
|         NT::ZwQueryVolumeInformationFile(
 | |
|                         hVolume, &ioSb, &volume->FssInfo,
 | |
|                         sizeof(NT::FILE_FS_SIZE_INFORMATION),
 | |
|                         NT::FileFsSizeInformation
 | |
|                         );
 | |
| 
 | |
|         if (volume->FsaInfo.FileSystemNameLength == 6 &&
 | |
|             (volume->FsaInfo.FileSystemName[0] == (WCHAR)'R' ||
 | |
|              volume->FsaInfo.FileSystemName[0] == (WCHAR)'r') &&
 | |
|             (volume->FsaInfo.FileSystemName[1] == (WCHAR)'A' ||
 | |
|              volume->FsaInfo.FileSystemName[1] == (WCHAR)'a') &&
 | |
|             (volume->FsaInfo.FileSystemName[2] == (WCHAR)'W' ||
 | |
|              volume->FsaInfo.FileSystemName[2] == (WCHAR)'w')) {
 | |
|             if (!Ext2QueryVolumeFS(hVolume, volume)) {
 | |
|                 /* memcpy(volume->Codepage, "N/A", 3); */
 | |
|             }
 | |
| 
 | |
|         } else {
 | |
|             if (Ext2QueryExt2Property(hVolume, &volume->EVP)) {
 | |
|                 volume->bRecognized = TRUE;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /* convert the unicode file system name to mbs */
 | |
| 
 | |
|         uniString.MaximumLength = uniString.Length = 
 | |
|             (USHORT)volume->FsaInfo.FileSystemNameLength; 
 | |
|         uniString.Buffer = volume->FsaInfo.FileSystemName;
 | |
| 
 | |
|         aniString.Buffer = volume->FileSystem;
 | |
|         aniString.Length = 0;
 | |
|         aniString.MaximumLength = 64;
 | |
| 
 | |
|         memset(volume->FileSystem, 0, 64);
 | |
|         NT::RtlUnicodeStringToAnsiString(&aniString, &uniString, FALSE);
 | |
|     }
 | |
| 
 | |
|     volume->Extent = Ext2QueryVolumeExtents(hVolume);
 | |
|     if (!volume->Extent) {
 | |
|         free(volume); volume = NULL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     *Volume = volume; rc = TRUE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&hVolume);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| CHAR
 | |
| Ext2ProcessExt2Property(PEXT2_VOLUME volume)
 | |
| {
 | |
|     HANDLE hVolume = NULL;
 | |
|     NT::NTSTATUS status;
 | |
|     CHAR rc = 0;
 | |
| 
 | |
|     status = Ext2Open(volume->Name, &hVolume, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (Ext2QueryExt2Property(hVolume, &volume->EVP)) {
 | |
|         if (volume->DrvLetters == 0 && volume->EVP.DrvLetter) {
 | |
|             CHAR DrvLetter = volume->EVP.DrvLetter & 0x7F;
 | |
|             if (DrvLetter && Ext2IsDrvLetterAvailable(DrvLetter)) {
 | |
|                 rc = Ext2MountVolumeAs(volume->Name, DrvLetter);
 | |
|             } else {
 | |
|                 rc = volume->EVP.DrvLetter = Ext2MountVolume(volume->Name);
 | |
|                 volume->EVP.DrvLetter |= 0x80;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&hVolume);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL Ext2ProcessExt2Volumes()
 | |
| {
 | |
|     PEXT2_VOLUME    volume = gVols;
 | |
|     BOOL         rc = FALSE;
 | |
| 
 | |
|     while (volume) {
 | |
|         if (Ext2ProcessExt2Property(volume)) {
 | |
|             rc = TRUE;
 | |
|         }
 | |
|         volume = volume->Next;
 | |
|     }
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2IsPartitionExtent(
 | |
|     ULONG                  disk,
 | |
|     PPARTITION_INFORMATION_EXT part,
 | |
|     PVOLUME_DISK_EXTENTS   extent
 | |
|     )
 | |
| {
 | |
|     DWORD nExt = 0;
 | |
| 
 | |
|     for (nExt = 0; nExt < extent->NumberOfDiskExtents; nExt++) {
 | |
|         if ((extent->Extents[nExt].DiskNumber == disk) &&
 | |
|             (extent->Extents[nExt].StartingOffset.QuadPart == 
 | |
|              part->StartingOffset.QuadPart ) &&
 | |
|             (extent->Extents[nExt].ExtentLength.QuadPart ==
 | |
|              part->PartitionLength.QuadPart)) {
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| /* should be called after volumes' initiaization */
 | |
| BOOL
 | |
| Ext2LoadDiskPartitions(PEXT2_DISK Disk)
 | |
| {
 | |
|     UCHAR i = 0, cnt = 0;
 | |
|     ULONG j = 0;
 | |
| 
 | |
|     BOOL bDynamic = FALSE;
 | |
| 
 | |
|     if (Disk->NumParts == 0) {
 | |
|         Disk->NumParts = 1;
 | |
|     }
 | |
| 
 | |
|     Disk->DataParts = (PEXT2_PARTITION) malloc(
 | |
|                         sizeof(EXT2_PARTITION) * Disk->NumParts);
 | |
|     if (!Disk->DataParts) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     memset(Disk->DataParts, 0, sizeof(EXT2_PARTITION) * Disk->NumParts);
 | |
| 
 | |
|     if (Disk->Layout) {
 | |
|         if (Disk->Layout->PartitionStyle == PARTITION_STYLE_MBR && 
 | |
|             Disk->Layout->PartitionEntry->Mbr.PartitionType == PARTITION_LDM) {
 | |
|             bDynamic = TRUE;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         /* Now walk through driveLayout and pack partitions */
 | |
|         for (i = 0; (Disk->Layout != NULL) && 
 | |
|              (i < (UCHAR)Disk->Layout->PartitionCount); i++) {
 | |
| 
 | |
|             PPARTITION_INFORMATION_EXT  Part;
 | |
|             Part = &Disk->Layout->PartitionEntry[i];
 | |
| 
 | |
|             if (Disk->Layout->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
|                 if (Part->Mbr.PartitionType == PARTITION_ENTRY_UNUSED ||
 | |
|                     Part->Mbr.PartitionType == PARTITION_EXTENDED || 
 | |
|                     Part->Mbr.PartitionType == PARTITION_XINT13_EXTENDED) {
 | |
|                     continue;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             sprintf(&Disk->DataParts[cnt].Name[0],
 | |
|                     "\\Device\\Harddisk%u\\Partition%u",
 | |
|                     Disk->OrderNo, cnt + 1);
 | |
|             Disk->DataParts[cnt].Magic = EXT2_PART_MAGIC;
 | |
|             Disk->DataParts[cnt].PartType = Disk->Layout->PartitionStyle;
 | |
| 
 | |
|             Disk->DataParts[cnt].Disk = Disk;
 | |
|             Disk->DataParts[cnt].Number = cnt + 1;
 | |
|             Disk->DataParts[cnt++].Entry = Part;
 | |
|         }
 | |
| 
 | |
|         /* Search the volumes of the partition */
 | |
|         for (i=0; i < cnt; i++) {
 | |
| 
 | |
|             PEXT2_VOLUME   volume = gVols;
 | |
|             for (j=0; (ULONG)j < g_nVols; j++) {
 | |
|                 if (Ext2IsPartitionExtent(Disk->OrderNo, 
 | |
|                         Disk->DataParts[i].Entry,
 | |
|                         volume->Extent )) {
 | |
|                     volume->bDynamic = bDynamic;
 | |
|                     if (volume->Extent->NumberOfDiskExtents == 1) {
 | |
|                         volume->Part = &Disk->DataParts[i];
 | |
|                     }
 | |
|                     Disk->DataParts[i].Volume = volume;
 | |
|                     Disk->DataParts[i].DrvLetters = volume->DrvLetters;
 | |
|                     break;
 | |
|                 }
 | |
|                 volume = volume->Next;
 | |
|             }
 | |
|         }
 | |
|     } else {
 | |
|         Disk->DataParts[cnt].Magic = EXT2_PART_MAGIC;
 | |
|         Disk->DataParts[cnt].Disk = Disk;
 | |
|         Disk->DataParts[cnt].Number = cnt + 1;
 | |
|         Disk->DataParts[cnt].DrvLetters = Ext2EjectedDiskLetters(Disk);
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| Ext2LoadAllDiskPartitions()
 | |
| {
 | |
|     for (ULONG i=0; i < g_nDisks; i++) {
 | |
|         Ext2LoadDiskPartitions(&gDisks[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2MountingVolumes()
 | |
| {
 | |
|     PEXT2_VOLUME   volume = gVols;
 | |
|     int j;
 | |
| 
 | |
|     if (!Ext2IsServiceStarted()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     for (j=0; (ULONG)j < g_nVols; j++) {
 | |
|         if ((volume->EVP.bExt2 || volume->EVP.bExt3) && !volume->bRecognized) {
 | |
|             if (Ext2IsRemovable(volume) || (volume->DrvLetters != 0) || g_bAutoMount) {
 | |
|                 if (!Ext2CheckVolumeRegistryProperty(&volume->EVP)) {
 | |
|                     Ext2SetDefaultVolumeRegistryProperty(&volume->EVP);
 | |
|                 }
 | |
|                 Ext2NotifyVolumePoint(volume, 0);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         volume = volume->Next;
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Must initialize driver letter before loading volumes
 | |
|  */
 | |
| 
 | |
| BOOL
 | |
| Ext2LoadVolumes()
 | |
| {
 | |
|     ULONG   rc = TRUE;
 | |
| 
 | |
|     TCHAR  *nameString = NULL;
 | |
|     ULONG   nameLen = REGSTR_VAL_MAX_HCID_LEN;
 | |
| 
 | |
|     HMACHINE hMachine = NULL;
 | |
|     DEVNODE  dnRoot, dnFirst;
 | |
| 
 | |
|     DEVINSTID  devIds[] = {
 | |
|             "ROOT\\FTDISK\\0000",
 | |
|             "ROOT\\DMIO\\0000",
 | |
|             NULL,
 | |
|             "ROOT\\VOLMGR\\0000",
 | |
|             NULL
 | |
|             };
 | |
| 
 | |
|     int i = 0;
 | |
| 
 | |
|     if (IsVistaOrAbove()) {
 | |
|         i = 3;
 | |
|     }
 | |
| 
 | |
|     nameString = new TCHAR [nameLen];
 | |
|     if (nameString == NULL) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     while (devIds[i] != NULL) {
 | |
| 
 | |
| 	    rc = CM_Locate_DevNode_Ex(&dnRoot, devIds[i], 
 | |
|                 CM_LOCATE_DEVNODE_NORMAL , hMachine);
 | |
|         if (rc != CR_SUCCESS) {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         rc = CM_Get_Child_Ex(&dnFirst, dnRoot, 0, hMachine);
 | |
|         if (rc != CR_SUCCESS) {
 | |
|             goto errorout;
 | |
|         }
 | |
| 
 | |
|         while (TRUE) {
 | |
| 
 | |
|             PEXT2_VOLUME volume = NULL;
 | |
| 
 | |
|             nameLen = REGSTR_VAL_MAX_HCID_LEN;
 | |
|             memset(nameString, 0, nameLen);
 | |
|             rc = CM_Get_DevNode_Registry_Property_Ex(
 | |
|                         dnFirst, CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,
 | |
|                         NULL, nameString, &nameLen, 0, hMachine);
 | |
|             if (rc != CR_SUCCESS) {
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if (Ext2InitializeVolume(nameString, &volume)) {
 | |
| 
 | |
|                  volume->bDynamic = 0;
 | |
| 
 | |
|                 /* attach the volume to global list */
 | |
|                 if (gVols) {
 | |
|                     PEXT2_VOLUME chain = gVols;
 | |
|                     while (chain->Next) {
 | |
|                         chain = chain->Next;
 | |
|                     }
 | |
|                     chain->Next = volume;
 | |
|                 } else {
 | |
|                     gVols = volume;
 | |
|                 }
 | |
|                 g_nVols++;
 | |
|             }
 | |
|             
 | |
|             rc = CM_Get_Sibling_Ex(&dnFirst, dnFirst, 0, hMachine);
 | |
|             if (rc != CR_SUCCESS) {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         i++;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (nameString) {
 | |
|         delete []nameString;
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2LoadRemovableVolumes()
 | |
| {
 | |
|     BOOL                     rc = FALSE;
 | |
|     HDEVINFO                    devInfo = INVALID_HANDLE_VALUE;
 | |
|     PSP_DEVICE_INTERFACE_DETAIL_DATA ifDetail = NULL;
 | |
|     SP_DEVICE_INTERFACE_DATA    ifData;
 | |
| 
 | |
|     PCHAR                       nameString;
 | |
|     int                         nInterface = 0;
 | |
| 
 | |
|     if (IsVistaOrAbove()) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     nameString = (PCHAR)malloc(REGSTR_VAL_MAX_HCID_LEN);
 | |
|     if (nameString == NULL) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     ifDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(PAGE_SIZE);
 | |
|     if (ifDetail == NULL) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     devInfo = SetupDiGetClassDevs(
 | |
|                     &VolumeClassGuid, NULL, NULL,
 | |
|                     DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
 | |
|                     );
 | |
|     if (devInfo == INVALID_HANDLE_VALUE) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| 	while (TRUE) {
 | |
| 
 | |
|         BOOL bFound = FALSE;
 | |
| 
 | |
| 		ifData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 | |
|         bFound = SetupDiEnumDeviceInterfaces(
 | |
| 				        devInfo,
 | |
| 				        NULL,
 | |
| 				        &VolumeClassGuid,
 | |
| 				        (ULONG)nInterface++,
 | |
| 				        &ifData);
 | |
|         if (!bFound) {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         memset(ifDetail, 0, PAGE_SIZE);
 | |
|         ifDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
 | |
|         if (SetupDiGetInterfaceDeviceDetail(
 | |
| 					     devInfo,
 | |
| 					     &ifData,
 | |
| 					     ifDetail,
 | |
| 					     PAGE_SIZE,
 | |
| 					     NULL,
 | |
| 					     NULL)) {
 | |
| 
 | |
|             PEXT2_VOLUME volume = NULL;
 | |
| 
 | |
|             memset(nameString, 0, REGSTR_VAL_MAX_HCID_LEN);
 | |
|             QueryDosDevice(&ifDetail->DevicePath[4], nameString, REGSTR_VAL_MAX_HCID_LEN);
 | |
| 
 | |
|             if (Ext2InitializeVolume(nameString, &volume)) {
 | |
| 
 | |
|                 if (volume->FsdInfo.Characteristics & FILE_REMOVABLE_MEDIA) {
 | |
| 
 | |
|                     /* attach the volume to global list */
 | |
|                     if (gVols) {
 | |
|                         PEXT2_VOLUME chain = gVols;
 | |
|                         while (chain->Next) {
 | |
|                             chain = chain->Next;
 | |
|                         }
 | |
|                         chain->Next = volume;
 | |
|                     } else {
 | |
|                         gVols = volume;
 | |
|                     }
 | |
|                     g_nVols++;
 | |
|                 } else {
 | |
|                     if (volume->Extent) {
 | |
|                         free(volume->Extent);
 | |
|                     }
 | |
|                     free(volume);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     rc = TRUE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (nameString) {
 | |
|         free(nameString);
 | |
|     }
 | |
| 
 | |
|     if (ifDetail) {
 | |
|         free(ifDetail);
 | |
|     }
 | |
| 
 | |
|     if (devInfo != INVALID_HANDLE_VALUE) {
 | |
|         SetupDiDestroyDeviceInfoList(devInfo);
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2LoadAllVolumeDrvLetters()
 | |
| {
 | |
|     PEXT2_VOLUME volume = gVols;
 | |
|     BOOL      started = Ext2IsServiceStarted();
 | |
| 
 | |
|     // Ext2DrvLetters[0] = Ext2DrvLetters[1];
 | |
|     // Ext2DrvLetters[1] = 0;
 | |
| 
 | |
|     while (volume) {
 | |
|         volume->DrvLetters = Ext2QueryVolumeDrvLetters(volume);
 | |
|         if ( started && volume->bRecognized &&
 | |
|             (volume->EVP.bExt2 || volume->EVP.bExt3)) {
 | |
|             Ext2DrvLetters[1] |=  volume->DrvLetters;
 | |
|         }
 | |
|         volume = volume->Next;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| CString
 | |
| Ext2QueryVolumeLetterStrings(
 | |
|     ULONGLONG       letters,
 | |
|     PEXT2_LETTER *  first
 | |
|     )
 | |
| {
 | |
|     CHAR        drvName[] = "C:\0";
 | |
|     CString     str;
 | |
|     int         i = 0;
 | |
|     BOOL     bInserted = FALSE;
 | |
|     ULONGLONG   drive = 0;
 | |
| 
 | |
|     str.Empty();
 | |
| 
 | |
|     for (i=0; i < 10; i++) {
 | |
|         drive = ((ULONGLONG) 1) << (i + 32);
 | |
|         if (letters & drive) {
 | |
|             if (bInserted) {
 | |
|                 str += ",";
 | |
|             } else {
 | |
|                 str = "(";
 | |
|                 if (first) {
 | |
|                     *first = &drvDigits[i];
 | |
|                 }
 | |
|             }
 | |
|             drvName[0] = '0' + i;
 | |
|             str += drvName;
 | |
|             bInserted = TRUE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i=0; i < 26; i++) {
 | |
|         drive = ((ULONGLONG) 1) << (i);
 | |
|         if (letters & drive) {
 | |
|             if (bInserted) {
 | |
|                 str += ",";
 | |
|             } else {
 | |
|                 str = "(";
 | |
|                 if (first) {
 | |
|                     *first = &drvLetters[i];
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             drvName[0] = 'A' + i;
 | |
|             str += drvName;
 | |
|             bInserted = TRUE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (bInserted) {
 | |
|         str += ")";
 | |
|     }
 | |
| 
 | |
|     return str;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshVLVI(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_VOLUME chain,
 | |
|     int  nItem
 | |
|     )
 | |
| {
 | |
|     ULONGLONG   totalSize, usedSize;
 | |
|     CString     sSize, sUnit, s;
 | |
| 
 | |
|     PEXT2_LETTER  first = NULL;
 | |
|     CString  Letters = Ext2QueryVolumeLetterStrings(
 | |
|                            chain->DrvLetters, &first);
 | |
| 
 | |
|     List->SetItem( nItem, 1, LVIF_TEXT, (LPCSTR)Letters, 0, 0, 0,0);
 | |
|     
 | |
|     if (chain->bDynamic) {
 | |
|         s.LoadString(IDS_DISK_TYPE_DYN);
 | |
|     } else {
 | |
|         s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|     }
 | |
|     List->SetItem(nItem, 2, LVIF_TEXT, (LPCSTR)s, 0, 0, 0,0);
 | |
|     List->SetItem(nItem, 3, LVIF_TEXT, (LPCSTR)chain->FileSystem, 0, 0, 0,0);
 | |
| 
 | |
|     totalSize = chain->FssInfo.TotalAllocationUnits.QuadPart;
 | |
|     usedSize  = totalSize - chain->FssInfo.AvailableAllocationUnits.QuadPart;
 | |
|     totalSize = totalSize * chain->FssInfo.BytesPerSector *
 | |
|                 chain->FssInfo.SectorsPerAllocationUnit;
 | |
|     usedSize  = usedSize * chain->FssInfo.BytesPerSector *
 | |
|                 chain->FssInfo.SectorsPerAllocationUnit;
 | |
| 
 | |
|     if (totalSize > (ULONGLONG) 10 * 1024 * 1024 * 1024) {
 | |
|         totalSize = totalSize / ((ULONG)1024 * 1024 * 1024);
 | |
|         usedSize  = usedSize / ((ULONG)1024 * 1024 * 1024);
 | |
|         sUnit = " GB";
 | |
|     } else if (totalSize > 10 * 1024 * 1024){
 | |
|         totalSize = totalSize / (1024 * 1024);
 | |
|         usedSize  = usedSize / (1024 * 1024);
 | |
|         sUnit = " MB";
 | |
|     } else if (totalSize > 10 * 1024){
 | |
|         totalSize = totalSize / (1024);
 | |
|         usedSize  = usedSize / (1024);
 | |
|         sUnit = " KB";
 | |
|     } else {
 | |
|         sUnit = " B";
 | |
|     }
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 4, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     if (chain->bRecognized) {
 | |
|         sSize.Format("%I64u", usedSize);
 | |
|         sSize += sUnit;
 | |
|     }
 | |
|     List->SetItem(nItem, 5, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     List->SetItem(nItem, 6, LVIF_TEXT, (LPCSTR)chain->EVP.Codepage, 0, 0, 0,0);
 | |
|     List->SetItem(nItem, 7, LVIF_TEXT, (LPCSTR)chain->Name, 0, 0, 0,0);
 | |
| 
 | |
| /*
 | |
|         List->SetItemState( nItem, LVIS_SELECTED | LVIS_FOCUSED ,
 | |
|                                    LVIS_SELECTED | LVIS_FOCUSED);
 | |
| */
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| Ext2InsertVolume(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_VOLUME chain
 | |
|     )
 | |
| {
 | |
|     int nItem = 0, nImage = 0;
 | |
| 
 | |
|     nItem = List->GetItemCount();
 | |
|     nImage = 0;
 | |
| 
 | |
|     if (chain->FsdInfo.Characteristics & FILE_VIRTUAL_VOLUME) {
 | |
|         nImage = IDI_DYNAMIC - IDI_FLOPPY;
 | |
|     } else if (chain->FsdInfo.Characteristics & FILE_REMOVABLE_MEDIA) {
 | |
|         nImage = IDI_FLOPPY - IDI_FLOPPY;
 | |
|     } else {
 | |
|         nImage = IDI_DISK - IDI_FLOPPY;
 | |
|     }
 | |
| 
 | |
|     nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                              0, 0, nImage, (LPARAM)chain);
 | |
| 
 | |
|     Ext2RefreshVLVI(List, chain, nItem);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshVLCD(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_CDROM Cdrom,
 | |
|     int nItem
 | |
|     )
 | |
| {
 | |
|     ULONGLONG   totalSize;
 | |
|     CString     sSize, sUnit, s;
 | |
| 
 | |
|     PEXT2_LETTER  first = NULL;
 | |
| 
 | |
|     CString  Letters = Ext2QueryVolumeLetterStrings(
 | |
|                             Cdrom->DrvLetters, &first);
 | |
| 
 | |
|     List->SetItem( nItem, 1, LVIF_TEXT, (LPCSTR)Letters, 0, 0, 0,0);
 | |
| 
 | |
|     s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|     List->SetItem(nItem, 2, LVIF_TEXT, (LPCSTR)s, 0, 0, 0,0);
 | |
|     List->SetItem(nItem, 3, LVIF_TEXT, (LPCSTR)"CDFS", 0, 0, 0,0);
 | |
| 
 | |
| 
 | |
|     totalSize = (ULONGLONG)Cdrom->DiskGeometry.Cylinders.QuadPart;
 | |
|     totalSize = totalSize * Cdrom->DiskGeometry.TracksPerCylinder *
 | |
|                 Cdrom->DiskGeometry.SectorsPerTrack * 
 | |
|                 Cdrom->DiskGeometry.BytesPerSector;
 | |
| 
 | |
|     if (totalSize > 1024 * 1024 * 1024) {
 | |
|         totalSize = totalSize / (1024 * 1024 * 1024);
 | |
|         sUnit = " GB";
 | |
|     } else if (totalSize > 1024 * 1024){
 | |
|         totalSize = totalSize / (1024 * 1024);
 | |
|         sUnit = " MB";
 | |
|     } else if (totalSize > 1024){
 | |
|         totalSize = totalSize / (1024);
 | |
|         sUnit = " KB";
 | |
|     } else {
 | |
|         sUnit = " B";
 | |
|     }
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 4, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 5, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     List->SetItem(nItem, 8, LVIF_TEXT, (LPCSTR)Cdrom->Name, 0, 0, 0,0);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2InsertCdromAsVolume(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_CDROM Cdrom
 | |
|     )
 | |
| {
 | |
|     int nItem = 0, nImage = 0;
 | |
| 
 | |
|     nItem = List->GetItemCount();
 | |
|     nImage = 0;
 | |
| 
 | |
|     if (Cdrom->bIsDVD) {
 | |
|         nImage = IDI_DVD - IDI_FLOPPY;
 | |
|     } else {
 | |
|         nImage = IDI_CDROM - IDI_FLOPPY;
 | |
|     }
 | |
| 
 | |
|     nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                              0, 0, nImage, (LPARAM)Cdrom);
 | |
| 
 | |
|     Ext2RefreshVLCD(List, Cdrom, nItem);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshVolumeList(CListCtrl *List)
 | |
| {
 | |
|     List->DeleteAllItems();
 | |
|     PEXT2_VOLUME  chain = gVols;
 | |
| 
 | |
|     /* adding disk volumes */
 | |
|     while (chain) {
 | |
|         Ext2InsertVolume(List, chain);
 | |
|         chain = chain->Next;
 | |
|     }
 | |
| 
 | |
|     /* adding cdroms */
 | |
| 
 | |
|     ULONG   i = 0;
 | |
| 
 | |
|     for (i=0; i < g_nCdroms; i++) {
 | |
| 
 | |
|         if (!gCdroms[i].bLoaded || gCdroms[i].bEjected) {
 | |
|             continue;
 | |
|         }
 | |
|         Ext2InsertCdromAsVolume(List, &gCdroms[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshDVPT(
 | |
|     CListCtrl*      List,
 | |
|     PEXT2_PARTITION Part,
 | |
|     int             nItem
 | |
|     )
 | |
| {
 | |
| 
 | |
|     ULONGLONG   totalSize, usedSize;
 | |
|     CString     sSize, sUnit, s;
 | |
| 
 | |
|     PEXT2_LETTER  first = NULL;
 | |
|     PEXT2_VOLUME    chain = NULL;
 | |
| 
 | |
|     CString  Letters = Ext2QueryVolumeLetterStrings(
 | |
|                             Part->DrvLetters, &first);
 | |
| 
 | |
|     List->SetItem( nItem, 0, LVIF_TEXT, (LPCSTR)Letters, 0, 0, 0,0);
 | |
| 
 | |
|     if (Part->Entry) {
 | |
|         CString PartType;
 | |
|         if (Part->Entry->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
|             PartType = PartitionString(Part->Entry->Mbr.PartitionType);
 | |
|         } else if (Part->Entry->PartitionStyle == PARTITION_STYLE_GPT) {
 | |
|             PartType = "";
 | |
|             if (Part->Entry->Gpt.Name && wcslen(Part->Entry->Gpt.Name)) {
 | |
|                 for (size_t i = 0; i < wcslen(Part->Entry->Gpt.Name); i++)
 | |
|                     PartType += (CHAR)Part->Entry->Gpt.Name[i];
 | |
| 
 | |
|             } else {
 | |
|                 PartType = "GPT";
 | |
|             }
 | |
|         } else {
 | |
|             PartType = "RAW";
 | |
|         }
 | |
|         
 | |
|         List->SetItem(nItem, 6, LVIF_TEXT, (LPCSTR)
 | |
|                       PartType, 0, 0, 0,0);
 | |
|     }
 | |
| 
 | |
|     /* query the volume information of the partition */
 | |
|     chain = Part->Volume;
 | |
|     if (!chain) {
 | |
|         PEXT2_DISK  disk = Part->Disk;
 | |
|         CString s;
 | |
|         if (disk->SDD.RemovableMedia) {
 | |
|             s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|         } else if (disk->bLoaded){
 | |
|             if (disk->Layout) {
 | |
|                 if (disk->Layout->PartitionStyle == PARTITION_STYLE_MBR) {
 | |
|                     if (disk->Layout->PartitionEntry->Mbr.PartitionType
 | |
|                         == PARTITION_LDM) {
 | |
|                         s.LoadString(IDS_DISK_TYPE_DYN);
 | |
|                     } else {
 | |
|                         s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|                     }
 | |
|                 } else if (disk->Layout->PartitionStyle == PARTITION_STYLE_GPT) {
 | |
|                      s = "GPT";
 | |
|                 }
 | |
|             } else {
 | |
|                 s = "RAW";
 | |
|             }
 | |
|         } else {
 | |
|             s = "Stopped";
 | |
|         }
 | |
| 
 | |
|         List->SetItem(nItem, 1, LVIF_TEXT, (LPCSTR)s, 0, 0, 0,0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (chain->bDynamic) {
 | |
|         s.LoadString(IDS_DISK_TYPE_DYN);
 | |
|     } else {
 | |
|         s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|     }
 | |
|     List->SetItem(nItem, 1, LVIF_TEXT, (LPCSTR)s, 0, 0, 0,0);
 | |
| 
 | |
|     List->SetItem(nItem, 2, LVIF_TEXT, (LPCSTR)chain->FileSystem, 0, 0, 0,0);
 | |
| 
 | |
|     totalSize = chain->FssInfo.TotalAllocationUnits.QuadPart;
 | |
|     usedSize  = totalSize - chain->FssInfo.AvailableAllocationUnits.QuadPart;
 | |
|     totalSize = totalSize * chain->FssInfo.BytesPerSector *
 | |
|                 chain->FssInfo.SectorsPerAllocationUnit;
 | |
|     usedSize  = usedSize * chain->FssInfo.BytesPerSector *
 | |
|                 chain->FssInfo.SectorsPerAllocationUnit;
 | |
| 
 | |
|     if (totalSize > (ULONGLONG) 10 * 1024 * 1024 * 1024) {
 | |
|         totalSize = totalSize / ((ULONG)1024 * 1024 * 1024);
 | |
|         usedSize  = usedSize / ((ULONG)1024 * 1024 * 1024);
 | |
|         sUnit = " GB";
 | |
|     } else if (totalSize > 10 * 1024 * 1024){
 | |
|         totalSize = totalSize / (1024 * 1024);
 | |
|         usedSize  = usedSize / (1024 * 1024);
 | |
|         sUnit = " MB";
 | |
|     } else if (totalSize > 10 * 1024){
 | |
|         totalSize = totalSize / (1024);
 | |
|         usedSize  = usedSize / (1024);
 | |
|         sUnit = " KB";
 | |
|     } else {
 | |
|         sUnit = " B";
 | |
|     }
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 3, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     if (chain->bRecognized) {
 | |
|         sSize.Format("%I64u", usedSize);
 | |
|         sSize += sUnit;
 | |
|     }
 | |
|     List->SetItem(nItem, 4, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     List->SetItem(nItem, 5, LVIF_TEXT, (LPCSTR)chain->EVP.Codepage, 0, 0, 0,0);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2InsertPartition(
 | |
|     CListCtrl*      List,
 | |
|     PEXT2_DISK      Disk,
 | |
|     PEXT2_PARTITION Part
 | |
|     )
 | |
| {
 | |
|     int nItem = 0, nImage = 0;
 | |
| 
 | |
|     nItem = List->GetItemCount();
 | |
|     nImage = 0;
 | |
| 
 | |
|     if (!Disk) {
 | |
|         nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                                  0, 0, nImage, (LPARAM)NULL);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (!Part) {
 | |
|         nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                                  0, 0, nImage, (LPARAM)&Disk->Null);
 | |
|         List->SetItem( nItem, 1, LVIF_TEXT, (LPCSTR)"RAW", 0, 0, 0,0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     nItem = List->InsertItem( LVIF_PARAM| LVIF_IMAGE, nItem, NULL,
 | |
|                                0, 0, nImage, (LPARAM)Part);
 | |
| 
 | |
|     Ext2RefreshDVPT(List, Part, nItem);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2InsertDisk(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_DISK Disk
 | |
|     )
 | |
| {
 | |
|     UCHAR   i;
 | |
|     CHAR  devName[64];
 | |
|     int nItem = 0, nImage = 0;
 | |
| 
 | |
|     sprintf(devName, "DISK %d", Disk->OrderNo);
 | |
|     nItem = List->GetItemCount();
 | |
|     nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                              0, 0, nImage, (LPARAM)Disk);
 | |
|     List->SetItem( nItem, 0, LVIF_TEXT, (LPCSTR)devName, 0, 0, 0,0);
 | |
| 
 | |
|     if (Disk->NumParts > 0) {
 | |
|         for (i=0; i < Disk->NumParts; i++) {
 | |
|             Ext2InsertPartition(List, Disk, &Disk->DataParts[i]);
 | |
|         }
 | |
|     } else {
 | |
|         Ext2InsertPartition(List, Disk, NULL);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshDVCM(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_CDROM Cdrom,
 | |
|     int nItem
 | |
|     )
 | |
| {
 | |
|     ULONGLONG   totalSize;
 | |
|     CString     sSize, sUnit, s;
 | |
| 
 | |
|     PEXT2_LETTER  first = NULL;
 | |
| 
 | |
|     CString  Letters = Ext2QueryVolumeLetterStrings(
 | |
|                             Cdrom->DrvLetters, &first);
 | |
| 
 | |
|     if (!Cdrom->bLoaded) {
 | |
|         List->SetItem( nItem, 1, LVIF_TEXT, (LPCSTR)"Stopped", 0, 0, 0,0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     List->SetItem( nItem, 0, LVIF_TEXT, (LPCSTR)Letters, 0, 0, 0,0);
 | |
| 
 | |
|     if (Cdrom->bEjected) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     s.LoadString(IDS_DISK_TYPE_BASIC);
 | |
|     List->SetItem(nItem, 1, LVIF_TEXT, (LPCSTR)s, 0, 0, 0,0);
 | |
|     List->SetItem(nItem, 2, LVIF_TEXT, (LPCSTR)"CDFS", 0, 0, 0,0);
 | |
| 
 | |
|     totalSize = (ULONGLONG)Cdrom->DiskGeometry.Cylinders.QuadPart;
 | |
|     totalSize = totalSize * Cdrom->DiskGeometry.TracksPerCylinder *
 | |
|                 Cdrom->DiskGeometry.SectorsPerTrack * 
 | |
|                 Cdrom->DiskGeometry.BytesPerSector;
 | |
| 
 | |
|     if (totalSize > 1024 * 1024 * 1024) {
 | |
|         totalSize = totalSize / (1024 * 1024 * 1024);
 | |
|         sUnit = " GB";
 | |
|     } else if (totalSize > 1024 * 1024){
 | |
|         totalSize = totalSize / (1024 * 1024);
 | |
|         sUnit = " MB";
 | |
|     } else if (totalSize > 1024){
 | |
|         totalSize = totalSize / (1024);
 | |
|         sUnit = " KB";
 | |
|     } else {
 | |
|         sUnit = " B";
 | |
|     }
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 3, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     sSize.Format("%I64u", totalSize);
 | |
|     sSize += sUnit;
 | |
|     List->SetItem(nItem, 4, LVIF_TEXT, (LPCSTR)sSize, 0, 0, 0,0);
 | |
| 
 | |
|     List->SetItem(nItem, 5, LVIF_TEXT, (LPCSTR)"", 0, 0, 0,0);
 | |
|     List->SetItem(nItem, 6, LVIF_TEXT, (LPCSTR)"", 0, 0, 0,0);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2InsertCdromAsDisk(
 | |
|     CListCtrl *List,
 | |
|     PEXT2_CDROM Cdrom
 | |
|     )
 | |
| {
 | |
|     CHAR  devName[64];
 | |
|     int nItem = 0, nImage = 0;
 | |
| 
 | |
|     sprintf(devName, "CDROM %d", Cdrom->OrderNo);
 | |
|     nItem = List->GetItemCount();
 | |
|     nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                              0, 0, nImage, (LPARAM)Cdrom);
 | |
|     List->SetItem( nItem, 0, LVIF_TEXT, (LPCSTR)devName, 0, 0, 0,0);
 | |
| 
 | |
|     nItem = List->GetItemCount();
 | |
|     nImage = 0;
 | |
| 
 | |
|     if (Cdrom->bIsDVD) {
 | |
|         nImage = IDI_DVD - IDI_FLOPPY;
 | |
|     } else {
 | |
|         nImage = IDI_CDROM - IDI_FLOPPY;
 | |
|     }
 | |
| 
 | |
|     nItem = List->InsertItem( LVIF_PARAM|LVIF_IMAGE, nItem, NULL,
 | |
|                              0, 0, nImage, (LPARAM)(&Cdrom->Magic[1]));
 | |
| 
 | |
|     Ext2RefreshDVCM(List, Cdrom, nItem);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RefreshDiskList(CListCtrl *List)
 | |
| {
 | |
|     List->DeleteAllItems();
 | |
|     ULONG   i = 0;
 | |
| 
 | |
|     /* adding disks */
 | |
|     for (i=0; i < g_nDisks; i++) {
 | |
|         Ext2InsertDisk(List, &gDisks[i]);
 | |
|         Ext2InsertPartition(List, NULL, NULL);
 | |
|     }
 | |
| 
 | |
|     /* adding cdroms */
 | |
|     for (i=0; i < g_nCdroms; i++) {
 | |
|         Ext2InsertCdromAsDisk(List, &gCdroms[i]);
 | |
|         Ext2InsertPartition(List, NULL, NULL);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| VOID
 | |
| Ext2CleanupVolumes()
 | |
| {
 | |
|     PEXT2_VOLUME  chain = gVols, next = NULL;
 | |
| 
 | |
|     while (chain) {
 | |
|         next = chain->Next;
 | |
|         if (chain->Extent) {
 | |
|             free(chain->Extent);
 | |
|         }
 | |
|         free(chain);
 | |
|         g_nVols--;
 | |
|         chain = next;
 | |
|     }
 | |
| 
 | |
|     ASSERT(g_nVols == 0);
 | |
|     g_nVols = 0; gVols = NULL;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2LoadDrvLetter(PEXT2_LETTER drvLetter, CHAR cLetter)
 | |
| {
 | |
|     if (drvLetter->bUsed) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (cLetter >= 'a' && cLetter <= 'z') {
 | |
|         cLetter -= 0x20;
 | |
|     }
 | |
| 
 | |
|     memset(drvLetter, 0, sizeof(EXT2_LETTER));
 | |
|     drvLetter->Letter = cLetter;
 | |
|     Ext2QueryDrvLetter(drvLetter);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2LoadDrvLetters()
 | |
| {
 | |
|     int     i;
 | |
| 
 | |
|     for (i=0; i < 36; i++) {
 | |
| 
 | |
|         PEXT2_LETTER    drvLetter = NULL;
 | |
|         CHAR            cLetter = 0;
 | |
| 
 | |
|         if (i < 10) {
 | |
|             drvLetter = &drvDigits[i];
 | |
|             cLetter = '0' + i;
 | |
|         } else {
 | |
|             drvLetter = &drvLetters[i-10];
 | |
|             cLetter = 'A' + (i - 10);
 | |
|         }
 | |
| 
 | |
|         Ext2LoadDrvLetter(drvLetter, cLetter);
 | |
|     }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2CleanDrvLetter(PEXT2_LETTER drvLetter)
 | |
| {
 | |
|     if (drvLetter->Extent) {
 | |
|         free(drvLetter->Extent);
 | |
|         drvLetter->Extent = NULL;
 | |
|     }
 | |
| 
 | |
|     if (drvLetter->SDN) {
 | |
|         free(drvLetter->SDN);
 | |
|         drvLetter->SDN = NULL;
 | |
|     }
 | |
| 
 | |
|     drvLetter->bUsed = FALSE;
 | |
|     drvLetter->bTemporary = FALSE;
 | |
|     drvLetter->DrvType = DRIVE_NO_ROOT_DIR;
 | |
|     memset(drvLetter->SymLink, 0, MAX_PATH);
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2CleanupDrvLetters()
 | |
| {
 | |
|     int i = 0;
 | |
| 
 | |
|     for (i=0; i < 10; i++) {
 | |
|         Ext2CleanDrvLetter(&drvDigits[i]);
 | |
|     }
 | |
| 
 | |
|     for (i=0; i < 26; i++) {
 | |
|         Ext2CleanDrvLetter(&drvLetters[i]);
 | |
|     }
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2DrvNotify(UCHAR drive, int mount)
 | |
| {
 | |
|     DEV_BROADCAST_VOLUME    dbv;
 | |
|     DWORD target = BSM_APPLICATIONS;
 | |
|     unsigned long drv = 0;
 | |
| 
 | |
|     if (drive >= 'A' && drive <= 'Z')
 | |
|         drv = drive - 'A';
 | |
|     else if(drive >= 'a' && drive <= 'z')
 | |
|         drv = drive - 'a';
 | |
|     else
 | |
|         return;
 | |
| 
 | |
|     dbv.dbcv_size       = sizeof( dbv );
 | |
|     dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME;
 | |
|     dbv.dbcv_reserved   = 0;
 | |
|     dbv.dbcv_unitmask   = (1 << drv);
 | |
|     dbv.dbcv_flags      = DBTF_NET;
 | |
|     BroadcastSystemMessage(BSF_IGNORECURRENTTASK | BSF_FORCEIFHUNG |
 | |
|                            BSF_NOHANG | BSF_NOTIMEOUTIFNOTHUNG,
 | |
|                            &target, WM_DEVICECHANGE, mount ?
 | |
|                            DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE,
 | |
|                            (LPARAM)(DEV_BROADCAST_HDR *)&dbv );
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2RemoveDrvLetter(
 | |
|     PEXT2_LETTER   drvLetter
 | |
|     )
 | |
| {
 | |
|     CHAR drvPath[] = "A:\\\0";
 | |
|     CHAR dosPath[] = "A:\0";
 | |
| 
 | |
|     BOOL rc = FALSE;
 | |
| 
 | |
|     if (!drvLetter->bUsed) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     dosPath[0] = drvPath[0] = drvLetter->Letter;
 | |
|     rc = Ext2DefineDosDevice ( 
 | |
|                 DDD_RAW_TARGET_PATH|
 | |
|                 DDD_REMOVE_DEFINITION|
 | |
|                 DDD_EXACT_MATCH_ON_REMOVE,
 | |
|                 dosPath, drvLetter->SymLink);
 | |
|     DeleteVolumeMountPoint(drvPath);
 | |
| 
 | |
|     if (!rc) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| CHAR
 | |
| Ext2QueryRegistryMountPoint (
 | |
|     CHAR * devName
 | |
|     )
 | |
| {
 | |
|     DWORD    i = 0;
 | |
| 
 | |
|     LONG    status;
 | |
|     HKEY    hKey;
 | |
| 
 | |
|     DWORD   drvSize;
 | |
|     DWORD   dosSize;
 | |
|     DWORD   valType;
 | |
| 
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     CHAR    drvPath[MAX_PATH];
 | |
|     CHAR    dosPath[64];
 | |
| 
 | |
|     /* set dos deivce path */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\DOS Devices");
 | |
| 
 | |
|     /* open session manager\dos devices */
 | |
|     status = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /* enum all values and compare devName ... */
 | |
|     while (status != ERROR_NO_MORE_ITEMS && i < 1024) {
 | |
| 
 | |
|         valType = REG_SZ;
 | |
|         dosSize = 64;
 | |
|         drvSize = MAX_PATH;
 | |
| 
 | |
|         status = RegEnumValue(hKey, 
 | |
|                               i++,
 | |
|                               &dosPath[0],
 | |
|                               &dosSize,
 | |
|                               NULL,
 | |
|                               &valType,
 | |
|                               (LPBYTE)&drvPath[0],
 | |
|                               &drvSize);
 | |
| 
 | |
|         if (status == ERROR_SUCCESS) {
 | |
|             if (_stricmp(devName, drvPath) == 0) {
 | |
|                 RegCloseKey(hKey);
 | |
|                 return dosPath[0];
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetRegistryMountPoint (
 | |
|     CHAR * dosPath,
 | |
|     CHAR * devName,
 | |
|     BOOL bSet
 | |
|     )
 | |
| {
 | |
|     LONG    status;
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     CHAR    drvPath[MAX_PATH];
 | |
| 
 | |
|     /* set dos driver name */
 | |
|     sprintf(drvPath, "%c:", dosPath[0]);
 | |
| 
 | |
|     /* set dos deivce path */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\DOS Devices");
 | |
| 
 | |
|     /* open session manager\dos devices */
 | |
|     status = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (bSet) {
 | |
|         /* set value */
 | |
|         status = RegSetValueEx(
 | |
|                     hKey, drvPath,
 | |
|                     0, REG_SZ,
 | |
|                     (BYTE *)devName,
 | |
|                     strlen(devName)
 | |
|                     );
 | |
|     } else {
 | |
|         /* delete key */
 | |
|         status = RegDeleteValue(
 | |
|                     hKey, drvPath
 | |
|                     );
 | |
|     }
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2UpdateDrvLetter(
 | |
|     PEXT2_LETTER   drvLetter,
 | |
|     PCHAR          devPath
 | |
|     )
 | |
| {
 | |
|     CHAR dosPath[] = "A:\0";
 | |
|     BOOL rc = 0;
 | |
| 
 | |
|     if (drvLetter->bUsed) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     dosPath[0] = drvLetter->Letter;
 | |
|     rc = Ext2DefineDosDevice(DDD_RAW_TARGET_PATH,
 | |
|                          dosPath, devPath);
 | |
| 
 | |
|     if (rc) {
 | |
|         Ext2DefineDosDevice ( 
 | |
|                     DDD_RAW_TARGET_PATH|
 | |
|                     DDD_REMOVE_DEFINITION|
 | |
|                     DDD_EXACT_MATCH_ON_REMOVE,
 | |
|                     dosPath, devPath);
 | |
|     }
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2AssignDrvLetter(
 | |
|     PEXT2_LETTER   drvLetter,
 | |
|     PCHAR          devPath,
 | |
|     BOOL        bMountMgr
 | |
|     )
 | |
| {
 | |
|     CHAR dosPath[] = "A:\0";
 | |
|     CHAR drvPath[] = "A:\\\0";
 | |
|     CHAR volumeName[MAX_PATH];
 | |
| 
 | |
|     BOOL rc = 0;
 | |
| 
 | |
|     if (drvLetter->bUsed) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     memset(volumeName, 0, MAX_PATH);
 | |
|     dosPath[0] = drvPath[0] = drvLetter->Letter;
 | |
| 
 | |
|     rc = Ext2DefineDosDevice(DDD_RAW_TARGET_PATH,
 | |
|                          dosPath, devPath);
 | |
| 
 | |
|     if (rc) {
 | |
| 
 | |
|         /* Now it's done, since user only
 | |
|            needs a temporary mount point */
 | |
|         if (!bMountMgr) {
 | |
|             goto DrvMounted;
 | |
|         }
 | |
| 
 | |
|         rc = GetVolumeNameForVolumeMountPoint (
 | |
|                     drvPath, volumeName, MAX_PATH);
 | |
| 
 | |
|         Ext2DefineDosDevice ( 
 | |
|                     DDD_RAW_TARGET_PATH|
 | |
|                     DDD_REMOVE_DEFINITION|
 | |
|                     DDD_EXACT_MATCH_ON_REMOVE,
 | |
|                     dosPath, devPath);
 | |
| 
 | |
|         if (rc) {
 | |
|             rc = SetVolumeMountPoint(drvPath, volumeName); 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
| DrvMounted:
 | |
| 
 | |
|     drvLetter->bTemporary = !bMountMgr;
 | |
|     Ext2QueryDrvLetter(drvLetter);
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *  Mount Manager Support Routines
 | |
|  */
 | |
| 
 | |
| VOID
 | |
| Ext2AnsiToUnicode(
 | |
|     CHAR *      AnsiName,
 | |
|     WCHAR*      UniName,
 | |
|     USHORT      UniLength
 | |
|     )
 | |
| {
 | |
|     USHORT                  NameLength = 0;
 | |
|     NT::ANSI_STRING         AnsiFilespec;
 | |
|     NT::UNICODE_STRING      UnicodeFilespec;
 | |
| 
 | |
|     memset(UniName, 0, sizeof(WCHAR) * UniLength);
 | |
| 
 | |
|     NameLength = strlen(AnsiName);
 | |
|     ASSERT(NameLength < UniLength);
 | |
| 
 | |
|     AnsiFilespec.MaximumLength = AnsiFilespec.Length = NameLength;
 | |
|     AnsiFilespec.Buffer = AnsiName;
 | |
| 
 | |
|     UnicodeFilespec.MaximumLength = UniLength * 2;
 | |
|     UnicodeFilespec.Length = 0;
 | |
|     UnicodeFilespec.Buffer = (PWSTR)UniName;
 | |
| 
 | |
|     NT::RtlAnsiStringToUnicodeString(&UnicodeFilespec, &AnsiFilespec, FALSE);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2VolumeArrivalNotify(PCHAR  VolumePath)
 | |
| {
 | |
|     HANDLE              hMountMgr = NULL;
 | |
| 
 | |
|     NT::IO_STATUS_BLOCK iosb;
 | |
|     NT::NTSTATUS        status;
 | |
|     DWORD               rc = 0; 
 | |
| 
 | |
|     WCHAR      volPath[MAX_PATH + 2];
 | |
|     PMOUNTMGR_TARGET_NAME target;
 | |
| 
 | |
|     target = (PMOUNTMGR_TARGET_NAME) volPath;
 | |
|     Ext2AnsiToUnicode(VolumePath, &target->DeviceName[0], MAX_PATH);
 | |
|     target->DeviceNameLength = (USHORT)wcslen(target->DeviceName) * 2;
 | |
| 
 | |
|     status = Ext2Open("\\Device\\MountPointManager", &hMountMgr, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hMountMgr, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
 | |
|                 (PVOID)target, sizeof(USHORT) +
 | |
|                 target->DeviceNameLength, NULL, 0
 | |
|                 );
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&hMountMgr);
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2SymLinkRemoval(CHAR drvLetter)
 | |
| {
 | |
|     HANDLE              hMountMgr = NULL;
 | |
| 
 | |
|     NT::IO_STATUS_BLOCK iosb;
 | |
|     NT::NTSTATUS        status;
 | |
|     DWORD               rc = 0; 
 | |
| 
 | |
|     WCHAR buffer[MAX_PATH], *dosName;
 | |
|     PMOUNTMGR_MOUNT_POINT  pmp = NULL;
 | |
|     PMOUNTMGR_MOUNT_POINTS pms = NULL;
 | |
| 
 | |
|     memset(buffer, 0, sizeof(WCHAR) * MAX_PATH);
 | |
|     pmp = (PMOUNTMGR_MOUNT_POINT) buffer;
 | |
|     pmp->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
 | |
|     pmp->SymbolicLinkNameLength = 14 * sizeof(WCHAR);
 | |
| 
 | |
|     dosName = (WCHAR *) (pmp + 1);
 | |
|     swprintf_s(dosName, MAX_PATH - sizeof(MOUNTMGR_MOUNT_POINT),
 | |
|                L"\\DosDevices\\%c:\0", drvLetter);
 | |
| 
 | |
|     status = Ext2Open("\\Device\\MountPointManager", &hMountMgr, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hMountMgr, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_MOUNTMGR_DELETE_POINTS,
 | |
|                 (PVOID)pmp, sizeof(WCHAR) * MAX_PATH, 
 | |
|                 (PVOID)pmp, sizeof(WCHAR) * MAX_PATH
 | |
|                 );
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&hMountMgr);
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetVolumeMountPoint (
 | |
|     CHAR * dosPath,
 | |
|     CHAR * devName
 | |
|     )
 | |
| {
 | |
|     HANDLE              hMountMgr;
 | |
| 
 | |
|     NT::IO_STATUS_BLOCK iosb;
 | |
|     NT::NTSTATUS        status;
 | |
|     DWORD               rc = 0; 
 | |
| 
 | |
|     CHAR       dosDevice[MAX_PATH];
 | |
|     WCHAR      volPath[MAX_PATH];
 | |
|     WCHAR      devPath[MAX_PATH];
 | |
| 
 | |
|     PMOUNTMGR_CREATE_POINT_INPUT  mcpi = NULL;
 | |
| 
 | |
|     USHORT   lmcpi = 0, lvolp = 0, ldevp = 0;
 | |
| 
 | |
|     memset(dosDevice, 0, MAX_PATH);
 | |
|     memset(volPath, 0, MAX_PATH * sizeof(WCHAR));
 | |
|     memset(devPath, 0, MAX_PATH * sizeof(WCHAR));
 | |
| 
 | |
|     /* covert names to unicode */
 | |
|     sprintf(dosDevice, "\\DosDevices\\%c:", toupper(dosPath[0]));
 | |
|     Ext2AnsiToUnicode(dosDevice, volPath, MAX_PATH);
 | |
|     Ext2AnsiToUnicode(devName, devPath, MAX_PATH);
 | |
| 
 | |
|     ldevp = (USHORT)wcslen(devPath) * 2;
 | |
|     lvolp = (USHORT)wcslen(volPath) * 2;
 | |
|     lmcpi = sizeof(MOUNTMGR_CREATE_POINT_INPUT) + lvolp + ldevp;
 | |
| 
 | |
|     /* initialize MMGR_CREATE_MOUNT_POINT_INPUT */
 | |
|     mcpi = (PMOUNTMGR_CREATE_POINT_INPUT) malloc(lmcpi);
 | |
|     if (mcpi == NULL) {
 | |
|         status = STATUS_UNSUCCESSFUL;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     mcpi->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
 | |
|     mcpi->SymbolicLinkNameLength = lvolp;
 | |
|     mcpi->DeviceNameOffset = mcpi->SymbolicLinkNameOffset + lvolp;
 | |
|     mcpi->DeviceNameLength = ldevp;
 | |
| 
 | |
|     memcpy((PCHAR)mcpi + mcpi->SymbolicLinkNameOffset,
 | |
|            volPath, lvolp);
 | |
|     memcpy((PCHAR)mcpi + mcpi->DeviceNameOffset,
 | |
|            devPath, ldevp);
 | |
| 
 | |
|     /* open MountMgr */
 | |
|     status = Ext2Open("\\Device\\MountPointManager", &hMountMgr, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* ioctl .... */
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hMountMgr, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_MOUNTMGR_CREATE_POINT,
 | |
|                 (PVOID)mcpi, lmcpi, NULL, 0
 | |
|                 );
 | |
| 
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     Ext2Close(&hMountMgr);
 | |
| 
 | |
| errorout:
 | |
|     if (mcpi) {
 | |
|         free(mcpi);
 | |
|     }
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 | |
| 
 | |
| 
 | |
| UCHAR
 | |
| Ext2QueryMountPoint(
 | |
|     CHAR *      volume
 | |
|     )
 | |
| {
 | |
|     NT::IO_STATUS_BLOCK     iosb;
 | |
|     NT::NTSTATUS            status;
 | |
|     ULONG                   lp, lps;
 | |
|     ULONG                   i;
 | |
|     HANDLE                  hMountMgr = 0;
 | |
| 
 | |
|     NT::UNICODE_STRING      volPoint;
 | |
|     NT::UNICODE_STRING      VolumeName;
 | |
|     WCHAR                   VolumeBuffer[MAX_PATH];
 | |
| 
 | |
|     PMOUNTMGR_MOUNT_POINT   point = NULL;
 | |
|     PMOUNTMGR_MOUNT_POINTS  points = NULL;
 | |
|     UCHAR                   drvLetter = 0;
 | |
| 
 | |
|     memset(VolumeBuffer, 0, MAX_PATH * sizeof(WCHAR));
 | |
|     Ext2AnsiToUnicode(volume, VolumeBuffer, MAX_PATH);
 | |
| 
 | |
|     VolumeName.MaximumLength = MAX_PATH;
 | |
|     VolumeName.Length = (USHORT)wcslen(VolumeBuffer) * 2;
 | |
|     VolumeName.Buffer = VolumeBuffer;
 | |
| 
 | |
|     status = Ext2Open("\\Device\\MountPointManager", &hMountMgr, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     lp = VolumeName.Length + sizeof(MOUNTMGR_MOUNT_POINT) + 2;
 | |
|     point = (PMOUNTMGR_MOUNT_POINT)malloc(lp);
 | |
|     if (point == NULL) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* initialize MountMgr ioctl input structure */
 | |
|     memset(point, 0, lp);
 | |
|     point->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
 | |
|     point->DeviceNameLength = VolumeName.Length;
 | |
|     RtlMoveMemory((PCHAR) point + point->DeviceNameOffset,
 | |
|                   VolumeBuffer, VolumeName.Length);
 | |
|     lps = 1024;
 | |
| 
 | |
| Again:
 | |
| 
 | |
|     /* allocate ioctl output structure */
 | |
|     points = (PMOUNTMGR_MOUNT_POINTS)malloc(lps);
 | |
|     if (!points) {
 | |
|         goto errorout;
 | |
|     }
 | |
|     RtlZeroMemory(points, lps);
 | |
| 
 | |
|     /* could MoungMgr to create volume points for us ? */
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 hMountMgr, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_MOUNTMGR_QUERY_POINTS,
 | |
|                 point, lp, points, lps
 | |
|                 );
 | |
| 
 | |
|     if (status == STATUS_BUFFER_OVERFLOW) {
 | |
|         lps = (ULONG)iosb.Information + 2;
 | |
|         free(points);
 | |
|         points = NULL;
 | |
|         goto Again;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < points->NumberOfMountPoints; i++) {
 | |
| 
 | |
|         volPoint.Length = volPoint.MaximumLength =
 | |
|                 points->MountPoints[i].SymbolicLinkNameLength;
 | |
|         volPoint.Buffer = (PWSTR) ((PCHAR) points +
 | |
|                      points->MountPoints[i].SymbolicLinkNameOffset);
 | |
| 
 | |
| #if 0
 | |
|         if (MOUNTMGR_IS_VOLUME_NAME(&volPoint)) {
 | |
|             if (length) {
 | |
|                 if (*length >= volPoint.Length + 2) {
 | |
|                     *length = volPoint.Length + 2;
 | |
|                     memcpy(vp, volPoint.Buffer, volPoint.Length);
 | |
|                     vp[1] = (WCHAR)'\\';
 | |
|                     vp[volPoint.Length / 2] = (WCHAR)'\\';
 | |
|                     vp[*length / 2] = 0;
 | |
|                 } else {
 | |
|                     *length = 0;
 | |
|                 }
 | |
|             } 
 | |
|         }
 | |
| #endif
 | |
| 
 | |
|         if (MOUNTMGR_IS_DRIVE_LETTER(&volPoint)) {
 | |
|             drvLetter = (UCHAR)(volPoint.Buffer[12]);
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (points) {
 | |
|         free(points);
 | |
|     }
 | |
| 
 | |
|     if (point) {
 | |
|         free(point);
 | |
|     }
 | |
| 
 | |
|     if (hMountMgr) {
 | |
|         Ext2Close(&hMountMgr);
 | |
|     }
 | |
| 
 | |
|     return drvLetter;
 | |
| }
 | |
| 
 | |
| PEXT2_LETTER
 | |
| Ext2GetDrvLetterPoint(CHAR drvChar)
 | |
| {
 | |
|     PEXT2_LETTER    drvLetter = NULL;
 | |
| 
 | |
|     if (drvChar >= '0' && drvChar <= '9') {
 | |
|         drvLetter = &drvDigits[drvChar - '0'];
 | |
|     } else if (drvChar >= 'A' && drvChar <= 'Z') {
 | |
|         drvLetter = &drvLetters[drvChar - 'A'];
 | |
|     } else {
 | |
|         drvLetter = NULL;
 | |
|     }
 | |
| 
 | |
|     return drvLetter;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2InsertMountPoint(
 | |
|     CHAR * volume,
 | |
|     UCHAR drvChar,
 | |
|     BOOL  bGlobal
 | |
|     )
 | |
| {
 | |
|     CHAR volumeName[MAX_PATH];
 | |
| 
 | |
|     CHAR dosPath[] = "A:\0";
 | |
|     CHAR drvPath[] = "A:\\\0";
 | |
|     BOOL rc = FALSE;
 | |
| 
 | |
|     dosPath[0] = drvPath[0] = drvChar & 0x7F;
 | |
|     rc = Ext2DefineDosDevice(DDD_RAW_TARGET_PATH,
 | |
|                              dosPath, volume);
 | |
| 
 | |
|     if (rc && bGlobal) {
 | |
|         rc = GetVolumeNameForVolumeMountPoint (
 | |
|                     drvPath, volumeName, MAX_PATH);
 | |
| 
 | |
|         Ext2DefineDosDevice ( 
 | |
|                     DDD_RAW_TARGET_PATH|
 | |
|                     DDD_REMOVE_DEFINITION,
 | |
|                     dosPath, volume);
 | |
|         if (rc) {
 | |
|             rc = SetVolumeMountPoint(drvPath, volumeName); 
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2RemoveMountPoint(
 | |
|     PEXT2_LETTER    drvLetter,
 | |
|     BOOL         bPermanent
 | |
|     )
 | |
| {
 | |
|     CHAR drvPath[] = "A:\\\0";
 | |
|     CHAR dosPath[] = "A:\0";
 | |
| 
 | |
|     dosPath[0] = drvPath[0] = drvLetter->Letter;
 | |
| 
 | |
|     Ext2DefineDosDevice ( 
 | |
|             DDD_RAW_TARGET_PATH|
 | |
|             DDD_REMOVE_DEFINITION|
 | |
|             DDD_EXACT_MATCH_ON_REMOVE,
 | |
|             dosPath, drvLetter->SymLink);
 | |
|     if (bPermanent) {
 | |
|         DeleteVolumeMountPoint(drvPath);
 | |
|     }
 | |
| 
 | |
|     Ext2CleanDrvLetter(drvLetter);
 | |
|     Ext2QueryDrvLetter(drvLetter);
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2RefreshVolumePoint(
 | |
|     CHAR *          volume,
 | |
|     UCHAR           drvChar
 | |
|     )
 | |
| {
 | |
|     PEXT2_LETTER    drvLetter = NULL;
 | |
|     BOOL         rc = TRUE;
 | |
|     CHAR            cLetter = 0;
 | |
| 
 | |
|     cLetter = Ext2QueryMountPoint(volume);
 | |
|     if (cLetter) {
 | |
|         goto errorout;
 | |
|     } else {
 | |
|         rc = FALSE;
 | |
|     }
 | |
| 
 | |
|     if (drvChar & 0x7F) {
 | |
|         if (Ext2InsertMountPoint(volume, drvChar & 0x7F, TRUE)) {
 | |
|             return TRUE;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!rc) {
 | |
|         Ext2VolumeArrivalNotify(volume);
 | |
|     }
 | |
| 
 | |
|     cLetter = Ext2QueryMountPoint(volume);
 | |
| 	if (!cLetter && (cLetter != (drvChar & 0x7F))) {
 | |
|         Ext2InsertMountPoint(volume, drvChar & 0x7F, TRUE);
 | |
|     }
 | |
| 
 | |
|     cLetter = Ext2QueryMountPoint(volume);
 | |
|     if (cLetter) {
 | |
|         Ext2InsertMountPoint(volume, cLetter, FALSE);
 | |
|     }
 | |
| 
 | |
|     rc =  (cLetter > 0) ?  TRUE: FALSE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL Ext2IsDrvLetterAvailable(CHAR drive)
 | |
| {
 | |
|     CHAR            symLink[MAX_PATH] = {0};
 | |
|     UINT            drvType;
 | |
| 
 | |
|     drvType = Ext2QueryDrive(drive, symLink);
 | |
|     if (drvType == DRIVE_NO_ROOT_DIR) {
 | |
|         return TRUE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| CHAR Ext2GetFirstAvailableDrvLetter()
 | |
| {
 | |
|     int             i;
 | |
| 
 | |
|     for (i = 2; i < 24; i++) {
 | |
|         if (Ext2IsDrvLetterAvailable('A' + i))
 | |
|             return ('A' + i);
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL
 | |
| Ext2NotifyVolumePoint(
 | |
|     PEXT2_VOLUME    volume,
 | |
|     UCHAR           drvChar
 | |
|     )
 | |
| {
 | |
|     PEXT2_LETTER letter;
 | |
|     UCHAR   mounted = 0;
 | |
|     BOOL    rc = FALSE;
 | |
|     PCHAR   Name = NULL;
 | |
| 
 | |
|     drvChar = (UCHAR)toupper(drvChar);
 | |
|     letter  = &drvLetters[drvChar - 'A'];
 | |
| 
 | |
|     if (volume->Part) {
 | |
|         Name = &volume->Part->Name[0];
 | |
|     } else {
 | |
|         Name = &volume->Name[0];
 | |
|     }
 | |
| 
 | |
|     /* do drive update */
 | |
|     if (Ext2IsDrvLetterAvailable(drvChar))
 | |
|         Ext2UpdateDrvLetter(letter, Name);
 | |
| 
 | |
|     rc = Ext2VolumeArrivalNotify(Name);
 | |
| 
 | |
|     Sleep(500);
 | |
| 
 | |
|     mounted = Ext2QueryMountPoint(Name);
 | |
|     if (mounted) {
 | |
|         rc = TRUE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     if (!Ext2IsDrvLetterAvailable(drvChar)) {
 | |
|         drvChar = Ext2GetFirstAvailableDrvLetter();
 | |
|         if ((drvChar|0x20) >= 'a' && (drvChar | 0x20) <= 'z') {
 | |
|             letter  = &drvLetters[drvChar - 'A'];
 | |
|         } else {
 | |
|             letter = NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (letter) {
 | |
|         rc = Ext2AssignDrvLetter(letter, Name, FALSE);
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| #define EXT2_MANAGER_NAME  "Ext2 Volume Manager"
 | |
| 
 | |
| BOOL Ext2RunMgrForCurrentUserXP()
 | |
| {
 | |
|     HKEY   key ;
 | |
|     CHAR   keyPath[MAX_PATH] ;
 | |
|     LONG   status ;
 | |
|     DWORD  type, len = MAX_PATH;
 | |
|     BOOL   rc = FALSE;
 | |
| 
 | |
|     CHAR   	appPath[MAX_PATH] ;
 | |
| 
 | |
|     GetModuleFileName(NULL, appPath, MAX_PATH - 6);
 | |
|     strcat(appPath, " -quiet");
 | |
| 
 | |
|     strcpy (keyPath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") ;
 | |
|     status = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                               keyPath,
 | |
|                               0,
 | |
|                               KEY_ALL_ACCESS,
 | |
|                               &key) ;
 | |
| 
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     status = RegQueryValueEx( key, EXT2_MANAGER_NAME, 0, &type, 
 | |
|                                (BYTE *)appPath, &len);
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     rc = TRUE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     RegCloseKey (key) ;
 | |
|     return rc;
 | |
| }
 | |
| 	
 | |
| BOOL
 | |
| Ext2SetAppAutorunXP(BOOL bInstall)
 | |
| {
 | |
|     BOOL   rc = FALSE;
 | |
|     HKEY   key ;
 | |
|     CHAR   keyPath[MAX_PATH] ;
 | |
|     LONG   status ;
 | |
| 
 | |
|     CHAR   	appPath[MAX_PATH] ;
 | |
| 
 | |
|     GetModuleFileName(NULL, appPath, MAX_PATH - 6);
 | |
|     strcat(appPath, " -quiet");
 | |
| 
 | |
|     strcpy (keyPath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run") ;
 | |
|     status = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                               keyPath,
 | |
|                               0,
 | |
|                               KEY_ALL_ACCESS,
 | |
|                               &key) ;
 | |
| 
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (!bInstall) {
 | |
|         status = RegDeleteValue (key, EXT2_MANAGER_NAME) ;
 | |
|         if (status != ERROR_SUCCESS) {
 | |
|             goto errorout;
 | |
|         }
 | |
|     } else {
 | |
|         status = RegSetValueEx( key, EXT2_MANAGER_NAME, 0, REG_SZ, 
 | |
|                                    (BYTE *)appPath, strlen(appPath));
 | |
|         if (status != ERROR_SUCCESS) {
 | |
|             goto errorout;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     rc = TRUE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     RegCloseKey (key) ;
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| CHAR *Ext2QueryAutoUserList()
 | |
| {
 | |
|     int     rc = TRUE;
 | |
|     HKEY    hKey;
 | |
|     CHAR    keyPath[MAX_PATH];
 | |
|     CHAR   *userList = NULL;
 | |
|     LONG    status, type, len;
 | |
| 
 | |
|     /* Open ext2fsd sevice key */
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Parameters") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS | KEY_WOW64_64KEY,
 | |
|                             &hKey) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         rc = FALSE;
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     /* query autorun user list */
 | |
|     len = PAGE_SIZE - 1;
 | |
|     userList = new CHAR[len + 1];
 | |
|     if (!userList)
 | |
|         goto errorout;
 | |
|     memset(userList, 0, len + 1);
 | |
|     status = RegQueryValueEx( hKey,
 | |
|                               "AutorunUsers",
 | |
|                               0,
 | |
|                               (LPDWORD)&type,
 | |
|                               (BYTE *)userList,
 | |
|                               (LPDWORD)&len);
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     RegCloseKey(hKey);
 | |
| 
 | |
|     return userList;
 | |
| }
 | |
| 
 | |
| BOOL Ext2SetAutoRunUserList(CHAR *userList)
 | |
| {
 | |
|     HKEY   key;
 | |
|     CHAR   keyPath[MAX_PATH] ;
 | |
|     LONG   status;
 | |
| 
 | |
|     strcpy (keyPath, "SYSTEM\\CurrentControlSet\\Services\\Ext2Fsd\\Parameters") ;
 | |
|     status = ::RegOpenKeyEx (HKEY_LOCAL_MACHINE,
 | |
|                             keyPath,
 | |
|                             0,
 | |
|                             KEY_ALL_ACCESS | KEY_WOW64_64KEY,
 | |
|                             &key) ;
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = RegSetValueEx( key, "AutorunUsers", 0, REG_SZ, 
 | |
|                             (BYTE *)userList, strlen(userList));
 | |
|     if (status != ERROR_SUCCESS) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     RegCloseKey(key) ;
 | |
| 
 | |
|     return (status == ERROR_SUCCESS);
 | |
| }
 | |
| 
 | |
| TCHAR *
 | |
| Ext2StrStr(TCHAR *s, TCHAR *t)
 | |
| {
 | |
|     int ls = _tcslen(s), lt = _tcslen(t), i;
 | |
|     for (i = 0; i + lt <= ls; i++) {
 | |
|         if (0 == _tcsnicmp(&s[i], t, lt))
 | |
|             return &s[i];
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL Ext2RunMgrForCurrentUserVista()
 | |
| {
 | |
|     CHAR *userList = NULL, *user, e;
 | |
|     CHAR  userName[256] = {0};
 | |
|     DWORD userLen = 255;
 | |
|     BOOL  rc = FALSE;
 | |
| 
 | |
|     if (!GetUserName(userName, &userLen))
 | |
|         return FALSE;
 | |
| 
 | |
|     userList = Ext2QueryAutoUserList();
 | |
|     if (!userList)
 | |
|         return FALSE;
 | |
| 
 | |
|     user = userList;
 | |
|     while (user = Ext2StrStr(user, userName)) {
 | |
|         if (user > userList) {
 | |
|             e = user[-1];
 | |
|             if (e != ',' && e != ';') {
 | |
|                 user = user + strlen(userName);
 | |
|                 continue;
 | |
|             }
 | |
|         }
 | |
|         e = user[strlen(userName)];
 | |
|         if (!e || e == ',' || e == ';') {
 | |
|             rc = TRUE;
 | |
|             goto errorout;
 | |
|         }
 | |
|         user = user + strlen(userName);
 | |
|     }
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (userList)
 | |
|         delete [] userList;
 | |
| 
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetAppAutorunVista(BOOL bAutorun)
 | |
| {
 | |
|     CHAR *userList = NULL, *user, *e;
 | |
|     CHAR  userName[256] = {0};
 | |
|     DWORD userLen = 255;
 | |
|     BOOL  changed = FALSE;
 | |
| 
 | |
|     if (!GetUserName(userName, &userLen))
 | |
|         return FALSE;
 | |
| 
 | |
|     userList = Ext2QueryAutoUserList();
 | |
|     if (!userList)
 | |
|         return FALSE;
 | |
| 
 | |
|     if (bAutorun) {
 | |
| 
 | |
|         user = userList;
 | |
|         while (user = Ext2StrStr(user, userName)) {
 | |
|             if (user > userList) {
 | |
|                 e = user-1;
 | |
|                 if (*e != ',' && *e != ';') {
 | |
|                     user = user + strlen(userName);
 | |
|                     continue;
 | |
|                 }
 | |
|             }
 | |
|             e = &user[strlen(userName)];
 | |
|             if (!*e || *e == ',' || *e == ';') {
 | |
|                 goto errorout;
 | |
|             }
 | |
|             user = user + strlen(userName);
 | |
|         }
 | |
| 
 | |
|         e = &userList[strlen(userList) - 1];
 | |
|         if (e > userList && *e != ',' && *e != ';') {
 | |
|             strcat_s(userList, PAGE_SIZE - 1, ";");
 | |
|         }
 | |
|         strcat_s(userList, PAGE_SIZE - 1, userName);
 | |
|         strcat_s(userList, PAGE_SIZE - 1, ";");
 | |
|         changed = TRUE;
 | |
| 
 | |
|     } else {
 | |
|         user = userList;
 | |
|         while (user = Ext2StrStr(user, userName)) {
 | |
|             if (user > userList) {
 | |
|                 e = user - 1;
 | |
|                 if (*e != ',' && *e != ';') {
 | |
|                     user = user + strlen(userName);
 | |
|                     continue;
 | |
|                 }
 | |
|             }
 | |
|             e = &user[strlen(userName)];
 | |
|             if (!*e) {
 | |
|                 memset(user, 0, strlen(userName) + 1);
 | |
|                 changed = TRUE;
 | |
|             } else if (*e == ',' || *e == ';') {
 | |
|                 memmove(user, e + 1, strlen(e));
 | |
|                 changed = TRUE;
 | |
|             } else {
 | |
|                 user = user + strlen(userName);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (changed)
 | |
|         changed = Ext2SetAutoRunUserList(userList);
 | |
|     else
 | |
|         changed = TRUE;
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     if (userList)
 | |
|         delete []userList;
 | |
| 
 | |
|     return TRUE;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2SetAppAutorun(BOOL bAutorun)
 | |
| {
 | |
|     if (IsWindowsVistaOrGreater())
 | |
|         return Ext2SetAppAutorunVista(bAutorun);
 | |
| 
 | |
|     return Ext2SetAppAutorunXP(bAutorun);
 | |
| }
 | |
| 
 | |
| 
 | |
| BOOL Ext2RunMgrForCurrentUser()
 | |
| {
 | |
|     if (IsWindowsVistaOrGreater())
 | |
|         return Ext2RunMgrForCurrentUserVista();
 | |
| 
 | |
|     return Ext2RunMgrForCurrentUserXP();
 | |
| }
 | |
| 
 | |
| 
 | |
| #define SERVICE_CMD_LENGTH (MAX_PATH * 2)
 | |
| 
 | |
| int
 | |
| Ext2SetManagerAsService(BOOL bInstall)
 | |
| {
 | |
|     SC_HANDLE   hService;
 | |
|     SC_HANDLE   hManager;
 | |
| 
 | |
|     CHAR Target[SERVICE_CMD_LENGTH];
 | |
| 
 | |
|     // get the filename of this executable
 | |
|     if (GetModuleFileName(NULL, Target, SERVICE_CMD_LENGTH - 20) == 0) {
 | |
|         AfxMessageBox("Unable to install Ext2Mgr as service",
 | |
|                       MB_ICONEXCLAMATION | MB_OK);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     // append parameters to the end of the path:
 | |
|     strcat(Target, " -service -hide");
 | |
| 
 | |
|     // open Service Control Manager
 | |
|     hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
 | |
|     if (hManager == NULL) {
 | |
|         AfxMessageBox("Ext2Mgr: cannot open Service Control Manager",
 | |
|                       MB_ICONEXCLAMATION | MB_OK);
 | |
|         return FALSE;
 | |
|     }
 | |
| 
 | |
|     if (bInstall) {
 | |
| 
 | |
|         // now create service entry for Ext2Mgr
 | |
|         hService = CreateService(
 | |
|                 hManager,                   // SCManager database
 | |
|                 "Ext2Mgr",                  // name of service
 | |
|                 "Ext2 Volume Manger",       // name to display
 | |
|                 SERVICE_ALL_ACCESS,	        // desired access
 | |
|                 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
 | |
|                                             // service type
 | |
|                 SERVICE_AUTO_START,	        // start type
 | |
|                 SERVICE_ERROR_NORMAL,       // error control type
 | |
| 				Target,	                    // service's binary
 | |
|                 NULL,                       // no load ordering group
 | |
|                 NULL,                       // no tag identifier
 | |
|                 NULL,			            // dependencies
 | |
|                 NULL,						// LocalSystem account
 | |
|                 NULL);                      // no password
 | |
| 
 | |
|         if (hService == NULL) {
 | |
|             DWORD error = GetLastError();
 | |
|             if (error == ERROR_SERVICE_EXISTS) {
 | |
|                 AfxMessageBox("Ext2Mgr service is already registered.",
 | |
|                               MB_ICONEXCLAMATION | MB_OK);
 | |
|             } else {
 | |
|                 AfxMessageBox("Ext2Mgr service couldn't be registered.",
 | |
|                               MB_ICONEXCLAMATION | MB_OK);
 | |
|             }
 | |
|         } else {
 | |
| 
 | |
|             CloseServiceHandle(hService);
 | |
| 
 | |
| 			// got Ext2Mgr installed as a service
 | |
|             AfxMessageBox(
 | |
|                 "Ext2Mgr service was successfully registered. \n\n"
 | |
| 				"You can modify the default settings and start/stop it from Control Panel.\n"
 | |
| 				"The service will automatically run the next time when system is restarted.\n",
 | |
| 				MB_ICONINFORMATION | MB_OK);
 | |
|         }
 | |
| 
 | |
|         Ext2SetAppAutorun(FALSE);
 | |
| 
 | |
|     } else {
 | |
| 
 | |
|         /* open the service of Ext2Mgr */
 | |
|         hService = OpenService(
 | |
|                 hManager,
 | |
|                 "Ext2Mgr",
 | |
|                 SERVICE_ALL_ACCESS
 | |
|                 );
 | |
| 
 | |
|         if (hService != NULL) {
 | |
| 
 | |
| #if 0
 | |
|             SERVICE_STATUS status;
 | |
| 
 | |
|             // stop the service
 | |
|             if (ControlService(hService, SERVICE_CONTROL_STOP, &status)) {
 | |
| 
 | |
|                 while(QueryServiceStatus(hService, &status)) {
 | |
|                     if (status.dwCurrentState == SERVICE_STOP_PENDING) {
 | |
|                         Sleep(1000);
 | |
|                     } else {
 | |
|                         break;
 | |
|                     }
 | |
|                 }
 | |
| 
 | |
|                 if (status.dwCurrentState != SERVICE_STOPPED) {
 | |
|                     AfxMessageBox("Could not stop Ext2Mgr service !",
 | |
|                                   MB_ICONEXCLAMATION | MB_OK);
 | |
|                 }
 | |
|             }
 | |
| #endif
 | |
|             // remove the service from the SCM
 | |
|             if (DeleteService(hService)) {
 | |
|                 AfxMessageBox("The Ext2Mgr service has been unregistered.",
 | |
|                 MB_ICONINFORMATION | MB_OK);
 | |
|             } else {
 | |
|                 DWORD error = GetLastError();
 | |
|                 if (error == ERROR_SERVICE_MARKED_FOR_DELETE) {
 | |
|                     AfxMessageBox("Ext2Mgr service is already unregistered",
 | |
|                                   MB_ICONEXCLAMATION | MB_OK);
 | |
|                 } else {
 | |
|                     AfxMessageBox("Ext2Mgr service could not be unregistered",
 | |
|                                    MB_ICONEXCLAMATION | MB_OK);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             CloseServiceHandle(hService);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     CloseServiceHandle(hManager);
 | |
| 
 | |
| 	return TRUE;
 | |
| }
 | |
| 
 | |
| BOOL g_bAutoRemoveDeadLetters = TRUE;
 | |
| 
 | |
| VOID
 | |
| Ext2AddLetterMask(ULONGLONG LetterMask)
 | |
| {
 | |
|     Ext2DrvLetters[1] |= LetterMask;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| Ext2AutoRemoveDeadLetters()
 | |
| {
 | |
|     ULONGLONG   LetterMask = Ext2DrvLetters[0];
 | |
|     DWORD       i, j;
 | |
|     PEXT2_DISK      disk;
 | |
|     PEXT2_PARTITION part;
 | |
|     PEXT2_CDROM     cdrom;
 | |
| 
 | |
|     if (LetterMask != -1) {
 | |
|         AfxMessageBox("Different Mask");
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < g_nDisks; i++) {
 | |
|         disk = &gDisks[i];
 | |
|         if (disk->DataParts == NULL) {
 | |
|             continue;
 | |
|         }
 | |
|         for (j=0; j < disk->NumParts; j++) {
 | |
|             part = &disk->DataParts[j];
 | |
|             if (part) {
 | |
|                  LetterMask &= ~(part->DrvLetters);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < g_nCdroms; i++) {
 | |
|         cdrom = &gCdroms[i];
 | |
|         LetterMask &= ~(cdrom->DrvLetters);
 | |
|     }
 | |
| 
 | |
|     for (i=0; i < 10; i++) {
 | |
|         if (drvDigits[i].bUsed && (drvDigits[i].Extent == NULL) &&
 | |
|             (LetterMask & (((ULONGLONG) 1) << (i + 32)) ) ) {
 | |
|             if (drvDigits[i].bInvalid && drvDigits[i].DrvType == DRIVE_FIXED) {
 | |
|                 LetterMask &= (~(((ULONGLONG) 1) << (i + 32)));
 | |
|                 Ext2RemoveMountPoint(&drvDigits[i], FALSE);
 | |
|                 Ext2RemoveDosSymLink(drvDigits[i].Letter);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     for (i=2; i <26; i++) {
 | |
|         if (drvLetters[i].bUsed && (drvLetters[i].Extent == NULL) &&
 | |
|             (LetterMask & (((ULONGLONG) 1) << i)) ) {
 | |
|             if (drvLetters[i].bInvalid && drvLetters[i].DrvType == DRIVE_FIXED) {
 | |
|                 LetterMask &= (~(((ULONGLONG) 1) << i));
 | |
|                 Ext2RemoveMountPoint(&drvLetters[i], FALSE);
 | |
|                 Ext2RemoveDosSymLink(drvLetters[i].Letter);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Ext2DrvLetters[0] = LetterMask;
 | |
| }
 | |
| 
 | |
| BOOL
 | |
| Ext2RemoveDosSymLink(CHAR drvChar)
 | |
| {
 | |
|     EXT2_MOUNT_POINT             E2MP;
 | |
|     NT::NTSTATUS                 status;
 | |
|     HANDLE                       handle = NULL;
 | |
|     NT::IO_STATUS_BLOCK          iosb;
 | |
| 
 | |
|     Ext2SymLinkRemoval(drvChar);
 | |
| 
 | |
|     memset(&E2MP, 0, sizeof(EXT2_MOUNT_POINT));
 | |
|     E2MP.Magic = EXT2_APP_MOUNTPOINT_MAGIC;
 | |
|     E2MP.Command = APP_CMD_DEL_DOS_SYMLINK;
 | |
|     E2MP.Link[0] = (USHORT) drvChar;
 | |
| 
 | |
|     status = Ext2Open("\\DosDevices\\Ext2Fsd", 
 | |
|                       &handle, EXT2_DESIRED_ACCESS);
 | |
|     if (!NT_SUCCESS(status)) {
 | |
|         goto errorout;
 | |
|     }
 | |
| 
 | |
|     status = NT::ZwDeviceIoControlFile(
 | |
|                 handle, NULL, NULL, NULL, &iosb,
 | |
|                 IOCTL_APP_MOUNT_POINT,
 | |
|                 &E2MP, sizeof(EXT2_MOUNT_POINT),
 | |
|                 &E2MP, sizeof(EXT2_MOUNT_POINT)
 | |
|             );
 | |
| 
 | |
| errorout:
 | |
| 
 | |
|     Ext2Close(&handle);
 | |
| 
 | |
|     return NT_SUCCESS(status);
 | |
| }
 |