AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi USB Stick sicher entfernen unter Vista

USB Stick sicher entfernen unter Vista

Ein Thema von Pichel · begonnen am 15. Sep 2008 · letzter Beitrag vom 24. Apr 2014
Antwort Antwort
Seite 1 von 3  1 23   
Benutzerbild von Pichel
Pichel

Registriert seit: 25. Feb 2005
Ort: Kassel
65 Beiträge
 
Delphi 7 Professional
 
#1

USB Stick sicher entfernen unter Vista

  Alt 15. Sep 2008, 20:54
Hallöchen.

Was unter XP tadellos funktionierte das streikt nun unter Vista.
Ich möchte aus meinem Programm heraus auch unter Vista einen Usb-Stick sicher entfernen.

Hierzu habe ich auch alle Laufwerke in einer Listbox inkl. Instanz als Object basieren auf irgendnem Code den ich mal irgendwo gefunden habe.
Bem.nicht schön aber funktionier

Delphi-Quellcode:
function TaForm.SaveRemoveDrive(Drive: Char): Boolean;
var S: string;
    idx, it,
    I: Integer;
    Inst: DEVINST;
    SymbolicName: string;
    VetoType: PNP_VETO_TYPE;
    //VetoBuffer: array [0..MAX_PATH-1] of TCHAR;
begin
  Result := False;
  idx := -1;
  // update the list of drive mount points
  FillInRemovableDriveMountPoints(DriveMountPoints);
  // show the list of drive letters from the drive mount point list
  DriveList.Items.BeginUpdate;
  DriveList.Items.Clear;
  S := 'A:';
  for I := 0 to DriveMountPoints.Count - 1 do begin
    S[1] := Char(DriveMountPoints.Objects[I]);
    GetDriveInstanceID(DriveMountPoints[I], Inst);
    SymbolicName := GetSymbolicName(Inst);
    it := DriveList.Items.AddObject(S + ' ' + ExtractSerialNumber(SymbolicName), TObject(Inst));
    if UpperCase(S[1]) = UpperCase(Drive) then begin
      idx := it;
    end;
  end;
  DriveList.Items.EndUpdate;
  if idx > -1 then
    // find the mount point name for the drive letter clicked
    for I := 0 to DriveMountPoints.Count - 1 do begin
      if Char(DriveMountPoints.Objects[I]) = DriveList.Items[idx][1] then begin
        VetoType := 0;
        // try to do a silent safe removal
        // for drives not able to do a safe removal the function simply fails
        // FillChar(VetoBuffer[0], SizeOf(VetoBuffer), 0);
        // CM_Request_Device_Eject(DEVINST(DriveList.Items.Objects[I]),
        // @VetoType, @VetoBuffer[0], Length(VetoBuffer), 0);
        // do a safe removal with dialog
        CM_Request_Device_Eject(DEVINST(DriveList.Items.Objects[idx]), @VetoType, nil, 0, 0);
        Result := True;
      end;
    end;
end;
Den restlichen Programmcode hab ich mal hier gepostet

Delphi-Quellcode:
uses
  JwaWinBase, JwaWinType, Cfg, CfgMgr32, SetupApi, mySysUtils;

{$R *.dfm}

// encapsulate GetVolumeNameForVolumeMountPoint in a Delphi-style function

function GetVolumeNameForVolumeMountPointString(Name: string): string;
var
  Volume: array [0..MAX_PATH] of Char;
begin
  FillChar(Volume[0], SizeOf(Volume), 0);
  GetVolumeNameForVolumeMountPoint(PChar(Name), @Volume[0], SizeOf(Volume));
  Result := Volume;
end;

// fills the TStringList with the mount points of all removable drives

procedure FillInRemovableDriveMountPoints(MountPoints: TStrings);
const
  MAX_DRIVES = 26;
var
  I: Integer;
  dwDriveMask: DWORD;
  DriveName: string;
begin
  MountPoints.Clear;
  // get all mounted drive letters as bitmask
  dwDriveMask := GetLogicalDrives;
  DriveName := 'A:\';
  // check all drive letters
  for I := 0 to MAX_DRIVES - 1 do
    // if drive letter exists
    if (dwDriveMask and (1 shl I)) <> 0 then
    begin
      DriveName[1] := 'A';
      Inc(DriveName[1], I);
      // see if it is a removable drive
      if GetDriveType(PChar(DriveName)) = DRIVE_REMOVABLE then
        // store mount point string and corresponding drive letter in list
        MountPoints.AddObject(GetVolumeNameForVolumeMountPointString(DriveName), TObject(DriveName[1]));
    end;
end;

// Delphi style encapsulation for CM_Get_Device_ID

function GetDeviceID(Inst: DEVINST): string;
var
  Buffer: PTSTR;
  Size: ULONG;
begin
  CM_Get_Device_ID_Size(Size, Inst, 0);
  // Required! See DDK help for CM_Get_Device_ID
  Inc(Size);
  Buffer := AllocMem(Size * SizeOf(TCHAR));
  CM_Get_Device_ID(Inst, Buffer, Size, 0);
  Result := Buffer;
  FreeMem(Buffer);
end;

// simple extraction of the bus name from DeviceID string

function ExtractBus(DeviceID: string): string;
begin
  Result := Copy(DeviceID, 1, Pos('\', DeviceID) - 1);
end;

// get the "SymbolicName" registry entry of a device
// for an USB device this string contains VID, PID and SerialNumber string

function GetSymbolicName(Inst: DEVINST): string;
var
  Len: DWORD;
  Key: HKEY;
  // a hopefully sufficiently large buffer
  Buffer: array [0..4095] of Char;
begin
  CM_Open_DevNode_Key(Inst, KEY_READ, 0,
    REGDISPOSITION(RegDisposition_OpenExisting), Key, 0);
  Buffer[0] := #0;
  if Key <> INVALID_HANDLE_VALUE then
  begin
    Len := SizeOf(Buffer);
    RegQueryValueEx(Key, 'SymbolicName', nil, nil, @Buffer[0], @Len);
    RegCloseKey(Key);
  end;
  Result := Buffer;
end;

// extract a 4 digit hex number from SymbolicName
// example "\??\USB#Vid_08ec&Pid_0010#0918121014000B59#{a5dcbf10-6530-11d2-901f-00c04fb951ed}"

function ExtractNum(const SymbolicName, Prefix: string): Integer;
var
  S: string;
  N: Integer;
begin
  S := LowerCase(SymbolicName);
  N := Pos(Prefix, S);
  if N > 0 then
  begin
    S := '$' + Copy(SymbolicName, N + Length(Prefix), 4);
    Result := StrToInt(S);
  end
  else
    Result := 0;
end;

function ExtractVID(const SymbolicName: string): Integer;
begin
  Result := ExtractNum(SymbolicName, 'vid_');
end;

function ExtractPID(const SymbolicName: string): Integer;
begin
  Result := ExtractNum(SymbolicName, 'pid_');
end;

function ExtractSerialNumber(SymbolicName: string): string;
var
  N: Integer;
begin
  N := Pos('#', SymbolicName);
  if N >= 0 then
  begin
    SymbolicName := Copy(SymbolicName, N + 1, Length(SymbolicName));
    N := Pos('#', SymbolicName);
    if N >= 0 then
    begin
      SymbolicName := Copy(SymbolicName, N + 1, Length(SymbolicName));
      N := Pos('#', SymbolicName);
      if N >= 0 then
        Result := Copy(SymbolicName, 1, N - 1)
      else
        Result := '';
    end;
  end
  else
    Result := '';
end;

// find the "bus" DeviceID for a given mount point

function GetDriveInstanceID(MountPointName: string; var DeviceInst: DEVINST): Boolean;
const
  GUID_DEVINTERFACE_VOLUME: TGUID = '{53f5630d-b6bf-11d0-94f2-00a0c91efb8b}';
var
  StorageGUID: TGUID;
  PnPHandle: HDEVINFO;
  DevData: TSPDevInfoData;
  DeviceInterfaceData: TSPDeviceInterfaceData;
  FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
  Success: LongBool;
  Devn: Integer;
  BytesReturned: DWORD;
  Inst: DEVINST;
  S, FileName, MountName, DevID: string;
begin
  Result := False;
  DeviceInst := 0;
  // enumerate all volumes
  StorageGUID := GUID_DEVINTERFACE_VOLUME;
  PnPHandle := SetupDiGetClassDevs(@StorageGUID, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
  if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then
    Exit;
  Devn := 0;
  repeat
    DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
    Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, StorageGUID, Devn, DeviceInterfaceData);
    if Success then
    begin
      DevData.cbSize := SizeOf(DevData);
      BytesReturned := 0;
      SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, BytesReturned, @DevData);
      if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
      begin
        FunctionClassDeviceData := AllocMem(BytesReturned);
        try
          FunctionClassDeviceData.cbSize := SizeOf(TSPDeviceInterfaceDetailData);
          if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData,
            FunctionClassDeviceData, BytesReturned, BytesReturned, @DevData) then
          begin
            FileName := PTSTR(@FunctionClassDeviceData.DevicePath[0]);
            // get the grandparent DevNode which is the "bus" device
            // like "USB". This is the DevNode for CM_Request_Device_Eject and
            // several other useful operations
            Inst := DevData.DevInst;
            CM_Get_Parent(Inst, Inst, 0);
            CM_Get_Parent(Inst, Inst, 0);
            DevID := GetDeviceID(Inst);

            // no need in this example to check for USB only
            // if ExtractBus(DevID) = 'USB' then
            begin
              S := '\';
              S := PTSTR(@FunctionClassDeviceData.DevicePath) + S;
              MountName := GetVolumeNameForVolumeMountPointString(S);
              if MountName = MountPointName then
              begin
                DeviceInst := Inst;
                Result := True;
                Exit;
              end;
            end;
          end;
        finally
          FreeMem(FunctionClassDeviceData);
        end;
      end;
    end;
    Inc(Devn);
  until not Success;
  SetupDiDestroyDeviceInfoList(PnPHandle);
end;

//============================================================================

procedure TaForm.FormCreate(Sender: TObject);
var i : Integer;
begin
  // never forget to load the dynamically linked APIs
  LoadSetupApi;
  LoadConfigManagerApi;
  DriveMountPoints := TStringList.Create;
  DriveMountPoints.Sorted := True;
  // initialize drive list
  if ParamCount > 0 then begin
    for i := 1 to ParamCount do begin
      if (Pos('DRIVEREMOVE:', UpperCase(ParamStr(i))) > 0)
      and (ParamStr(i)[length(ParamStr(i))] in ['A'..'Z','a'..'z']) then begin
        if not SaveRemoveDrive(ParamStr(i)[length(ParamStr(i))])
          then begin end;
      end;
    end;
  end;
  PostMessage(Handle, WM_CLOSE, 0, 0);
end;

procedure TaForm.FormDestroy(Sender: TObject);
begin
  DriveMountPoints.Free;
  UnloadConfigManagerApi;
  UnloadSetupApi;
end;
Da dies nicht unter Vista funktioniert, bzw. einfach gar nichts tut hab ich recherchiert und nur bei MS gefunden das unter Vista man die Privilegien haben muss, also hab ichs noch damit versucht den CM_Request_Device_Eject wie folgt abzuändern:

Delphi-Quellcode:
        SetPrivilege('SeUndockPrivilege', true);
        CM_Request_Device_Eject(DEVINST(DriveList.Items.Objects[idx]), @VetoType, nil, 0, CM_REMOVE_NO_RESTART);
        SetPrivilege('SeUndockPrivilege', False);
Die SetPrivilege Funktion hier:
Delphi-Quellcode:
function SetPrivilege(privilegeName: string; enable: boolean): boolean;
var
  tpPrev,
  tp : TTokenPrivileges;
  token : THandle;
  dwRetLen : DWord;
begin
  result := False;
  OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, token);
  tp.PrivilegeCount := 1;
  if LookupPrivilegeValue(nil, pchar(privilegeName), tp.Privileges[0].LUID) then begin
    if enable then
      tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
    else
      tp.Privileges[0].Attributes := 0;
    dwRetLen := 0;
    result := AdjustTokenPrivileges(token, False, tp, SizeOf(tpPrev), tpPrev, dwRetLen);
  end;
  CloseHandle(token);
end;
Funktioniert nicht, wer kann hier auf die Sprünge helfen nachdem ich alle gefundenen Quellen schon nach Lösungen durchforstet habe.
Grüße aus Kassel.

Konfuzius sprach: Etwas lernen und sich immer wieder darin üben - schafft das nicht auch Befriedigung?
  Mit Zitat antworten Zitat
Benutzerbild von Pichel
Pichel

Registriert seit: 25. Feb 2005
Ort: Kassel
65 Beiträge
 
Delphi 7 Professional
 
#2

Re: USB Stick sicher entfernen unter Vista

  Alt 18. Sep 2008, 14:47
Wie denn, keiner hier irgendeine Idee
Grüße aus Kassel.

Konfuzius sprach: Etwas lernen und sich immer wieder darin üben - schafft das nicht auch Befriedigung?
  Mit Zitat antworten Zitat
Benutzerbild von Pichel
Pichel

Registriert seit: 25. Feb 2005
Ort: Kassel
65 Beiträge
 
Delphi 7 Professional
 
#3

Re: USB Stick sicher entfernen unter Vista

  Alt 3. Okt 2008, 10:43
Schade, ich denke kann dann diese Frage als unbeantwortet schließen
Grüße aus Kassel.

Konfuzius sprach: Etwas lernen und sich immer wieder darin üben - schafft das nicht auch Befriedigung?
  Mit Zitat antworten Zitat
Dust Signs

Registriert seit: 28. Dez 2004
Ort: Salzburg
379 Beiträge
 
#4

Re: USB Stick sicher entfernen unter Vista

  Alt 3. Okt 2008, 11:02
Hallo!

Kann es evtl. damit zusammenhängen, dass du unter Vista für einige Operationen höhere Rechte benötigst? Funktioniert denn dein Code, wenn du das Programm als Administrator startest?

Dust Signs
(aka AXMD in der EE)
Die Nummer, die Sie gewählt haben, ist imaginär. Bitte drehen Sie Ihr Telefon um 90° und versuchen Sie es erneut.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#5

Re: USB Stick sicher entfernen unter Vista

  Alt 3. Okt 2008, 12:46
Soweit ich weiß, ist es unter Vista nicht mehr notwendig dieses "sichere Entfernen" zu verwenden.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: USB Stick sicher entfernen unter Vista

  Alt 3. Okt 2008, 12:50
Zitat von Zacherl:
Soweit ich weiß, ist es unter Vista nicht mehr notwendig dieses "sichere Entfernen" zu verwenden.
Warum sollte das nicht mehr nötig sein?
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von MagicAndre1981
MagicAndre1981

Registriert seit: 4. Jun 2004
Ort: Nordhausen
2.214 Beiträge
 
Delphi 7 Enterprise
 
#7

Re: USB Stick sicher entfernen unter Vista

  Alt 3. Okt 2008, 12:57
das ist nur dann nicht nötig wenn man den Cache deaktiviert. Als Standard ist der Cache deaktiviert und dann kann man den Stick einfach abziehen sonst nicht. Unter *nix muss man den Stick auch erst unmounten, sonst sind die Daten noch im Cache und nicht auf dem Stick
André
"A programmer is just a tool which converts caffeine into code", daran wirds wohl liegen, dass ich Abends nie pennen kann

Zitat von Luckie:
Nicht nur dass ihr offtopic geworden seid, jetzt werdet ihr selber im Offtopic noch offtopic
  Mit Zitat antworten Zitat
Benutzerbild von Pichel
Pichel

Registriert seit: 25. Feb 2005
Ort: Kassel
65 Beiträge
 
Delphi 7 Professional
 
#8

Re: USB Stick sicher entfernen unter Vista

  Alt 5. Okt 2008, 18:23
Zitat von Dust Signs:
Kann es evtl. damit zusammenhängen, dass du unter Vista für einige Operationen höhere Rechte benötigst? Funktioniert denn dein Code, wenn du das Programm als Administrator startest?
Leider liegt es nicht daran da ich sowas immer als Admin teste Laut MS sind ja weiter Privilegien nötig (wie oben geschildert) welche ich in allem möglichen Kombinationen getestet habe - ohne Erfolg, der Dialog aus dem Systemtray poppt einfach nicht auf.

Bin schon fast soweit mich direkt an dem TrayIcon und dem dahinter liegendem Popupmenü zum sicheren entfernen zu vergreifen

Zitat von Zacherl:
Soweit ich weiß, ist es unter Vista nicht mehr notwendig dieses "sichere Entfernen" zu verwenden.
Aber das TrayIcon erscheint immer noch unter Vista, also wird das wohl irgend enen Sinn haben, und möchte mir ja nur den Umweg über das TrayIcon sparen.
Grüße aus Kassel.

Konfuzius sprach: Etwas lernen und sich immer wieder darin üben - schafft das nicht auch Befriedigung?
  Mit Zitat antworten Zitat
Uwe Sieber

Registriert seit: 21. Jan 2009
4 Beiträge
 
#9

Re: USB Stick sicher entfernen unter Vista

  Alt 21. Jan 2009, 16:57
Sieht so aus, dass Du ein Parent/Child-Beziehung zwischen Volume und Disk voraussetzt.
Das war schon unter XP nur für Wechseldatenträger und CDROMs ok, unter Vista nur noch
für CDROMs.

Hier habe ich in C++ gezeigt, wie es geht:
http://www.codeproject.com/KB/system...eByLetter.aspx


Gruß Uwe
  Mit Zitat antworten Zitat
worker.db

Registriert seit: 5. Nov 2009
8 Beiträge
 
#10

Re: USB Stick sicher entfernen unter Vista

  Alt 5. Nov 2009, 15:26
Hallöchen.

Was unter XP tadellos funktionierte das streikt nun unter Vista.
Ich möchte aus meinem Programm heraus auch unter Vista einen Usb-Stick sicher entfernen.

Hierzu habe ich auch alle Laufwerke in einer Listbox inkl. Instanz als Object basieren auf irgendnem Code den ich mal irgendwo gefunden habe.
Bem.nicht schön aber funktionier Wink
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:12 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz