mapping partitions starting from PhysicalDrive

后端 未结 3 1229
慢半拍i
慢半拍i 2021-01-17 03:11

I want to map all partitions from all drives in Windows (the ones who are not mapped already). I mean I want to assign to each of them drive letters. I know that you can do

相关标签:
3条回答
  • 2021-01-17 03:33

    Maybe my Change DriveLetter commandline tool can help you, at least you can start it with commandline parameters and see if it lists all volumes you expect.

    This link might also be useful: Converting a volume name to a devicename

    0 讨论(0)
  • 2021-01-17 03:45

    I did it :) I made a program who adds or removes drive letters when it's started - if one or more storage drives were added or removed from the computer:

    program MapDrives;
    
    uses Windows;
    
    type
       TPARTITION_INFORMATION = record
          StartingOffset: _LARGE_INTEGER; //TLargeInteger;
          PartitionLength: _LARGE_INTEGER; //TLargeInteger;
          HiddenSectors: DWORD;
          PartitionNumber: DWORD;
          PartitionType: BYTE;
          BootIndicator: BOOLEAN;
          RecognizedPartition: BOOLEAN;
          RewritePartition: BOOLEAN;
       end;
    
    function IntToStr(Value: Integer): string;
    begin
       if Value < 10 then
          Result := Char(Value + 48)
       else
          Result := Char(Value div 10 + 48) + Char(Value + 48);
    end;
    
    function GetNextAvailableLetter: AnsiChar;
    var Drives, mask: DWord;
       i: Integer;
    begin
       Drives := GetLogicalDrives;
       mask := 4;
       Result := 'Z';
       for i := 3 to 26 do //C to Z
       begin
          if mask and Drives = 0 then
          begin
             Result := AnsiChar(64 + i);
             Exit;
          end;
          mask := mask shl 1;
       end;
    end;
    
    
    const IOCTL_DISK_GET_PARTITION_INFO = $0074004;
    
    var i, j, k: Integer;
       H: THandle;
       dwBytesReturned: DWORD;
       BreakCycle, DoMount: Boolean;
       NextLetter: AnsiChar;
       PartitionInformation: TPARTITION_INFORMATION;
       PartitionsInformation: array of TPARTITION_INFORMATION;
       Drives, mask: DWord;
       OldMode: UINT;
    
    begin
       OldMode := SetErrorMode(SEM_FAILCRITICALERRORS); //so it shouldn't ask to insert CD or card
    
       //gets informations about already mounted partitions
       SetLength(PartitionsInformation, 0);
       Drives := GetLogicalDrives;
       mask := 4;
       for i := 3 to 26 do //C to Z
       begin
          if mask and Drives <> 0 then
          begin
             H := CreateFile(PAnsiChar('\\.\' + Char(64 + i) + ':'), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
             if H <> INVALID_HANDLE_VALUE then
             begin
                SetLength(PartitionsInformation, Length(PartitionsInformation) + 1);
                DeviceIoControl(H, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @PartitionsInformation[High(PartitionsInformation)], SizeOf(TPARTITION_INFORMATION), dwBytesReturned, nil);
                CloseHandle(H);
             end
             else     //removes unaccessible drives
                DefineDosDevice(DDD_REMOVE_DEFINITION or DDD_RAW_TARGET_PATH, PAnsiChar(string(Char(64 + i) + ':')), nil);
          end;
          mask := mask shl 1;
       end;
    
       for i := 0 to 99 do
       begin
          H := CreateFile(PAnsiChar('\\.\PhysicalDrive' + IntToStr(i)), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
          if H = INVALID_HANDLE_VALUE then //no more hdd's
             Break;
          CloseHandle(H);
          for j := 1 to 20 do
          begin
             BreakCycle := False;
             NextLetter := GetNextAvailableLetter;
             DefineDosDevice(DDD_RAW_TARGET_PATH or DDD_NO_BROADCAST_SYSTEM, PAnsiChar(string(NextLetter + ':')), PAnsiChar('\Device\Harddisk' + IntToStr(i) + '\Partition' + IntToStr(j)));
             DoMount := True;
             H := CreateFile(PAnsiChar('\\.\' + NextLetter + ':'), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
             if H = INVALID_HANDLE_VALUE then //no more partitions
                BreakCycle := True
             else
             begin
                PartitionInformation.PartitionType := 0;
                DeviceIoControl(H, IOCTL_DISK_GET_PARTITION_INFO, nil, 0, @PartitionInformation, SizeOf(TPARTITION_INFORMATION), dwBytesReturned, nil);
                DoMount := PartitionInformation.PartitionType in [0, 1, 6, 7, 11, 12, 114];
                CloseHandle(H);
             end;
             if DoMount then
             begin
                for k := 0 to High(PartitionsInformation) do  //compare with already mounted partitions
                   if (PartitionsInformation[k].StartingOffset.LowPart = PartitionInformation.StartingOffset.LowPart) and
                      (PartitionsInformation[k].StartingOffset.HighPart = PartitionInformation.StartingOffset.HighPart) and
                      (PartitionsInformation[k].StartingOffset.QuadPart = PartitionInformation.StartingOffset.QuadPart) and
                      (PartitionsInformation[k].PartitionLength.LowPart = PartitionInformation.PartitionLength.LowPart) and
                      (PartitionsInformation[k].PartitionLength.HighPart = PartitionInformation.PartitionLength.HighPart) and
                      (PartitionsInformation[k].PartitionLength.QuadPart = PartitionInformation.PartitionLength.QuadPart) and
                      (PartitionsInformation[k].HiddenSectors = PartitionInformation.HiddenSectors) and
                      (PartitionsInformation[k].PartitionType = PartitionInformation.PartitionType) and
                      (PartitionsInformation[k].BootIndicator = PartitionInformation.BootIndicator) and
                      (PartitionsInformation[k].RecognizedPartition = PartitionInformation.RecognizedPartition) then
                      Break;
                DoMount := k > High(PartitionsInformation);
             end;
             DefineDosDevice(DDD_REMOVE_DEFINITION or DDD_RAW_TARGET_PATH, PAnsiChar(string(NextLetter + ':')), nil);
             if (not BreakCycle) and DoMount then
                DefineDosDevice(DDD_RAW_TARGET_PATH, PAnsiChar(string(NextLetter + ':')), PAnsiChar('\Device\Harddisk' + IntToStr(i) + '\Partition' + IntToStr(j)));
             if BreakCycle then
                Break;
          end;
       end;
       SetErrorMode(OldMode); //restore original mode
    end.
    

    On the computers that I mentioned it works perfectly.

    Thank you guys for all your ideas which helped me to make this code.

    If someone notice some bugs or has any good ideas about how to improve it, I'll be glad to fix/implement them.

    0 讨论(0)
  • 2021-01-17 03:49

    You can do This using WMI.
    In library GLibWMI (http://neftali.clubdelphi.com or SourceForge) you can find the TDiskPartitionInfo and TDiskDriveInfo.
    The first can give you the created partitions and all of your properties.
    Test the Generic Sample and check the results. In an partitioned disk like this:
    alt text

    You obtains 4 instantes with the properties of 4 partitions like this:

    alt text

    The library it's totally free and source is avaible. Check the samples.
    You can find some other codes to access this information using WMI. If you want use another, you can search for "WMI and Win32_DiskPartition Class" (Link doc).

    Excuse-me for mistakes with English.
    Regards

    0 讨论(0)
提交回复
热议问题