Einzelnen Beitrag anzeigen

Benutzerbild von TKC
TKC

Registriert seit: 21. Apr 2004
Ort: Tuningen
367 Beiträge
 
Delphi XE2 Enterprise
 
#9

Re: Mit DeviceIoControl Laufwerk sperren und auslesen

  Alt 22. Nov 2005, 14:03
ich hab das mal vor einiger Zeit für meine TDriveCheck Kompo gebraucht ...

den Code kann man bestimmt noch verbessern ... stammt noch aus meiner Anfangszeit mit Delphi





Delphi-Quellcode:
const
  //Konstanten für Volume Funktionen
  METHOD_BUFFERED = 0;
  {$EXTERNALSYM METHOD_BUFFERED}
  FILE_ANY_ACCESS = 0;
  {$EXTERNALSYM FILE_ANY_ACCESS}
  FILE_DEVICE_FILE_SYSTEM = $00000009;
  {$EXTERNALSYM FILE_DEVICE_FILE_SYSTEM}
  FSCTL_LOCK_VOLUME = (FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (6 shl 2) or METHOD_BUFFERED;
  {$EXTERNALSYM FSCTL_LOCK_VOLUME}
  FSCTL_UNLOCK_VOLUME = ((FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (7 shl 2) or METHOD_BUFFERED);
  {$EXTERNALSYM FSCTL_UNLOCK_VOLUME}
  FSCTL_DISMOUNT_VOLUME = ((FILE_DEVICE_FILE_SYSTEM shl 16) or (FILE_ANY_ACCESS shl 14) or (8 shl 2) or METHOD_BUFFERED);
  {$EXTERNALSYM FSCTL_DISMOUNT_VOLUME}


{-----------------------------------------------------------------------------
  Funcktion:  DismountVolume
  Date:        21-Aug-2005
  Arguments:  sDrive: string
  Result:      Boolean
  Description: Schreibzugriff auf Volume herstellen
-----------------------------------------------------------------------------}


function TDriveCheck.DismountVolume(sDrive: string): Boolean;
const
  LOCK_TIMEOUT = 3000;
  LOCK_RETRIES = 3;

var
  iWaitTimeout : Integer;
  iTryCount : Integer;
  bLocked : Boolean;
  sVolumeName : string;
  bIOResult : Boolean;
  cBytesReturned : Cardinal;
  hVolumeHandle : THandle;

begin
  bLocked := False;
  iWaitTimeout := LOCK_TIMEOUT div LOCK_RETRIES;
  sVolumeName := '\\.\' + sDrive;

  //Generischen Schreibzugriff prüfen
  hVolumeHandle := CreateFile(PChar(sVolumeName), GENERIC_WRITE, 0, nil, OPEN_EXISTING, 0, 0);
  if hVolumeHandle <> INVALID_HANDLE_VALUE then
    begin
      Result := true;
      CloseHandle(hVolumeHandle);
      LogToMemo('Schreibzugriff hergestellt ...'#13#10);
      Exit;
    end;

  //Volumehandle für DeviceIO - Lock/Dismount holen
  hVolumeHandle := CreateFile(PChar(sVolumeName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
  if hVolumeHandle = INVALID_HANDLE_VALUE then
    begin
      Result := False;
      CloseHandle(hVolumeHandle);
      LogToMemo('Fehler beim Volume zugriff !!'#13#10);
      Exit;
    end;


  //Versuch das Laufwerk zu sperren
  LogToMemo('Versuche Laufwerk zu sperren ...'#13#10);
  for iTryCount := 0 to LOCK_RETRIES do
    begin
      bIOResult := DeviceIoControl(hVolumeHandle, FSCTL_LOCK_VOLUME, nil, 0, nil, 0, cBytesReturned, nil);

      if bIOResult then
        begin
          bLocked := true;
          LogToMemo('Laufwerk erfolgreich gesperrt ...'#13#10#13#10);
          break;
        end;

      Sleep(iWaitTimeout);
    end;

  //Laufwerk konnte nicht gesperrt werden - Versuch die Handles zu schließen
  if not bLocked then
    begin
      LogToMemo('Schließe alle offenen Handles auf das Volume ...'#13#10);
      for iTryCount := 0 to LOCK_RETRIES do
        begin
          bIOResult := DeviceIoControl(hVolumeHandle, FSCTL_DISMOUNT_VOLUME, nil, 0, nil, 0, cBytesReturned, nil);

          if bIOResult then
            begin
              bLocked := true;
              LogToMemo('Alle Handles erfolgreich geschlossen.'#13#10#13#10);
              break;
            end;

          Sleep(iWaitTimeout);
        end;
    end;

  //Volume wieder freigeben
  CloseHandle(hVolumeHandle);
  Sleep(LOCK_TIMEOUT);

  //Ergebnis setzen
  if bLocked then
    Result := true
  else
    begin
      LogToMemo('Handles konnten nicht geschlossen werden !');

      if (MessageBox(0, 'Es konnte kein exclusiver Zugriff auf das Laufwerk hergestellt werden.' + #13#10#13#10 + 'Soll das Laufwerk beim nächsten Systemstart geprüft werden ?', 'Laufwerksprüfung', MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON1) = idYes) then
        SetBootAutochk()
      else
        LogToMemo(#13#10'Scan vom Benutzer abgebrochen !!'#13#10);

      Result := False;
    end;
end;
  Mit Zitat antworten Zitat