00001
#include "precomp.h"
00002
#pragma hdrstop
00003
00004 #define READ_SIZE 65536
00005
00006 typedef struct {
00007 UCHAR IntelNearJumpCommand[1];
00008 UCHAR BootStrapJumpOffset[2];
00009 UCHAR OemData[8];
00010 UCHAR BytesPerSector[2];
00011 UCHAR SectorsPerCluster[1];
00012 UCHAR ReservedSectors[2];
00013 UCHAR Fats[1];
00014 UCHAR RootEntries[2];
00015 UCHAR Sectors[2];
00016 UCHAR Media[1];
00017 UCHAR SectorsPerFat[2];
00018 UCHAR SectorsPerTrack[2];
00019 UCHAR Heads[2];
00020 UCHAR HiddenSectors[4];
00021 UCHAR LargeSectors[4];
00022 UCHAR PhysicalDrive[1];
00023 UCHAR CurrentHead[1];
00024 UCHAR Signature[1];
00025 UCHAR SerialNumber[4];
00026 UCHAR Label[11];
00027 UCHAR SystemIdText[8];
00028 }
UNALIGNED_SECTOR_ZERO, *
PUNALIGNED_SECTOR_ZERO;
00029
00030
00031 #define CSEC_FAT32MEG 65536
00032 #define CSEC_FAT16BIT 32680
00033 #define SYSID_FAT12BIT 1
00034 #define SYSID_FAT16BIT 4
00035 #define SYSID_FAT32MEG 6
00036 #define MIN_CLUS_BIG 4085 // Minimum clusters for a big FAT.
00037 #define MAX_CLUS_BIG 65525 // Maximum + 1 clusters for big FAT.
00038
00039
00040
00041
ARC_STATUS
00042 FmtIsFatPartition(
00043 IN ULONG PartitionId,
00044 IN ULONG SectorSize,
00045 OUT PBOOLEAN IsFatPartition
00046 )
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 {
00066 PUCHAR
Buffer;
00067
ARC_STATUS r;
00068
00069
if (!(
Buffer =
AllocateMemory(
SectorSize*2))) {
00070
return ENOMEM;
00071 }
00072
00073 r =
LowReadSectors(PartitionId,
SectorSize, 0, 2,
Buffer);
00074
00075
if (r !=
ESUCCESS) {
00076
FreeMemory(
Buffer);
00077
return r;
00078 }
00079
00080 *IsFatPartition =
Buffer[510] == 0x55 &&
00081
Buffer[511] == 0xAA &&
00082
Buffer[0x10] != 0 &&
00083
Buffer[0x15] ==
Buffer[
SectorSize] &&
00084
Buffer[
SectorSize + 1] == 0xFF &&
00085
Buffer[
SectorSize + 2] == 0xFF;
00086
00087
FreeMemory(
Buffer);
00088
return ESUCCESS;
00089 }
00090
00091
00092
ARC_STATUS
00093 FmtIsFat(
00094 IN PCHAR PartitionPath,
00095 OUT PBOOLEAN IsFatPartition
00096 )
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 {
00115 ULONG partition_id;
00116
ARC_STATUS r;
00117 ULONG total_sectors, sector_size, sec_per_track, heads;
00118
00119 r =
LowGetPartitionGeometry(PartitionPath, &total_sectors, §or_size,
00120 &sec_per_track, &heads);
00121
00122
if (r !=
ESUCCESS) {
00123
return r;
00124 }
00125
00126 r =
ArcOpen(PartitionPath,
ArcOpenReadOnly, &partition_id);
00127
00128
if (r !=
ESUCCESS) {
00129
return r;
00130 }
00131
00132 r =
FmtIsFatPartition(partition_id, sector_size, IsFatPartition);
00133
00134
if (r !=
ESUCCESS) {
00135
ArcClose(partition_id);
00136
return r;
00137 }
00138
00139
return ArcClose(partition_id);
00140 }
00141
00142
00143
00144
00145
USHORT
00146 ComputeSecPerCluster(
00147 IN ULONG NumSectors,
00148 IN BOOLEAN SmallFat
00149 )
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 {
00167 ULONG threshold;
00168
USHORT sec_per_clus;
00169
USHORT min_sec_per_clus;
00170
00171 threshold = SmallFat ?
MIN_CLUS_BIG :
MAX_CLUS_BIG;
00172 sec_per_clus = 1;
00173
00174
while (NumSectors >= threshold) {
00175 sec_per_clus *= 2;
00176 threshold *= 2;
00177 }
00178
00179
if (SmallFat) {
00180 min_sec_per_clus = 8;
00181 }
else {
00182 min_sec_per_clus = 4;
00183 }
00184
00185
return max(sec_per_clus, min_sec_per_clus);
00186 }
00187
00188
00189 ULONG
00190 ComputeNewSerialNumber(
00191 IN ULONG Seed
00192 )
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 {
00209 PUCHAR p;
00210 ULONG i;
00211
00212 p = (PUCHAR) &
Seed;
00213
00214
for (i = 0; i <
sizeof(ULONG); i++) {
00215
00216
Seed += p[i];
00217
Seed = (
Seed >> 2) + (
Seed << 30);
00218 }
00219
00220
return Seed;
00221 }
00222
00223
00224
VOID
00225 EditFat(
00226 IN USHORT ClusterNumber,
00227 IN USHORT ClusterEntry,
00228 IN OUT PUCHAR Fat,
00229 IN BOOLEAN SmallFat
00230 )
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 {
00250 ULONG
n;
00251
00252
if (SmallFat) {
00253
00254
n = ClusterNumber*3;
00255
if (
n%2) {
00256 Fat[
n/2] = (UCHAR) ((Fat[
n/2]&0x0F) | ((ClusterEntry&0x000F)<<4));
00257 Fat[
n/2 + 1] = (UCHAR) ((ClusterEntry&0x0FF0)>>4);
00258 }
else {
00259 Fat[
n/2] = (UCHAR) (ClusterEntry&0x00FF);
00260 Fat[
n/2 + 1] = (UCHAR) ((Fat[
n/2 + 1]&0xF0) |
00261 ((ClusterEntry&0x0F00)>>8));
00262 }
00263
00264 }
else {
00265
00266 ((
PUSHORT) Fat)[ClusterNumber] = ClusterEntry;
00267
00268 }
00269 }
00270
00271
00272
ARC_STATUS
00273 FmtFillFormatBuffer(
00274 IN ULONG NumberOfSectors,
00275 IN ULONG SectorSize,
00276 IN ULONG SectorsPerTrack,
00277 IN ULONG NumberOfHeads,
00278 IN ULONG NumberOfHiddenSectors,
00279 OUT PVOID FormatBuffer,
00280 IN ULONG FormatBufferSize,
00281 OUT PULONG SuperAreaSize,
00282 IN ULONG TimeSeed,
00283 IN PULONG BadSectorsList,
00284 IN ULONG NumberOfBadSectors
00285 )
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317 {
00318
PUNALIGNED_SECTOR_ZERO psecz;
00319 PUCHAR puchar;
00320
USHORT tmp_ushort;
00321 ULONG tmp_ulong;
00322 BOOLEAN small_fat;
00323 ULONG num_sectors;
00324 ULONG partition_id;
00325 ULONG sec_per_fat;
00326 ULONG sec_per_root;
00327 ULONG sec_per_clus;
00328 ULONG i;
00329 ULONG sec_per_sa;
00330
00331
00332
00333 memset(FormatBuffer, 0, (
unsigned int) FormatBufferSize);
00334
00335
00336
00337
00338
if (!FormatBuffer || FormatBufferSize <
SectorSize) {
00339
return ENOMEM;
00340 }
00341
00342
00343 num_sectors = NumberOfSectors;
00344
00345
00346 partition_id = num_sectors <
CSEC_FAT16BIT ?
SYSID_FAT12BIT :
00347 num_sectors <
CSEC_FAT32MEG ?
SYSID_FAT16BIT :
00348
SYSID_FAT32MEG;
00349
00350
00351 small_fat = (BOOLEAN) (partition_id ==
SYSID_FAT12BIT);
00352
00353
00354 psecz = (
PUNALIGNED_SECTOR_ZERO) FormatBuffer;
00355 puchar = (PUCHAR) FormatBuffer;
00356
00357
00358 psecz->IntelNearJumpCommand[0] = 0xEB;
00359 tmp_ushort = 0x903C;
00360 memcpy(psecz->BootStrapJumpOffset, &tmp_ushort,
sizeof(
USHORT));
00361
00362
00363 memcpy(psecz->OemData,
"WINNT1.0", 8);
00364
00365
00366 tmp_ushort = (
USHORT)
SectorSize;
00367 memcpy(psecz->BytesPerSector, &tmp_ushort,
sizeof(
USHORT));
00368
00369
00370 sec_per_clus =
ComputeSecPerCluster(num_sectors, small_fat);
00371
if (sec_per_clus > 128) {
00372
00373
00374
return E2BIG;
00375 }
00376 psecz->SectorsPerCluster[0] = (UCHAR) sec_per_clus;
00377
00378
00379 tmp_ushort = 1;
00380 memcpy(psecz->ReservedSectors, &tmp_ushort,
sizeof(
USHORT));
00381
00382
00383 psecz->Fats[0] = 2;
00384
00385
00386 tmp_ushort = 512;
00387 memcpy(psecz->RootEntries, &tmp_ushort,
sizeof(
USHORT));
00388 sec_per_root = (512*32 - 1)/
SectorSize + 1;
00389
00390
00391
if (num_sectors >= 1<<16) {
00392 tmp_ushort = 0;
00393 tmp_ulong = num_sectors;
00394 }
else {
00395 tmp_ushort = (
USHORT) num_sectors;
00396 tmp_ulong = 0;
00397 }
00398 memcpy(psecz->Sectors, &tmp_ushort,
sizeof(
USHORT));
00399 memcpy(psecz->LargeSectors, &tmp_ulong,
sizeof(ULONG));
00400
00401
00402 psecz->Media[0] = 0xF8;
00403
00404
00405
if (small_fat) {
00406 sec_per_fat = num_sectors/(2 +
SectorSize*sec_per_clus*2/3);
00407 }
else {
00408 sec_per_fat = num_sectors/(2 +
SectorSize*sec_per_clus/2);
00409 }
00410 sec_per_fat++;
00411 tmp_ushort = (
USHORT) sec_per_fat;
00412 memcpy(psecz->SectorsPerFat, &tmp_ushort,
sizeof(
USHORT));
00413
00414
00415 tmp_ushort = (
USHORT) SectorsPerTrack;
00416 memcpy(psecz->SectorsPerTrack, &tmp_ushort,
sizeof(
USHORT));
00417
00418
00419 tmp_ushort = (
USHORT) NumberOfHeads;
00420 memcpy(psecz->Heads, &tmp_ushort,
sizeof(
USHORT));
00421
00422
00423 memcpy(psecz->HiddenSectors, &NumberOfHiddenSectors,
sizeof(ULONG));
00424
00425
00426 psecz->PhysicalDrive[0] = 0x80;
00427
00428
00429 psecz->Signature[0] = 0x29;
00430
00431
00432 tmp_ulong =
ComputeNewSerialNumber(TimeSeed);
00433 memcpy(psecz->SerialNumber, &tmp_ulong,
sizeof(ULONG));
00434
00435
00436 memcpy(psecz->SystemIdText,
"FAT ", 8);
00437
00438
00439 puchar[510] = 0x55;
00440 puchar[511] = 0xAA;
00441
00442
00443
00444
00445
00446 sec_per_sa = 1 + 2*sec_per_fat + sec_per_root;
00447 *SuperAreaSize =
SectorSize*sec_per_sa;
00448
if (*SuperAreaSize > FormatBufferSize) {
00449
return ENOMEM;
00450 }
00451
00452
00453
00454
00455 puchar[
SectorSize] = 0xF8;
00456 puchar[
SectorSize + 1] = 0xFF;
00457 puchar[
SectorSize + 2] = 0xFF;
00458
00459
if (!small_fat) {
00460 puchar[
SectorSize + 3] = 0xFF;
00461 }
00462
00463
00464
for (i = 0; i < NumberOfBadSectors; i++) {
00465
00466
if (BadSectorsList[i] < sec_per_sa) {
00467
00468
return EIO;
00469 }
00470
00471
if (BadSectorsList[i] >= num_sectors) {
00472
00473
return EINVAL;
00474 }
00475
00476
00477 tmp_ushort = (
USHORT)
00478 ((BadSectorsList[i] - sec_per_sa)/sec_per_clus + 2);
00479
00480
EditFat(tmp_ushort, (
USHORT) 0xFFF7, &puchar[
SectorSize], small_fat);
00481 }
00482
00483
00484
00485
00486 memcpy(&puchar[
SectorSize*(1 + sec_per_fat)],
00487 &puchar[
SectorSize],
00488 (
unsigned int)
SectorSize*sec_per_fat);
00489
00490
return ESUCCESS;
00491 }
00492
00493
00494
ARC_STATUS
00495 FmtVerifySectors(
00496 IN ULONG PartitionId,
00497 IN ULONG NumberOfSectors,
00498 IN ULONG SectorSize,
00499 OUT PULONG* BadSectorsList,
00500 OUT PULONG NumberOfBadSectors
00501 )
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 {
00524 ULONG num_read_sec;
00525 PVOID read_buffer;
00526 ULONG i, j;
00527 PULONG bad_sec_buf;
00528 ULONG max_num_bad;
00529
ARC_STATUS r;
00530 ULONG percent;
00531
00532
if (!(read_buffer =
AllocateMemory(
READ_SIZE))) {
00533
return ENOMEM;
00534 }
00535
00536 max_num_bad = 100;
00537
if (!(bad_sec_buf = (PULONG)
AllocateMemory(max_num_bad*
sizeof(ULONG)))) {
00538
FreeMemory(read_buffer);
00539
return ENOMEM;
00540 }
00541
00542 *NumberOfBadSectors = 0;
00543
00544 num_read_sec =
READ_SIZE/
SectorSize;
00545
00546
00547 percent = 1;
00548
for (i = 0; i < NumberOfSectors; i += num_read_sec) {
00549
00550
if (percent != i*100/NumberOfSectors) {
00551 percent = i*100/NumberOfSectors;
00552
AlPrint(
"%s%d percent formatted.\r",
MSGMARGIN, percent);
00553 }
00554
00555
if (i + num_read_sec > NumberOfSectors) {
00556 num_read_sec = NumberOfSectors - i;
00557 }
00558
00559 r =
LowReadSectors(PartitionId,
SectorSize, i,
00560 num_read_sec, read_buffer);
00561
00562
if (r !=
ESUCCESS) {
00563
00564
for (j = 0; j < num_read_sec; j++) {
00565
00566 r =
LowReadSectors(PartitionId,
SectorSize, i+j, 1,
00567 read_buffer);
00568
00569
if (r !=
ESUCCESS) {
00570
00571
if (*NumberOfBadSectors == max_num_bad) {
00572
00573 max_num_bad += 100;
00574
if (!(bad_sec_buf = (PULONG)
00575
ReallocateMemory(bad_sec_buf,
00576 max_num_bad*
sizeof(ULONG)))) {
00577
00578
FreeMemory(read_buffer);
00579
FreeMemory(bad_sec_buf);
00580
return ENOMEM;
00581 }
00582 }
00583
00584 bad_sec_buf[(*NumberOfBadSectors)++] = i + j;
00585 }
00586 }
00587 }
00588 }
00589
00590
AlPrint(
"%s100 percent formatted.\r\n",
MSGMARGIN);
00591
00592 *BadSectorsList = bad_sec_buf;
00593
00594
FreeMemory(read_buffer);
00595
00596
return ESUCCESS;
00597 }
00598
00599
00600
ARC_STATUS
00601 FmtFatFormat(
00602 IN PCHAR PartitionPath,
00603 IN ULONG HiddenSectorCount
00604 )
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 {
00623 ULONG num_sectors;
00624 ULONG sector_size;
00625 ULONG sec_per_track;
00626 ULONG heads;
00627 ULONG hidden_sectors;
00628 PULONG bad_sectors;
00629 ULONG num_bad_sectors;
00630 PVOID format_buffer;
00631 ULONG max_sec_per_sa;
00632 ULONG super_area_size;
00633
ARC_STATUS r;
00634 ULONG partition_id;
00635 ULONG time_seed;
00636 PTIME_FIELDS ptime_fields;
00637
00638
00639 r =
LowGetPartitionGeometry(PartitionPath, &num_sectors,
00640 §or_size, &sec_per_track, &heads);
00641
00642
if (r !=
ESUCCESS) {
00643
return r;
00644 }
00645
00646 hidden_sectors = HiddenSectorCount;
00647
00648 r =
ArcOpen(PartitionPath,
ArcOpenReadWrite, &partition_id);
00649
00650
if (r !=
ESUCCESS) {
00651
return r;
00652 }
00653
00654 bad_sectors =
NULL;
00655
00656 r =
FmtVerifySectors(partition_id, num_sectors, sector_size,
00657 &bad_sectors, &num_bad_sectors);
00658
00659
if (r !=
ESUCCESS) {
00660
ArcClose(partition_id);
00661
return r;
00662 }
00663
00664 max_sec_per_sa = 1 +
00665 2*((2*65536 - 1)/sector_size + 1) +
00666 ((512*32 - 1)/sector_size + 1);
00667
00668 ptime_fields =
ArcGetTime();
00669
00670 time_seed = (ptime_fields->Year - 1970)*366*24*60*60 +
00671 (ptime_fields->Month)*31*24*60*60 +
00672 (ptime_fields->Day)*24*60*60 +
00673 (ptime_fields->Hour)*60*60 +
00674 (ptime_fields->Minute)*60 +
00675 (ptime_fields->Second);
00676
00677
if (!(format_buffer =
AllocateMemory(max_sec_per_sa*sector_size))) {
00678
00679
if (bad_sectors) {
00680
FreeMemory(bad_sectors);
00681 }
00682
ArcClose(partition_id);
00683
return ENOMEM;
00684 }
00685
00686 r =
FmtFillFormatBuffer(num_sectors,
00687 sector_size,
00688 sec_per_track,
00689 heads,
00690 hidden_sectors,
00691 format_buffer,
00692 max_sec_per_sa*sector_size,
00693 &super_area_size,
00694 time_seed,
00695 bad_sectors,
00696 num_bad_sectors);
00697
00698
00699
if (bad_sectors) {
00700
FreeMemory(bad_sectors);
00701 }
00702
00703
if (r !=
ESUCCESS) {
00704
ArcClose(partition_id);
00705
FreeMemory(format_buffer);
00706
return r;
00707 }
00708
00709 r =
LowWriteSectors(partition_id, sector_size, 0,
00710 super_area_size/sector_size, format_buffer);
00711
00712
FreeMemory(format_buffer);
00713
00714
if (r !=
ESUCCESS) {
00715
ArcClose(partition_id);
00716
return r;
00717 }
00718
00719
return ArcClose(partition_id);
00720 }
00721
00722
00723
ARC_STATUS
00724 FmtQueryFatPartitionList(
00725 OUT PCHAR** FatPartitionList,
00726 OUT PULONG ListLength
00727 )
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 {
00747
CONFIGURATION_TYPE config_type;
00748
ARC_STATUS r;
00749 PCHAR* peripheral_list;
00750 ULONG peripheral_list_length;
00751 ULONG i, j;
00752 ULONG num_partitions;
00753
CHAR partition_buf[21];
00754 ULONG partition_id;
00755 PCHAR* fat_partition_list;
00756 ULONG fat_partition_list_length;
00757 BOOLEAN is_fat;
00758 PCHAR partition_name;
00759
00760
00761
00762
00763 config_type =
DiskPeripheral;
00764 r =
LowQueryPathList(
NULL, &config_type, &peripheral_list,
00765 &peripheral_list_length);
00766
00767
if (r !=
ESUCCESS) {
00768
return r;
00769 }
00770
00771
00772
00773
00774
00775
00776
00777 num_partitions = 0;
00778
for (i = 0; i < peripheral_list_length; i++) {
00779
00780 partition_name =
AllocateMemory(
strlen(peripheral_list[i]) + 21);
00781
00782
if (!partition_name) {
00783
LowFreePathList(peripheral_list, peripheral_list_length);
00784
return ENOMEM;
00785 }
00786
00787
for (j = 1; ; j++) {
00788
00789 strcpy(partition_name, peripheral_list[i]);
00790
sprintf(partition_buf,
"partition(%d)", j);
00791 strcat(partition_name, partition_buf);
00792
00793 r =
ArcOpen(partition_name,
ArcOpenReadOnly, &partition_id);
00794
00795
if (r !=
ESUCCESS) {
00796
break;
00797 }
00798
00799 num_partitions++;
00800
00801 r =
ArcClose(partition_id);
00802
00803
if (r !=
ESUCCESS) {
00804
LowFreePathList(peripheral_list, peripheral_list_length);
00805
FreeMemory(partition_name);
00806
return r;
00807 }
00808 }
00809
00810
FreeMemory(partition_name);
00811 }
00812
00813
00814
00815
00816
00817
00818
00819 fat_partition_list = (PCHAR*)
AllocateMemory(num_partitions*
sizeof(PCHAR));
00820
00821
if (!fat_partition_list) {
00822
LowFreePathList(peripheral_list, peripheral_list_length);
00823
return ENOMEM;
00824 }
00825
00826
for (i = 0; i < num_partitions; i++) {
00827 fat_partition_list[i] =
NULL;
00828 }
00829
00830 fat_partition_list_length = 0;
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
for (i = 0; i < peripheral_list_length; i++) {
00841
00842 partition_name =
AllocateMemory(
strlen(peripheral_list[i]) + 21);
00843
00844
if (!partition_name) {
00845
LowFreePathList(peripheral_list, peripheral_list_length);
00846
LowFreePathList(fat_partition_list, fat_partition_list_length);
00847
return ENOMEM;
00848 }
00849
00850
for (j = 1; ; j++) {
00851
00852 strcpy(partition_name, peripheral_list[i]);
00853
sprintf(partition_buf,
"partition(%d)", j);
00854 strcat(partition_name, partition_buf);
00855
00856 r =
ArcOpen(partition_name,
ArcOpenReadOnly, &partition_id);
00857
00858
if (r !=
ESUCCESS) {
00859
break;
00860 }
00861
00862 r =
ArcClose(partition_id);
00863
00864
if (r !=
ESUCCESS) {
00865
LowFreePathList(peripheral_list, peripheral_list_length);
00866
LowFreePathList(fat_partition_list, fat_partition_list_length);
00867
FreeMemory(partition_name);
00868
return r;
00869 }
00870
00871 r =
FmtIsFat(partition_name, &is_fat);
00872
00873
if (r !=
ESUCCESS) {
00874
LowFreePathList(peripheral_list, peripheral_list_length);
00875
LowFreePathList(fat_partition_list, fat_partition_list_length);
00876
FreeMemory(partition_name);
00877
return r;
00878 }
00879
00880
if (is_fat) {
00881
00882
if (fat_partition_list_length == num_partitions) {
00883
00884
LowFreePathList(peripheral_list, peripheral_list_length);
00885
LowFreePathList(fat_partition_list, fat_partition_list_length);
00886
FreeMemory(partition_name);
00887
return EIO;
00888 }
00889
00890 fat_partition_list[fat_partition_list_length] =
00891
AllocateMemory(
strlen(partition_name) + 1);
00892
00893
if (!fat_partition_list[fat_partition_list_length]) {
00894
LowFreePathList(peripheral_list, peripheral_list_length);
00895
LowFreePathList(fat_partition_list, fat_partition_list_length);
00896
FreeMemory(partition_name);
00897
return ENOMEM;
00898 }
00899
00900 strcpy(fat_partition_list[fat_partition_list_length], partition_name);
00901
00902 fat_partition_list_length++;
00903 }
00904 }
00905
00906
FreeMemory(partition_name);
00907 }
00908
00909
LowFreePathList(peripheral_list, peripheral_list_length);
00910
00911 *FatPartitionList = fat_partition_list;
00912 *ListLength = fat_partition_list_length;
00913
00914
return ESUCCESS;
00915 }
00916
00917
00918
ARC_STATUS
00919 FmtFreeFatPartitionList(
00920 IN OUT PCHAR* FatPartitionList,
00921 IN ULONG ListLength
00922 )
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940 {
00941
return LowFreePathList(FatPartitionList, ListLength);
00942 }