0

Windows のすべてのドライブ (まだマップされていないドライブ) からすべてのパーティションをマップしたいと考えています。つまり、それぞれにドライブ文字を割り当てたいということです。FindFirstVolume、FindNextVolume、FindVolumeClose でできることは知っていますが、使用できない状況があります。同じことをQueryDosDeviceで試しました。

アイデアは、\.\PhysicalDrive[n] から開始し、パーティションを見つけてマップすることです。それができるプログラムを見たので、それが実行可能であることを知っています。しかし、隠しパーティションもマップするので、私はそれが好きではありません。

誰か方法を知っていますか...?ありがとうございました。

4

3 に答える 3

3

私はやりました:)起動時にドライブ文字を追加または削除するプログラムを作成しました-1つ以上のストレージドライブがコンピューターに追加または削除された場合:

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.

私が言及したコンピューターでは、完全に機能します。

このコードを作成するのに役立ったすべてのアイデアに感謝します。

誰かがバグに気づいたり、それを改善する方法について良いアイデアを持っている場合は、喜んで修正/実装します.

于 2011-01-14T15:15:05.577 に答える
2

これは、WMI を使用して実行できます。
ライブラリ GLibWMI ( http://neftali.clubdelphi.comまたはSourceForge ) には、TDiskPartitionInfoTDiskDriveInfoがあります。
1 つ目は、作成されたパーティションとすべてのプロパティを提供します。
汎用サンプルをテストし、結果を確認します。次のようなパーティション分割されたディスク:
代替テキスト

次のように、4 つのパーティションのプロパティを持つ 4 つのインスタントを取得します。

代替テキスト

ライブラリは完全に無料で、ソースも利用できます。サンプルを確認してください。
WMI を使用してこの情報にアクセスするためのコードが他にもいくつかあります。別のものを使用する場合は、「WMI と Win32_DiskPartition クラス」( Link doc )を検索できます。

英語の間違いをお許しください。
よろしく

于 2011-01-13T11:42:02.893 に答える
1

私のChange DriveLetterコマンドライン ツールが役立つかもしれません。少なくとも、コマンドライン パラメーターを使用して開始し、期待するすべてのボリュームが一覧表示されるかどうかを確認できます。

このリンクも役立つ場合があります: Converting a volume name to a devicename

于 2011-01-12T19:27:37.690 に答える