Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061/* * PROJECT: ReactOS DiskPart * LICENSE: GPL - See COPYING in the top level directory * FILE: base/system/diskpart/partlist.c * PURPOSE: Manages all the partitions of the OS in an interactive way. * PROGRAMMERS: Eric Kohl */
/* INCLUDES *******************************************************************/
#include "diskpart.h"
#define NDEBUG#include <debug.h>
#define InsertAscendingList(ListHead, NewEntry, Type, ListEntryField, SortField)\{\ PLIST_ENTRY current;\\ current = (ListHead)->Flink;\ while (current != (ListHead))\ {\ if (CONTAINING_RECORD(current, Type, ListEntryField)->SortField >=\ (NewEntry)->SortField)\ {\ break;\ }\ current = current->Flink;\ }\\ InsertTailList(current, &((NewEntry)->ListEntryField));\}
/* We have to define it there, because it is not in the MS DDK */#define PARTITION_LINUX 0x83
#define PARTITION_TBL_SIZE 4
#define MBR_MAGIC 0xAA55
#include <pshpack1.h>
typedef struct _PARTITION{ unsigned char BootFlags; /* bootable? 0=no, 128=yes */ unsigned char StartingHead; /* beginning head number */ unsigned char StartingSector; /* beginning sector number */ unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */ unsigned char PartitionType; /* Operating System type indicator code */ unsigned char EndingHead; /* ending head number */ unsigned char EndingSector; /* ending sector number */ unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */ unsigned int StartingBlock; /* first sector relative to start of disk */ unsigned int SectorCount; /* number of sectors in partition */} PARTITION, *PPARTITION;
typedef struct _PARTITION_SECTOR{ UCHAR BootCode[440]; /* 0x000 */ ULONG Signature; /* 0x1B8 */ UCHAR Reserved[2]; /* 0x1BC */ PARTITION Partition[PARTITION_TBL_SIZE]; /* 0x1BE */ USHORT Magic; /* 0x1FE */} PARTITION_SECTOR, *PPARTITION_SECTOR;
#include <poppack.h>
/* GLOBALS ********************************************************************/
LIST_ENTRY DiskListHead;LIST_ENTRY BiosDiskListHead;LIST_ENTRY VolumeListHead;
PDISKENTRY CurrentDisk = NULL;PPARTENTRY CurrentPartition = NULL;PVOLENTRY CurrentVolume = NULL;
/* FUNCTIONS ******************************************************************/
#ifdef DUMP_PARTITION_TABLEVOIDDumpPartitionTable( _In_ PDISKENTRY DiskEntry){ PPARTITION_INFORMATION_EX PartitionInfo; ULONG i;
DbgPrint("\n");
if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_MBR) { DbgPrint("Index Start Length Hidden Nr Type Boot RW\n"); DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i]; DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n", i, PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector, PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector, PartitionInfo->Mbr.HiddenSectors, PartitionInfo->PartitionNumber, PartitionInfo->Mbr.PartitionType, PartitionInfo->Mbr.BootIndicator ? '*': ' ', PartitionInfo->RewritePartition ? 'Y': 'N'); } } else if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_GPT) { DbgPrint("Index Start Length Nr RW Type \n"); DbgPrint("----- ------------ ------------ -- -- --------\n"); for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
DbgPrint(" %3lu %12I64u %12I64u %2lu %c %08lx\n", i, PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector, PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector, PartitionInfo->PartitionNumber, PartitionInfo->RewritePartition ? 'Y': 'N', PartitionInfo->Gpt.PartitionType.Data1); } }
DbgPrint("\n");}#endif
#ifdef DUMP_PARTITION_LISTVOIDDumpPartitionList( _In_ PDISKENTRY DiskEntry){ PLIST_ENTRY ListEntry; PPARTENTRY PartEntry;
DbgPrint("\n");
if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) { DbgPrint("Disk Start Disk End Disk Length \n"); DbgPrint("------------ ------------ ------------\n"); DbgPrint("%12I64u %12I64u %12I64u\n", DiskEntry->StartSector.QuadPart, DiskEntry->EndSector.QuadPart, DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
DbgPrint("\n");
DbgPrint("Start End Length Nr Type P\n"); DbgPrint("------------ ------------ ------------ --- -------- --\n");
for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; ListEntry != &DiskEntry->PrimaryPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
DbgPrint("%12I64u %12I64u %12I64u %3lu %08lx %c\n", PartEntry->StartSector.QuadPart, PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1, PartEntry->SectorCount.QuadPart, PartEntry->PartitionNumber, PartEntry->Gpt.PartitionType.Data1, PartEntry->IsPartitioned ? 'Y': 'N'); } } else if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) { DbgPrint("Disk Start Disk End Disk Length \n"); DbgPrint("------------ ------------ ------------\n"); DbgPrint("%12I64u %12I64u %12I64u\n", DiskEntry->StartSector.QuadPart, DiskEntry->EndSector.QuadPart, DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
}
DbgPrint("\n");}#endif
ULONGLONGAlignDown( _In_ ULONGLONG Value, _In_ ULONG Alignment){ ULONGLONG Temp;
Temp = Value / Alignment;
return Temp * Alignment;}
staticVOIDGetDriverName( PDISKENTRY DiskEntry){ RTL_QUERY_REGISTRY_TABLE QueryTable[2]; WCHAR KeyName[32]; NTSTATUS Status;
RtlInitUnicodeString(&DiskEntry->DriverName, NULL);
StringCchPrintfW(KeyName, ARRAYSIZE(KeyName), L"\\Scsi\\Scsi Port %lu", DiskEntry->Port);
RtlZeroMemory(&QueryTable, sizeof(QueryTable));
QueryTable[0].Name = L"Driver"; QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; QueryTable[0].EntryContext = &DiskEntry->DriverName;
Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP, KeyName, QueryTable, NULL, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status); }}
staticNTSTATUSNTAPIDiskIdentifierQueryRoutine( PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext){ PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context; UNICODE_STRING NameU;
if (ValueType == REG_SZ && ValueLength == 20 * sizeof(WCHAR)) { NameU.Buffer = (PWCHAR)ValueData; NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR); RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
NameU.Buffer = (PWCHAR)ValueData + 9; RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
return STATUS_SUCCESS; }
return STATUS_UNSUCCESSFUL;}
staticNTSTATUSNTAPIDiskConfigurationDataQueryRoutine( PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext){ PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context; PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry; ULONG i;
if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR || ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) return STATUS_UNSUCCESSFUL;
FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
/* Hm. Version and Revision are not set on Microsoft Windows XP... */#if 0 if (FullResourceDescriptor->PartialResourceList.Version != 1 || FullResourceDescriptor->PartialResourceList.Revision != 1) return STATUS_UNSUCCESSFUL;#endif
for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++) { if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific || FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA)) continue;
DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1]; BiosDiskEntry->DiskGeometry = *DiskGeometry;
return STATUS_SUCCESS; }
return STATUS_UNSUCCESSFUL;}
staticNTSTATUSNTAPISystemConfigurationDataQueryRoutine( PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext){ PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor; PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context; ULONG i;
if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR || ValueLength < sizeof (CM_FULL_RESOURCE_DESCRIPTOR)) return STATUS_UNSUCCESSFUL;
FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
/* Hm. Version and Revision are not set on Microsoft Windows XP... */#if 0 if (FullResourceDescriptor->PartialResourceList.Version != 1 || FullResourceDescriptor->PartialResourceList.Revision != 1) return STATUS_UNSUCCESSFUL;#endif
for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++) { if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific || FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0) continue;
*Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(RtlGetProcessHeap(), 0, FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize); if (*Int13Drives == NULL) return STATUS_NO_MEMORY;
memcpy(*Int13Drives, &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1], FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize); return STATUS_SUCCESS; }
return STATUS_UNSUCCESSFUL;}
#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
staticVOIDEnumerateBiosDiskEntries(VOID){ RTL_QUERY_REGISTRY_TABLE QueryTable[3]; WCHAR Name[120]; ULONG AdapterCount; ULONG DiskCount; NTSTATUS Status; PCM_INT13_DRIVE_PARAMETER Int13Drives; PBIOSDISKENTRY BiosDiskEntry;
memset(QueryTable, 0, sizeof(QueryTable));
QueryTable[1].Name = L"Configuration Data"; QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine; Int13Drives = NULL; Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System", &QueryTable[1], (PVOID)&Int13Drives, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status); return; }
AdapterCount = 0; while (1) { StringCchPrintfW(Name, ARRAYSIZE(Name), L"%s\\%lu", ROOT_NAME, AdapterCount); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, Name, &QueryTable[2], NULL, NULL); if (!NT_SUCCESS(Status)) { break; }
StringCchPrintfW(Name, ARRAYSIZE(Name), L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, Name, &QueryTable[2], NULL, NULL); if (NT_SUCCESS(Status)) { while (1) { StringCchPrintfW(Name, ARRAYSIZE(Name), L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, Name, &QueryTable[2], NULL, NULL); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives); return; }
StringCchPrintfW(Name, ARRAYSIZE(Name), L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, Name, &QueryTable[2], NULL, NULL); if (NT_SUCCESS(Status)) { QueryTable[0].Name = L"Identifier"; QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine; QueryTable[1].Name = L"Configuration Data"; QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
DiskCount = 0; while (1) { BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY)); if (BiosDiskEntry == NULL) { break; }
StringCchPrintfW(Name, ARRAYSIZE(Name), L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, Name, QueryTable, (PVOID)BiosDiskEntry, NULL); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry); break; }
BiosDiskEntry->DiskNumber = DiskCount; BiosDiskEntry->Recognized = FALSE;
if (DiskCount < Int13Drives[0].NumberDrives) { BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount]; } else { DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount); }
InsertTailList(&BiosDiskListHead, &BiosDiskEntry->ListEntry);
DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber); DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature); DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum); DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector); DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders); DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads); DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect); DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders); DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack); DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads); DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
DiskCount++; } }
RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives); return; } }
AdapterCount++; }
RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);}
staticVOIDAddMbrPartitionToDisk( ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, BOOLEAN LogicalPartition){ PPARTITION_INFORMATION_EX PartitionInfo; PPARTENTRY PartEntry;
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex]; if (PartitionInfo->Mbr.PartitionType == 0 || (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->Mbr.PartitionType))) return;
PartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (PartEntry == NULL) { /* TODO: Error message */ return; }
PartEntry->DiskEntry = DiskEntry;
PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
PartEntry->Mbr.BootIndicator = PartitionInfo->Mbr.BootIndicator; PartEntry->Mbr.PartitionType = PartitionInfo->Mbr.PartitionType;
PartEntry->LogicalPartition = LogicalPartition; PartEntry->IsPartitioned = TRUE; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; PartEntry->PartitionIndex = PartitionIndex;
if (IsContainerPartition(PartEntry->Mbr.PartitionType)) { PartEntry->FormatState = Unformatted;
if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL) DiskEntry->ExtendedPartition = PartEntry; } else if ((PartEntry->Mbr.PartitionType == PARTITION_FAT_12) || (PartEntry->Mbr.PartitionType == PARTITION_FAT_16) || (PartEntry->Mbr.PartitionType == PARTITION_HUGE) || (PartEntry->Mbr.PartitionType == PARTITION_XINT13) || (PartEntry->Mbr.PartitionType == PARTITION_FAT32) || (PartEntry->Mbr.PartitionType == PARTITION_FAT32_XINT13)) {#if 0 if (CheckFatFormat()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; }#endif PartEntry->FormatState = Preformatted; } else if (PartEntry->Mbr.PartitionType == PARTITION_LINUX) {#if 0 if (CheckExt2Format()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; }#endif PartEntry->FormatState = Preformatted; } else if (PartEntry->Mbr.PartitionType == PARTITION_IFS) {#if 0 if (CheckNtfsFormat()) { PartEntry->FormatState = Preformatted; } else if (CheckHpfsFormat()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; }#endif PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = UnknownFormat; }
if (LogicalPartition) InsertTailList(&DiskEntry->LogicalPartListHead, &PartEntry->ListEntry); else InsertTailList(&DiskEntry->PrimaryPartListHead, &PartEntry->ListEntry);}
staticVOIDAddGptPartitionToDisk( ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex){ PPARTITION_INFORMATION_EX PartitionInfo; PPARTENTRY PartEntry;
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex]; if (IsEqualGUID(&PartitionInfo->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) return;
PartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (PartEntry == NULL) { /* TODO: Error message */ return; }
PartEntry->DiskEntry = DiskEntry;
PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
CopyMemory(&PartEntry->Gpt.PartitionType, &PartitionInfo->Gpt.PartitionType, sizeof(GUID)); CopyMemory(&PartEntry->Gpt.PartitionId, &PartitionInfo->Gpt.PartitionId, sizeof(GUID)); PartEntry->Gpt.Attributes = PartitionInfo->Gpt.Attributes;
PartEntry->LogicalPartition = FALSE; PartEntry->IsPartitioned = TRUE; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; PartEntry->PartitionIndex = PartitionIndex;
/* TODO: Determine the format state */ PartEntry->FormatState = Unformatted;
InsertTailList(&DiskEntry->PrimaryPartListHead, &PartEntry->ListEntry);}
VOIDScanForUnpartitionedMbrDiskSpace( PDISKENTRY DiskEntry){ ULONGLONG StartSector, EndSector; ULONGLONG LastStartSector; ULONGLONG LastSectorCount; ULONGLONG LastUnusedSectorCount; PPARTENTRY PartEntry; PPARTENTRY NewPartEntry; PLIST_ENTRY Entry;
DPRINT("ScanForUnpartitionedMbrDiskSpace()\n");
/* Calculate the disk sector limits */ /* Limit the SectorCount to 2^32 sectors for MBR disks */ StartSector = (ULONGLONG)DiskEntry->SectorAlignment; EndSector = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
if (IsListEmpty(&DiskEntry->PrimaryPartListHead)) { DPRINT1("No primary partition!\n");
/* Create a partition table that represents the empty disk */ NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = StartSector; NewPartEntry->SectorCount.QuadPart = AlignDown(EndSector + 1, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
InsertTailList(&DiskEntry->PrimaryPartListHead, &NewPartEntry->ListEntry);
return; }
/* Start at the first usable sector */ LastStartSector = StartSector; LastSectorCount = 0ULL; LastUnusedSectorCount = 0ULL;
Entry = DiskEntry->PrimaryPartListHead.Flink; while (Entry != &DiskEntry->PrimaryPartListHead) { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->SectorCount.QuadPart != 0ULL) { LastUnusedSectorCount = PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) && LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Insert the table into the list */ InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry); }
LastStartSector = PartEntry->StartSector.QuadPart; LastSectorCount = PartEntry->SectorCount.QuadPart; }
Entry = Entry->Flink; }
/* Check for trailing unpartitioned disk space */ if ((LastStartSector + LastSectorCount) < (EndSector + 1)) { LastUnusedSectorCount = AlignDown((EndSector + 1) - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT1("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Append the table to the list */ InsertTailList(&DiskEntry->PrimaryPartListHead, &NewPartEntry->ListEntry); } }
if (DiskEntry->ExtendedPartition != NULL) { if (IsListEmpty(&DiskEntry->LogicalPartListHead)) { DPRINT1("No logical partition!\n");
/* Create a partition table entry that represents the empty extended partition */ NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->LogicalPartition = TRUE;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment; NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
InsertTailList(&DiskEntry->LogicalPartListHead, &NewPartEntry->ListEntry);
return; }
/* Start partition at head 1, cylinder 0 */ LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment; LastSectorCount = 0ULL; LastUnusedSectorCount = 0ULL;
Entry = DiskEntry->LogicalPartListHead.Flink; while (Entry != &DiskEntry->LogicalPartListHead) { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->SectorCount.QuadPart != 0ULL) { LastUnusedSectorCount = PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) && LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->LogicalPartition = TRUE;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Insert the table into the list */ InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry); }
LastStartSector = PartEntry->StartSector.QuadPart; LastSectorCount = PartEntry->SectorCount.QuadPart; }
Entry = Entry->Flink; }
/* Check for trailing unpartitioned disk space */ if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart) { LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry; NewPartEntry->LogicalPartition = TRUE;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Append the table to the list */ InsertTailList(&DiskEntry->LogicalPartListHead, &NewPartEntry->ListEntry); } } }
DPRINT("ScanForUnpartitionedMbrDiskSpace() done\n");}
VOIDScanForUnpartitionedGptDiskSpace( PDISKENTRY DiskEntry){ ULONGLONG LastStartSector; ULONGLONG LastSectorCount; ULONGLONG LastUnusedSectorCount; PPARTENTRY PartEntry; PPARTENTRY NewPartEntry; PLIST_ENTRY Entry;
DPRINT("ScanForUnpartitionedGptDiskSpace()\n");
#ifdef DUMP_PARTITION_LIST DumpPartitionList(DiskEntry);#endif
if (IsListEmpty(&DiskEntry->PrimaryPartListHead)) { DPRINT("No partitions!\n");
/* Create a partition table that represents the empty disk */ NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = DiskEntry->StartSector.QuadPart; NewPartEntry->SectorCount.QuadPart = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1;
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
InsertTailList(&DiskEntry->PrimaryPartListHead, &NewPartEntry->ListEntry);
#ifdef DUMP_PARTITION_LIST DumpPartitionList(DiskEntry);#endif
return; }
/* Start at the first usable sector */ LastStartSector = DiskEntry->StartSector.QuadPart; LastSectorCount = 0ULL; LastUnusedSectorCount = 0ULL;
Entry = DiskEntry->PrimaryPartListHead.Flink; while (Entry != &DiskEntry->PrimaryPartListHead) { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID) || PartEntry->SectorCount.QuadPart != 0ULL) { LastUnusedSectorCount = PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) && LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Insert the table into the list */ InsertTailList(&PartEntry->ListEntry, &NewPartEntry->ListEntry); }
LastStartSector = PartEntry->StartSector.QuadPart; LastSectorCount = PartEntry->SectorCount.QuadPart; }
Entry = Entry->Flink; }
/* Check for trailing unpartitioned disk space */ if ((LastStartSector + LastSectorCount) < DiskEntry->EndSector.QuadPart + 1) { LastUnusedSectorCount = AlignDown(DiskEntry->EndSector.QuadPart + 1 - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment) { DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (NewPartEntry == NULL) return;
NewPartEntry->DiskEntry = DiskEntry;
NewPartEntry->IsPartitioned = FALSE; NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount; NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) - NewPartEntry->StartSector.QuadPart;
DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart); DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1); DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
NewPartEntry->FormatState = Unformatted;
/* Append the table to the list */ InsertTailList(&DiskEntry->PrimaryPartListHead, &NewPartEntry->ListEntry); } }
#ifdef DUMP_PARTITION_LIST DumpPartitionList(DiskEntry);#endif
DPRINT("ScanForUnpartitionedGptDiskSpace() done\n");}
VOIDReadLayoutBuffer( _In_ HANDLE FileHandle, _In_ PDISKENTRY DiskEntry){ ULONG LayoutBufferSize; PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer; IO_STATUS_BLOCK Iosb; NTSTATUS Status;
/* Allocate a layout buffer with 4 partition entries first */ LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX)); DiskEntry->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, LayoutBufferSize); if (DiskEntry->LayoutBuffer == NULL) { DPRINT1("Failed to allocate the disk layout buffer!\n"); return; }
for (;;) { DPRINT("Buffer size: %lu\n", LayoutBufferSize); Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, DiskEntry->LayoutBuffer, LayoutBufferSize); if (NT_SUCCESS(Status)) break;
if (Status != STATUS_BUFFER_TOO_SMALL) { DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status); return; }
LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION_EX); NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DiskEntry->LayoutBuffer, LayoutBufferSize); if (NewLayoutBuffer == NULL) { DPRINT1("Failed to reallocate the disk layout buffer!\n"); return; }
DiskEntry->LayoutBuffer = NewLayoutBuffer; }}
staticVOIDAddDiskToList( HANDLE FileHandle, ULONG DiskNumber){ DISK_GEOMETRY DiskGeometry; SCSI_ADDRESS ScsiAddress; PDISKENTRY DiskEntry; IO_STATUS_BLOCK Iosb; NTSTATUS Status; PPARTITION_SECTOR Mbr; PULONG Buffer; LARGE_INTEGER FileOffset; WCHAR Identifier[20]; ULONG Checksum; ULONG Signature; ULONG i; PLIST_ENTRY ListEntry; PBIOSDISKENTRY BiosDiskEntry;
Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, sizeof(DISK_GEOMETRY)); if (!NT_SUCCESS(Status)) { return; }
if (DiskGeometry.MediaType != FixedMedia && DiskGeometry.MediaType != RemovableMedia) { return; }
Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_SCSI_GET_ADDRESS, NULL, 0, &ScsiAddress, sizeof(SCSI_ADDRESS)); if (!NT_SUCCESS(Status)) { return; }
PBYTE pBuffer = NULL;
pBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 1024);
STORAGE_PROPERTY_QUERY StoragePropertyQuery; StoragePropertyQuery.PropertyId = StorageDeviceProperty; StoragePropertyQuery.QueryType = PropertyStandardQuery; Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_STORAGE_QUERY_PROPERTY, &StoragePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), pBuffer, 1024); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer); pBuffer = NULL; }
Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(RtlGetProcessHeap(), 0, DiskGeometry.BytesPerSector); if (Mbr == NULL) { return; }
FileOffset.QuadPart = 0; Status = NtReadFile(FileHandle, NULL, NULL, NULL, &Iosb, (PVOID)Mbr, DiskGeometry.BytesPerSector, &FileOffset, NULL); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr); DPRINT1("NtReadFile failed, status=%x\n", Status); return; } Signature = Mbr->Signature;
/* Calculate the MBR checksum */ Checksum = 0; Buffer = (PULONG)Mbr; for (i = 0; i < 128; i++) { Checksum += Buffer[i]; } Checksum = ~Checksum + 1;
StringCchPrintfW(Identifier, ARRAYSIZE(Identifier), L"%08x-%08x-A", Checksum, Signature); DPRINT("Identifier: %S\n", Identifier);
DiskEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISKENTRY)); if (DiskEntry == NULL) { if (pBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer); RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr); return; }
if (pBuffer) { PSTORAGE_DESCRIPTOR_HEADER pDescriptorHeader;
pDescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)pBuffer; DPRINT("DescriptorHeader.Size %lu\n", pDescriptorHeader->Size);
if (pDescriptorHeader->Size <= 1024) { PSTORAGE_DEVICE_DESCRIPTOR pDeviceDescriptor; pDeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)pBuffer; DPRINT("VendorIdOffset %lu\n", pDeviceDescriptor->VendorIdOffset); DPRINT("ProductIdOffset %lu\n", pDeviceDescriptor->ProductIdOffset); DPRINT("ProductRevisionOffset %lu\n", pDeviceDescriptor->ProductRevisionOffset); DPRINT("SerialNumberOffset %lu\n", pDeviceDescriptor->SerialNumberOffset); DPRINT("BusType: %u\n", pDeviceDescriptor->BusType); if (pDeviceDescriptor->VendorIdOffset) { DPRINT("Vendor: %s\n", (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset)); }
if (pDeviceDescriptor->ProductIdOffset) { DPRINT("Product: %s\n", (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset)); }
INT VendorLength = 0, ProductLength = 0; PWSTR VendorBuffer = NULL, ProductBuffer = NULL;
if (pDeviceDescriptor->VendorIdOffset) { VendorLength = MultiByteToWideChar(437, 0, (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset), -1, NULL, 0); VendorBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, VendorLength * sizeof(WCHAR)); if (VendorBuffer) MultiByteToWideChar(437, 0, (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset), -1, VendorBuffer, VendorLength); }
if (pDeviceDescriptor->ProductIdOffset) { ProductLength = MultiByteToWideChar(437, 0, (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset), -1, NULL, 0);
ProductBuffer = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, ProductLength * sizeof(WCHAR)); if (ProductBuffer) MultiByteToWideChar(437, 0, (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset), -1, ProductBuffer, ProductLength); }
DiskEntry->Description = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, (VendorLength + ProductLength + 2) * sizeof(WCHAR)); if (VendorBuffer) wcscat(DiskEntry->Description, VendorBuffer);
if ((VendorLength > 0) && (ProductLength > 0)) wcscat(DiskEntry->Description, L" ");
if (ProductBuffer) wcscat(DiskEntry->Description, ProductBuffer);
DiskEntry->BusType = pDeviceDescriptor->BusType;
if (VendorBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, VendorBuffer);
if (ProductBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, ProductBuffer); }
RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer); }
// DiskEntry->Checksum = Checksum;// DiskEntry->Signature = Signature; DiskEntry->BiosFound = FALSE;
/* Check the disk partition style */ if (Mbr->Magic != MBR_MAGIC) { DPRINT("Partition style: RAW\n"); DiskEntry->PartitionStyle = PARTITION_STYLE_RAW; } else { if (Mbr->Partition[0].PartitionType == PARTITION_GPT) { DPRINT("Partition style: GPT\n"); DiskEntry->PartitionStyle = PARTITION_STYLE_GPT; } else { DPRINT("Partition style: MBR\n"); DiskEntry->PartitionStyle = PARTITION_STYLE_MBR; } }
/* Free Mbr sector buffer */ RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
ListEntry = BiosDiskListHead.Flink; while (ListEntry != &BiosDiskListHead) { BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry); /* FIXME: * Compare the size from bios and the reported size from driver. * If we have more than one disk with a zero or with the same signatur * we must create new signatures and reboot. After the reboot, * it is possible to identify the disks. */ if (BiosDiskEntry->Signature == Signature && BiosDiskEntry->Checksum == Checksum && !BiosDiskEntry->Recognized) { if (!DiskEntry->BiosFound) { DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber; DiskEntry->BiosFound = TRUE; BiosDiskEntry->Recognized = TRUE; } else { } } ListEntry = ListEntry->Flink; }
if (!DiskEntry->BiosFound) {#if 0 RtlFreeHeap(ProcessHeap, 0, DiskEntry); return;#else DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);#endif }
InitializeListHead(&DiskEntry->PrimaryPartListHead); InitializeListHead(&DiskEntry->LogicalPartListHead);
DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart; DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder; DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack; DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders); DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder); DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack); DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart * (ULONGLONG)DiskGeometry.TracksPerCylinder * (ULONGLONG)DiskGeometry.SectorsPerTrack;
// DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;// DiskEntry->CylinderAlignment = DiskGeometry.SectorsPerTrack * DiskGeometry.TracksPerCylinder; DiskEntry->SectorAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector; DiskEntry->CylinderAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
DPRINT("SectorCount: %I64u\n", DiskEntry->SectorCount); DPRINT("SectorAlignment: %lu\n", DiskEntry->SectorAlignment); DPRINT("CylinderAlignment: %lu\n", DiskEntry->CylinderAlignment);
DiskEntry->DiskNumber = DiskNumber; DiskEntry->Port = ScsiAddress.PortNumber; DiskEntry->PathId = ScsiAddress.PathId; DiskEntry->TargetId = ScsiAddress.TargetId; DiskEntry->Lun = ScsiAddress.Lun;
GetDriverName(DiskEntry);
InsertAscendingList(&DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
ReadLayoutBuffer(FileHandle, DiskEntry);
DPRINT("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
#ifdef DUMP_PARTITION_TABLE DumpPartitionTable(DiskEntry);#endif
if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) { if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 && DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 && DiskEntry->LayoutBuffer->PartitionEntry[0].Mbr.PartitionType != 0) { if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0) { DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack); } else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0) { DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); } else { DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart); } } else { DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector); }
/* Calculate the number of usable sectors */ /* Limit the number of usable sectors to 2^32 */ DiskEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment; DiskEntry->EndSector.QuadPart = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
if (DiskEntry->LayoutBuffer->PartitionCount == 0) { DiskEntry->NewDisk = TRUE; DiskEntry->LayoutBuffer->PartitionCount = 4;
for (i = 0; i < 4; i++) DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE; } else { for (i = 0; i < 4; i++) { AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, FALSE); }
for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4) { AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, TRUE); } }
ScanForUnpartitionedMbrDiskSpace(DiskEntry); } else if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) { /* Calculate the number of usable sectors */ DiskEntry->StartSector.QuadPart = AlignDown(DiskEntry->LayoutBuffer->Gpt.StartingUsableOffset.QuadPart / DiskEntry->BytesPerSector, DiskEntry->SectorAlignment) + (ULONGLONG)DiskEntry->SectorAlignment; DiskEntry->EndSector.QuadPart = AlignDown(DiskEntry->StartSector.QuadPart + (DiskEntry->LayoutBuffer->Gpt.UsableLength.QuadPart / DiskEntry->BytesPerSector) - 1, DiskEntry->SectorAlignment);
if (DiskEntry->LayoutBuffer->PartitionCount == 0) { DiskEntry->NewDisk = TRUE; } else { for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++) { AddGptPartitionToDisk(DiskNumber, DiskEntry, i); } }
ScanForUnpartitionedGptDiskSpace(DiskEntry); }}
NTSTATUSCreatePartitionList(VOID){ OBJECT_ATTRIBUTES ObjectAttributes; SYSTEM_DEVICE_INFORMATION Sdi; IO_STATUS_BLOCK Iosb; ULONG ReturnSize; NTSTATUS Status; ULONG DiskNumber; WCHAR Buffer[MAX_PATH]; UNICODE_STRING Name; HANDLE FileHandle;
CurrentDisk = NULL; CurrentPartition = NULL;
// BootDisk = NULL;// BootPartition = NULL;
// TempDisk = NULL;// TempPartition = NULL;// FormatState = Start;
InitializeListHead(&DiskListHead); InitializeListHead(&BiosDiskListHead);
EnumerateBiosDiskEntries();
Status = NtQuerySystemInformation(SystemDeviceInformation, &Sdi, sizeof(SYSTEM_DEVICE_INFORMATION), &ReturnSize); if (!NT_SUCCESS(Status)) { return Status; }
for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++) { StringCchPrintfW(Buffer, ARRAYSIZE(Buffer), L"\\Device\\Harddisk%d\\Partition0", DiskNumber);
RtlInitUnicodeString(&Name, Buffer);
InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
Status = NtOpenFile(&FileHandle, FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &Iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT); if (NT_SUCCESS(Status)) { AddDiskToList(FileHandle, DiskNumber);
NtClose(FileHandle); } }
// UpdateDiskSignatures(List);
// AssignDriveLetters(List);
return STATUS_SUCCESS;}
VOIDDestroyPartitionList(VOID){ PDISKENTRY DiskEntry; PBIOSDISKENTRY BiosDiskEntry; PPARTENTRY PartEntry; PLIST_ENTRY Entry;
CurrentDisk = NULL; CurrentPartition = NULL;
/* Release disk and partition info */ while (!IsListEmpty(&DiskListHead)) { Entry = RemoveHeadList(&DiskListHead); DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
/* Release driver name */ RtlFreeUnicodeString(&DiskEntry->DriverName);
/* Release primary partition list */ while (!IsListEmpty(&DiskEntry->PrimaryPartListHead)) { Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead); PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry); }
/* Release logical partition list */ while (!IsListEmpty(&DiskEntry->LogicalPartListHead)) { Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead); PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry); }
/* Release layout buffer */ if (DiskEntry->LayoutBuffer != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->LayoutBuffer);
if (DiskEntry->Description != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->Description);
if (DiskEntry->Location != NULL) RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->Location);
/* Release disk entry */ RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry); }
/* Release the bios disk info */ while (!IsListEmpty(&BiosDiskListHead)) { Entry = RemoveHeadList(&BiosDiskListHead); BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry); }}
staticVOIDGetVolumeExtents( _In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry){ DWORD dwBytesReturned = 0, dwLength, i; PVOLUME_DISK_EXTENTS pExtents; BOOL bResult; DWORD dwError;
dwLength = sizeof(VOLUME_DISK_EXTENTS); pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (pExtents == NULL) return;
bResult = DeviceIoControl(VolumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, pExtents, dwLength, &dwBytesReturned, NULL); if (!bResult) { dwError = GetLastError();
if (dwError != ERROR_MORE_DATA) { RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents); return; } else { dwLength = sizeof(VOLUME_DISK_EXTENTS) + ((pExtents->NumberOfDiskExtents - 1) * sizeof(DISK_EXTENT)); RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents); pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength); if (pExtents == NULL) { return; }
bResult = DeviceIoControl(VolumeHandle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, pExtents, dwLength, &dwBytesReturned, NULL); if (!bResult) { RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents); return; } } }
for (i = 0; i < pExtents->NumberOfDiskExtents; i++) VolumeEntry->Size.QuadPart += pExtents->Extents[i].ExtentLength.QuadPart;
VolumeEntry->pExtents = pExtents;}
staticVOIDGetVolumeType( _In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry){ FILE_FS_DEVICE_INFORMATION DeviceInfo; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status;
Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, &DeviceInfo, sizeof(FILE_FS_DEVICE_INFORMATION), FileFsDeviceInformation); if (!NT_SUCCESS(Status)) return;
switch (DeviceInfo.DeviceType) { case FILE_DEVICE_CD_ROM: case FILE_DEVICE_CD_ROM_FILE_SYSTEM: VolumeEntry->VolumeType = VOLUME_TYPE_CDROM; break;
case FILE_DEVICE_DISK: case FILE_DEVICE_DISK_FILE_SYSTEM: if (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA) VolumeEntry->VolumeType = VOLUME_TYPE_REMOVABLE; else VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION; break;
default: VolumeEntry->VolumeType = VOLUME_TYPE_UNKNOWN; break; }}
staticVOIDGetVolumeSize( _In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry){ FILE_FS_FULL_SIZE_INFORMATION SizeInfo; FILE_FS_FULL_SIZE_INFORMATION FullSizeInfo; IO_STATUS_BLOCK IoStatusBlock; NTSTATUS Status;
ZeroMemory(&FullSizeInfo, sizeof(FullSizeInfo)); Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, &FullSizeInfo, sizeof(FILE_FS_FULL_SIZE_INFORMATION), FileFsFullSizeInformation); if (NT_SUCCESS(Status)) { DPRINT("FullSizeInfo.TotalAllocationUnits %I64u\n", FullSizeInfo.TotalAllocationUnits.QuadPart); DPRINT("FullSizeInfo.SectorsPerAllocationUnit %lu\n", FullSizeInfo.SectorsPerAllocationUnit); DPRINT("FullSizeInfo.BytesPerSector %lu\n", FullSizeInfo.BytesPerSector);
VolumeEntry->TotalAllocationUnits.QuadPart = FullSizeInfo.TotalAllocationUnits.QuadPart; VolumeEntry->SectorsPerAllocationUnit = FullSizeInfo.SectorsPerAllocationUnit; VolumeEntry->BytesPerSector = FullSizeInfo.BytesPerSector; } else { ZeroMemory(&SizeInfo, sizeof(SizeInfo)); Status = NtQueryVolumeInformationFile(VolumeHandle, &IoStatusBlock, &SizeInfo, sizeof(FILE_FS_SIZE_INFORMATION), FileFsSizeInformation); if (NT_SUCCESS(Status)) { DPRINT("SizeInfo.TotalAllocationUnits %I64u\n", SizeInfo.TotalAllocationUnits.QuadPart); DPRINT("SizeInfo.SectorsPerAllocationUnit %lu\n", SizeInfo.SectorsPerAllocationUnit); DPRINT("SizeInfo.BytesPerSector %lu\n", SizeInfo.BytesPerSector);
VolumeEntry->TotalAllocationUnits.QuadPart = SizeInfo.TotalAllocationUnits.QuadPart; VolumeEntry->SectorsPerAllocationUnit = SizeInfo.SectorsPerAllocationUnit; VolumeEntry->BytesPerSector = SizeInfo.BytesPerSector; } else { DPRINT("GetVolumeSize() failed!\n"); } }}
staticPDISKENTRYGetDiskForVolume( _In_ PVOLENTRY VolumeEntry){ PLIST_ENTRY Entry; PDISKENTRY DiskEntry; INT i;
DPRINT("GetDiskFromVolume(%p)\n", VolumeEntry);
DPRINT("Extents: %p\n", VolumeEntry->pExtents); if (VolumeEntry->pExtents == NULL) return NULL;
DPRINT("Extents: %lu\n", VolumeEntry->pExtents->NumberOfDiskExtents);
Entry = DiskListHead.Flink; while (Entry != &DiskListHead) { DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++) { DPRINT("DiskNumber: %lu -- %lu\n", VolumeEntry->pExtents->Extents[i].DiskNumber, DiskEntry->DiskNumber); if (VolumeEntry->pExtents->Extents[i].DiskNumber == DiskEntry->DiskNumber) return DiskEntry; }
Entry = Entry->Flink; }
return NULL;}
staticPPARTENTRYGetPartitionForVolume( _In_ PVOLENTRY VolumeEntry){ PLIST_ENTRY Entry1, Entry2; PDISKENTRY DiskEntry; PPARTENTRY PartEntry; INT i;
DPRINT("GetPartitionFromVolume(%p)\n", VolumeEntry);
DPRINT("Extents: %p\n", VolumeEntry->pExtents); if (VolumeEntry->pExtents == NULL) return NULL;
DPRINT("Extents: %lu\n", VolumeEntry->pExtents->NumberOfDiskExtents);
Entry1 = DiskListHead.Flink; while (Entry1 != &DiskListHead) { DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++) { DPRINT("DiskNumber: %lu -- %lu\n", VolumeEntry->pExtents->Extents[i].DiskNumber, DiskEntry->DiskNumber); if (VolumeEntry->pExtents->Extents[i].DiskNumber == DiskEntry->DiskNumber) {
Entry2 = DiskEntry->PrimaryPartListHead.Flink; while (Entry2 != &DiskEntry->PrimaryPartListHead) { PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) && (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector)) return PartEntry;
Entry2 = Entry2->Flink; }
Entry2 = DiskEntry->LogicalPartListHead.Flink; while (Entry2 != &DiskEntry->LogicalPartListHead) { PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) && (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector)) return PartEntry;
Entry2 = Entry2->Flink; } } }
Entry1 = Entry1->Flink; }
return NULL;}
staticVOIDIsVolumeSystem( _In_ PVOLENTRY VolumeEntry){ WCHAR szSystemPartition[MAX_PATH]; PPARTENTRY PartEntry; HKEY hKey; DWORD dwError, dwLength;
DPRINT("IsVolumeSystem()\n");
VolumeEntry->IsSystem = FALSE;
dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_READ, &hKey); if (dwError != ERROR_SUCCESS) { DPRINT1("\n"); return; }
dwLength = sizeof(szSystemPartition); dwError = RegQueryValueExW(hKey, L"SystemPartition", NULL, NULL, (PBYTE)szSystemPartition, &dwLength); RegCloseKey(hKey);
if (dwError != ERROR_SUCCESS) { DPRINT1("\n"); return; }
DPRINT("SystemPartition: %S\n", szSystemPartition); DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
if (_wcsnicmp(szSystemPartition, VolumeEntry->DeviceName, wcslen(szSystemPartition)) == 0) { VolumeEntry->IsSystem = TRUE;
PartEntry = GetPartitionForVolume(VolumeEntry); if (PartEntry) PartEntry->IsSystem = TRUE; }}
staticVOIDIsVolumeBoot( _In_ PVOLENTRY VolumeEntry){ WCHAR szSystemDir[MAX_PATH]; PDISKENTRY DiskEntry; PPARTENTRY PartEntry;
DPRINT("IsVolumeBoot()\n");
VolumeEntry->IsBoot = FALSE;
if (VolumeEntry->DriveLetter == UNICODE_NULL) return;
GetSystemDirectoryW(szSystemDir, ARRAYSIZE(szSystemDir));
DPRINT("SystemDirectory: %S\n", szSystemDir); DPRINT("DriveLetter: %C\n", VolumeEntry->DriveLetter);
if (szSystemDir[0] == VolumeEntry->DriveLetter) { VolumeEntry->IsBoot = TRUE;
PartEntry = GetPartitionForVolume(VolumeEntry); if (PartEntry) PartEntry->IsBoot = TRUE;
DiskEntry = GetDiskForVolume(VolumeEntry); if (DiskEntry) DiskEntry->IsBoot = TRUE; }}
staticVOIDAddVolumeToList( ULONG ulVolumeNumber, PWSTR pszVolumeName){ PVOLENTRY VolumeEntry; HANDLE VolumeHandle;
DWORD dwError, dwLength; WCHAR szPathNames[MAX_PATH + 1]; WCHAR szVolumeName[MAX_PATH + 1]; WCHAR szFilesystem[MAX_PATH + 1];
DWORD CharCount = 0; size_t Index = 0;
OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING Name; IO_STATUS_BLOCK Iosb; NTSTATUS Status;
DPRINT("AddVolumeToList(%S)\n", pszVolumeName);
VolumeEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VOLENTRY)); if (VolumeEntry == NULL) return;
VolumeEntry->VolumeNumber = ulVolumeNumber; wcscpy(VolumeEntry->VolumeName, pszVolumeName);
Index = wcslen(pszVolumeName) - 1;
pszVolumeName[Index] = L'\0';
CharCount = QueryDosDeviceW(&pszVolumeName[4], VolumeEntry->DeviceName, ARRAYSIZE(VolumeEntry->DeviceName));
pszVolumeName[Index] = L'\\';
if (CharCount == 0) { RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry); return; }
DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
RtlInitUnicodeString(&Name, VolumeEntry->DeviceName);
InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL);
Status = NtOpenFile(&VolumeHandle, SYNCHRONIZE, &ObjectAttributes, &Iosb, 0, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (NT_SUCCESS(Status)) { GetVolumeType(VolumeHandle, VolumeEntry); GetVolumeExtents(VolumeHandle, VolumeEntry); GetVolumeSize(VolumeHandle, VolumeEntry); NtClose(VolumeHandle); }
if (GetVolumeInformationW(pszVolumeName, szVolumeName, MAX_PATH + 1, &VolumeEntry->SerialNumber, NULL, NULL, szFilesystem, MAX_PATH + 1)) { VolumeEntry->pszLabel = RtlAllocateHeap(RtlGetProcessHeap(), 0, (wcslen(szVolumeName) + 1) * sizeof(WCHAR)); if (VolumeEntry->pszLabel) wcscpy(VolumeEntry->pszLabel, szVolumeName);
VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(), 0, (wcslen(szFilesystem) + 1) * sizeof(WCHAR)); if (VolumeEntry->pszFilesystem) wcscpy(VolumeEntry->pszFilesystem, szFilesystem); } else { dwError = GetLastError(); if (dwError == ERROR_UNRECOGNIZED_VOLUME) { VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(), 0, (3 + 1) * sizeof(WCHAR)); if (VolumeEntry->pszFilesystem) wcscpy(VolumeEntry->pszFilesystem, L"RAW"); VolumeEntry->SerialNumber = 0; VolumeEntry->SectorsPerAllocationUnit = 1; VolumeEntry->BytesPerSector = 512; VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION; } }
if (GetVolumePathNamesForVolumeNameW(pszVolumeName, szPathNames, ARRAYSIZE(szPathNames), &dwLength)) { INT nPathLength; PWSTR pszPath = szPathNames; while (*pszPath != UNICODE_NULL) { DPRINT("PathName: %S\n", pszPath); nPathLength = wcslen(pszPath); if ((nPathLength == 3) && (iswalpha(pszPath[0])) && (pszPath[1] == L':') && (pszPath[2] == L'\\')) VolumeEntry->DriveLetter = pszPath[0];
pszPath += (nPathLength + 1); } }
IsVolumeSystem(VolumeEntry); IsVolumeBoot(VolumeEntry);
InsertTailList(&VolumeListHead, &VolumeEntry->ListEntry);}
NTSTATUSCreateVolumeList(VOID){ HANDLE hVolume = INVALID_HANDLE_VALUE; WCHAR szVolumeName[MAX_PATH]; ULONG ulVolumeNumber = 0; BOOL Success;
CurrentVolume = NULL;
InitializeListHead(&VolumeListHead);
hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName)); if (hVolume == INVALID_HANDLE_VALUE) {
return STATUS_UNSUCCESSFUL; }
AddVolumeToList(ulVolumeNumber++, szVolumeName);
for (;;) { Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName)); if (!Success) { break; }
AddVolumeToList(ulVolumeNumber++, szVolumeName); }
FindVolumeClose(hVolume);
return STATUS_SUCCESS;}
VOIDDestroyVolumeList(VOID){ PLIST_ENTRY Entry; PVOLENTRY VolumeEntry;
CurrentVolume = NULL;
/* Release disk and partition info */ while (!IsListEmpty(&VolumeListHead)) { Entry = RemoveHeadList(&VolumeListHead); VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
if (VolumeEntry->pszLabel) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
if (VolumeEntry->pszFilesystem) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
if (VolumeEntry->pExtents) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
/* Release disk entry */ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry); }}
NTSTATUSWriteMbrPartitions( _In_ PDISKENTRY DiskEntry){ NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING Name; HANDLE FileHandle; IO_STATUS_BLOCK Iosb; ULONG BufferSize; PPARTITION_INFORMATION_EX PartitionInfo; ULONG PartitionCount; PLIST_ENTRY ListEntry; PPARTENTRY PartEntry; WCHAR DstPath[MAX_PATH];
DPRINT("WriteMbrPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
/* If the disk is not dirty, there is nothing to do */ if (!DiskEntry->Dirty) return STATUS_SUCCESS;
StringCchPrintfW(DstPath, ARRAYSIZE(DstPath), L"\\Device\\Harddisk%lu\\Partition0", DiskEntry->DiskNumber); RtlInitUnicodeString(&Name, DstPath);
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenFile(&FileHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); return Status; }
// // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize // the disk in MBR or GPT format in case the disk was not initialized!! // For this we must ask the user which format to use. //
/* Save the original partition count to be restored later (see comment below) */ PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
/* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */ BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX)); Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, DiskEntry->LayoutBuffer, BufferSize, DiskEntry->LayoutBuffer, BufferSize); NtClose(FileHandle);
/* * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count, * where such a table is expected to enumerate up to 4 partitions: * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 . * Due to this we need to restore the original PartitionCount number. */ DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
/* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */ if (!NT_SUCCESS(Status)) { DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status); return Status; }
/* Update the partition numbers */
/* Update the primary partition table */ for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; ListEntry != &DiskEntry->PrimaryPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned) { ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex]; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; } }
/* Update the logical partition table */ for (ListEntry = DiskEntry->LogicalPartListHead.Flink; ListEntry != &DiskEntry->LogicalPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned) { ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex]; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; } }
/* The layout has been successfully updated, the disk is not dirty anymore */ DiskEntry->Dirty = FALSE;
return Status;}
NTSTATUSWriteGptPartitions( _In_ PDISKENTRY DiskEntry){ NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING Name; HANDLE FileHandle; IO_STATUS_BLOCK Iosb; ULONG BufferSize; WCHAR DstPath[MAX_PATH];
DPRINT("WriteGptPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
/* If the disk is not dirty, there is nothing to do */ if (!DiskEntry->Dirty) return STATUS_SUCCESS;
StringCchPrintfW(DstPath, ARRAYSIZE(DstPath), L"\\Device\\Harddisk%lu\\Partition0", DiskEntry->DiskNumber); RtlInitUnicodeString(&Name, DstPath);
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenFile(&FileHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &Iosb, 0, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); return Status; }
// // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize // the disk in MBR or GPT format in case the disk was not initialized!! // For this we must ask the user which format to use. //
/* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */ BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX)); Status = NtDeviceIoControlFile(FileHandle, NULL, NULL, NULL, &Iosb, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, DiskEntry->LayoutBuffer, BufferSize, DiskEntry->LayoutBuffer, BufferSize); NtClose(FileHandle);
/* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT_EX call succeeded */ if (!NT_SUCCESS(Status)) { DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed (Status 0x%08lx)\n", Status); return Status; }
/* The layout has been successfully updated, the disk is not dirty anymore */ DiskEntry->Dirty = FALSE;
return Status;}
staticBOOLEANIsEmptyLayoutEntry( IN PPARTITION_INFORMATION_EX PartitionInfo){ if (PartitionInfo->StartingOffset.QuadPart == 0 && PartitionInfo->PartitionLength.QuadPart == 0) { return TRUE; }
return FALSE;}
staticBOOLEANIsSamePrimaryLayoutEntry( IN PPARTITION_INFORMATION_EX PartitionInfo, IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry){ if ((PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector) && (PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)) { return TRUE; }
return FALSE;}
ULONGGetPrimaryPartitionCount( _In_ PDISKENTRY DiskEntry){ PLIST_ENTRY Entry; PPARTENTRY PartEntry; ULONG Count = 0;
for (Entry = DiskEntry->PrimaryPartListHead.Flink; Entry != &DiskEntry->PrimaryPartListHead; Entry = Entry->Flink) { PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry); if (PartEntry->IsPartitioned) Count++; }
return Count;}
staticULONGGetLogicalPartitionCount( _In_ PDISKENTRY DiskEntry){ PLIST_ENTRY ListEntry; PPARTENTRY PartEntry; ULONG Count = 0;
for (ListEntry = DiskEntry->LogicalPartListHead.Flink; ListEntry != &DiskEntry->LogicalPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry); if (PartEntry->IsPartitioned) Count++; }
return Count;}
staticBOOLEANReAllocateLayoutBuffer( _In_ PDISKENTRY DiskEntry){ PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer; ULONG NewPartitionCount; ULONG CurrentPartitionCount = 0; ULONG LayoutBufferSize; ULONG i;
DPRINT1("ReAllocateLayoutBuffer()\n");
NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
if (DiskEntry->LayoutBuffer) CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n", CurrentPartitionCount, NewPartitionCount);
if (CurrentPartitionCount == NewPartitionCount) return TRUE;
LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX)); NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DiskEntry->LayoutBuffer, LayoutBufferSize); if (NewLayoutBuffer == NULL) { DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize); return FALSE; }
NewLayoutBuffer->PartitionCount = NewPartitionCount;
/* If the layout buffer grows, make sure the new (empty) entries are written to the disk */ if (NewPartitionCount > CurrentPartitionCount) { for (i = CurrentPartitionCount; i < NewPartitionCount; i++) { NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE; } }
DiskEntry->LayoutBuffer = NewLayoutBuffer;
return TRUE;}
VOIDUpdateMbrDiskLayout( _In_ PDISKENTRY DiskEntry){ PPARTITION_INFORMATION_EX PartitionInfo; PPARTITION_INFORMATION_EX LinkInfo = NULL; PLIST_ENTRY ListEntry; PPARTENTRY PartEntry; LARGE_INTEGER HiddenSectors64; ULONG Index; ULONG PartitionNumber = 1;
DPRINT("UpdateMbrDiskLayout()\n");
/* Resize the layout buffer if necessary */ if (ReAllocateLayoutBuffer(DiskEntry) == FALSE) { DPRINT("ReAllocateLayoutBuffer() failed.\n"); return; }
DiskEntry->LayoutBuffer->PartitionStyle = PARTITION_STYLE_MBR;
/* Update the primary partition table */ Index = 0; for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; ListEntry != &DiskEntry->PrimaryPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned) { ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED);
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; PartEntry->PartitionIndex = Index;
/* Reset the current partition number only for newly-created (unmounted) partitions */ if (PartEntry->New) PartEntry->PartitionNumber = 0;
PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->Mbr.PartitionType) ? PartitionNumber : 0);
if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry)) { DPRINT1("Updating primary partition entry %lu\n", Index);
PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR; PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->Mbr.HiddenSectors = PartEntry->StartSector.LowPart; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType; PartitionInfo->Mbr.BootIndicator = PartEntry->Mbr.BootIndicator; PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType); PartitionInfo->RewritePartition = TRUE; }
if (!IsContainerPartition(PartEntry->Mbr.PartitionType)) PartitionNumber++;
Index++; } }
ASSERT(Index <= 4);
/* Update the logical partition table */ Index = 4; for (ListEntry = DiskEntry->LogicalPartListHead.Flink; ListEntry != &DiskEntry->LogicalPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (PartEntry->IsPartitioned) { ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED);
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; PartEntry->PartitionIndex = Index;
/* Reset the current partition number only for newly-created (unmounted) partitions */ if (PartEntry->New) PartEntry->PartitionNumber = 0;
PartEntry->OnDiskPartitionNumber = PartitionNumber;
DPRINT1("Updating logical partition entry %lu\n", Index);
PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR; PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->Mbr.HiddenSectors = DiskEntry->SectorAlignment; PartitionInfo->PartitionNumber = PartEntry->PartitionNumber; PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType; PartitionInfo->Mbr.BootIndicator = FALSE; PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType); PartitionInfo->RewritePartition = TRUE;
/* Fill the link entry of the previous partition entry */ if (LinkInfo != NULL) { LinkInfo->PartitionStyle = PARTITION_STYLE_MBR; LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector; LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector; HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart; LinkInfo->Mbr.HiddenSectors = HiddenSectors64.LowPart; LinkInfo->PartitionNumber = 0; LinkInfo->Mbr.PartitionType = PARTITION_EXTENDED; LinkInfo->Mbr.BootIndicator = FALSE; LinkInfo->Mbr.RecognizedPartition = FALSE; LinkInfo->RewritePartition = TRUE; }
/* Save a pointer to the link entry of the current partition entry */ LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
PartitionNumber++; Index += 4; } }
/* Wipe unused primary partition entries */ for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++) { DPRINT1("Primary partition entry %lu\n", Index);
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
if (!IsEmptyLayoutEntry(PartitionInfo)) { DPRINT1("Wiping primary partition entry %lu\n", Index);
PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR; PartitionInfo->StartingOffset.QuadPart = 0; PartitionInfo->PartitionLength.QuadPart = 0; PartitionInfo->Mbr.HiddenSectors = 0; PartitionInfo->PartitionNumber = 0; PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED; PartitionInfo->Mbr.BootIndicator = FALSE; PartitionInfo->Mbr.RecognizedPartition = FALSE; PartitionInfo->RewritePartition = TRUE; } }
/* Wipe unused logical partition entries */ for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++) { if (Index % 4 >= 2) { DPRINT1("Logical partition entry %lu\n", Index);
PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
if (!IsEmptyLayoutEntry(PartitionInfo)) { DPRINT1("Wiping partition entry %lu\n", Index);
PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR; PartitionInfo->StartingOffset.QuadPart = 0; PartitionInfo->PartitionLength.QuadPart = 0; PartitionInfo->Mbr.HiddenSectors = 0; PartitionInfo->PartitionNumber = 0; PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED; PartitionInfo->Mbr.BootIndicator = FALSE; PartitionInfo->Mbr.RecognizedPartition = FALSE; PartitionInfo->RewritePartition = TRUE; } } }
DiskEntry->Dirty = TRUE;}
VOIDUpdateGptDiskLayout( _In_ PDISKENTRY DiskEntry, _In_ BOOL DeleteEntry){ PLIST_ENTRY ListEntry; PPARTENTRY PartEntry; PPARTITION_INFORMATION_EX PartitionInfo; ULONG Count, Index;
DPRINT("UpdateGptDiskLayout()\n");
/* Count used partition entries */ Count = 0; for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; ListEntry != &DiskEntry->PrimaryPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) Count++; }
DPRINT("Used partition entries: %lu\n", Count);
if (DeleteEntry) Count++;
/* Reallocate the layout buffer */ if (Count != DiskEntry->LayoutBuffer->PartitionCount) { PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer; ULONG NewLayoutBufferSize;
NewLayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + ((Count - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX)); NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, DiskEntry->LayoutBuffer, NewLayoutBufferSize); if (NewLayoutBuffer == NULL) { DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", NewLayoutBufferSize); return; }
NewLayoutBuffer->PartitionCount = Count; DiskEntry->LayoutBuffer = NewLayoutBuffer; }
/* Fill the new layout buffer */ Index = 0; for (ListEntry = DiskEntry->PrimaryPartListHead.Flink; ListEntry != &DiskEntry->PrimaryPartListHead; ListEntry = ListEntry->Flink) { PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID)) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; PartEntry->PartitionIndex = Index;
DPRINT("Updating primary partition entry %lu\n", Index); PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT; PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector; PartitionInfo->PartitionNumber = Index + 1; PartitionInfo->RewritePartition = TRUE; CopyMemory(&PartitionInfo->Gpt.PartitionType, &PartEntry->Gpt.PartitionType, sizeof(GUID)); CopyMemory(&PartitionInfo->Gpt.PartitionId, &PartEntry->Gpt.PartitionId, sizeof(GUID)); PartitionInfo->Gpt.Attributes = PartEntry->Gpt.Attributes; ZeroMemory(&PartitionInfo->Gpt.Name, 36 * sizeof(WCHAR)); /* ??? */
PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
Index++; } }
if (DeleteEntry) { PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index]; ZeroMemory(PartitionInfo, sizeof(PARTITION_INFORMATION_EX)); PartitionInfo->RewritePartition = TRUE; }}
PPARTENTRYGetPrevUnpartitionedEntry( _In_ PPARTENTRY PartEntry){ PDISKENTRY DiskEntry = PartEntry->DiskEntry; PPARTENTRY PrevPartEntry; PLIST_ENTRY ListHead;
if (PartEntry->LogicalPartition) ListHead = &DiskEntry->LogicalPartListHead; else ListHead = &DiskEntry->PrimaryPartListHead;
if (PartEntry->ListEntry.Blink != ListHead) { PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink, PARTENTRY, ListEntry); if (!PrevPartEntry->IsPartitioned) { ASSERT(PrevPartEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED); return PrevPartEntry; } }
return NULL;}
PPARTENTRYGetNextUnpartitionedEntry( _In_ PPARTENTRY PartEntry){ PDISKENTRY DiskEntry = PartEntry->DiskEntry; PPARTENTRY NextPartEntry; PLIST_ENTRY ListHead;
if (PartEntry->LogicalPartition) ListHead = &DiskEntry->LogicalPartListHead; else ListHead = &DiskEntry->PrimaryPartListHead;
if (PartEntry->ListEntry.Flink != ListHead) { NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink, PARTENTRY, ListEntry); if (!NextPartEntry->IsPartitioned) { ASSERT(NextPartEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED); return NextPartEntry; } }
return NULL;}
NTSTATUSDismountVolume( _In_ PPARTENTRY PartEntry){ NTSTATUS Status; NTSTATUS LockStatus; UNICODE_STRING Name; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; HANDLE PartitionHandle; WCHAR Buffer[MAX_PATH];
/* Check whether the partition is valid and was mounted by the system */ if (PartEntry->DiskEntry->PartitionStyle == PARTITION_STYLE_MBR) { if (!PartEntry->IsPartitioned || IsContainerPartition(PartEntry->Mbr.PartitionType) || !IsRecognizedPartition(PartEntry->Mbr.PartitionType) || PartEntry->FormatState == UnknownFormat || // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means // it has been usually mounted with RawFS and thus needs to be dismounted./* !*PartEntry->FileSystem || */ PartEntry->PartitionNumber == 0) { /* The partition is not mounted, so just return success */ return STATUS_SUCCESS; }
ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED); } else if (PartEntry->DiskEntry->PartitionStyle == PARTITION_STYLE_GPT) { if (!PartEntry->IsPartitioned || IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID) || (PartEntry->FormatState == UnknownFormat)) { /* The partition is not mounted, so just return success */ return STATUS_SUCCESS; } }
/* Open the volume */ StringCchPrintfW(Buffer, ARRAYSIZE(Buffer), L"\\Device\\Harddisk%lu\\Partition%lu", PartEntry->DiskEntry->DiskNumber, PartEntry->PartitionNumber); RtlInitUnicodeString(&Name, Buffer);
InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenFile(&PartitionHandle, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status); return Status; }
/* Lock the volume */ LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(LockStatus)) { DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus); }
/* Dismount the volume */ Status = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status); }
/* Unlock the volume */ LockStatus = NtFsControlFile(PartitionHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); if (!NT_SUCCESS(LockStatus)) { DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus); }
/* Close the volume */ NtClose(PartitionHandle);
return Status;}
PVOLENTRYGetVolumeFromPartition( _In_ PPARTENTRY PartEntry){ PLIST_ENTRY Entry; PVOLENTRY VolumeEntry; ULONG i;
if ((PartEntry == NULL) || (PartEntry->DiskEntry == NULL)) return NULL;
Entry = VolumeListHead.Flink; while (Entry != &VolumeListHead) { VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
if (VolumeEntry->pExtents == NULL) return NULL;
for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++) { if (VolumeEntry->pExtents->Extents[i].DiskNumber == PartEntry->DiskEntry->DiskNumber) { if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) && (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector)) return VolumeEntry; } }
Entry = Entry->Flink; }
return NULL;}
VOIDRemoveVolume( _In_ PVOLENTRY VolumeEntry){ if (VolumeEntry == NULL) return;
if (VolumeEntry == CurrentVolume) CurrentVolume = NULL;
RemoveEntryList(&VolumeEntry->ListEntry);
if (VolumeEntry->pszLabel) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
if (VolumeEntry->pszFilesystem) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
if (VolumeEntry->pExtents) RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
/* Release disk entry */ RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);}
/* EOF */