2011-01-12 58 views
0

我想映射Windows中所有驅動器的所有分區(未映射的分區)。我的意思是我想分配給他們每個人的驅動器號。 我知道你可以使用FindFirstVolume,FindNextVolume,FindVolumeClose來做到這一點,但有些情況下你不能使用它們。 我用QueryDosDevice嘗試過,同樣的事情。映射分區從PhysicalDrive開始

的想法是從\啓動\ PhysicalDrive [N],找出分區和映射。 我知道這是可行的,因爲我看到一個程序可以做到這一點。但我不喜歡它,因爲它也映射隱藏的分區。

有人知道一種方式......? 謝謝。

+0

你可以描述何時使用FindFirstVolume..FindNextVolume不起作用? – Remko 2011-01-12 19:25:20

+0

所以你的問題是如何遍歷所有分區,而不是如何安裝它們? – 2011-01-12 19:29:04

+0

@Remko它們不適用於某些Windows版本,其中某些設備(如USB驅動器)的驅動程序會動態添加,並且這些功能無法「看見」它們。 @Ritsaert我說我想掛載他們(全部)。 – 2011-01-12 20:29:11

回答

3

我做到了:) 我做了一個節目誰添加或當它開始刪除驅動器號 - 是否添加或從計算機中刪除一個或多個存儲驅動器:

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. 

在我提到它的電腦完美無缺。

謝謝大家的所有幫助我製作此代碼的想法。

如果有人注意到一些錯誤或對如何改進它有任何好的想法,我會很樂意修復/實施它們。

2

可以做到這一點使用WMI。
在庫GLibWMI(http://neftali.clubdelphi.comSourceForge),你可以找到TDiskPartitionInfoTDiskDriveInfo
第一個可以給你創建的分區和所有的屬性。
測試通用樣品並檢查結果。在一個分區的磁盤是這樣的:
alt text

你獲得4個instantes與4個分區這樣的性質:

alt text

這是完全免費和源是avaible庫。檢查樣品。
您可以通過WMI找到其他一些代碼來訪問這些信息。如果你想使用另一個,你可以搜索「WMI和Win32_DiskPartition Class」(Link doc)。

對英語錯誤的打擾。
問候