Registriert seit: 23. Sep 2003
227 Beiträge
|
Re: USB Stick sicher entfernen unter Vista
13. Nov 2009, 13:30
Ich hänge mich hier mal an mit meinem Problem:
Ich nutze folgenden Quelltext:
Delphi-Quellcode:
Function EjectVolume(ADrive: char): Boolean;
Function OpenVolume(ADrive: char): THandle;
Var
RootName, VolumeName : String;
AccessFlags : DWORD;
DriveType : Cardinal;
Begin
RootName := ADrive + ':\';
DriveType := GetDriveType(pChar(RootName));
Case DriveType Of
DRIVE_REMOVABLE:
AccessFlags := GENERIC_READ Or GENERIC_WRITE;
DRIVE_CDROM:
AccessFlags := GENERIC_READ;
// DRIVE_FIXED:
// AccessFlags := GENERIC_READ or GENERIC_WRITE;
Else
Result := INVALID_HANDLE_VALUE;
Exit;
End;
VolumeName := Format('\\.\%s:', [ADrive]);
Result := CreateFile(pChar(VolumeName), AccessFlags,
FILE_SHARE_READ Or FILE_SHARE_WRITE, Nil, OPEN_EXISTING, 0, 0);
If Result = INVALID_HANDLE_VALUE Then
RaiseLastWin32Error;
End;
Function LockVolume(AVolumeHandle: THandle): Boolean;
Const
LOCK_TIMEOUT = 10 * 1000; // 10 Seconds
LOCK_RETRIES = 20;
LOCK_SLEEP = LOCK_TIMEOUT Div LOCK_RETRIES;
FSCTL_LOCK_VOLUME = (9 Shl 16) Or (0 Shl 14) Or (6 Shl 2) Or 0;
Var
Retries : Integer;
BytesReturned : Cardinal;
Begin
For Retries := 1 To LOCK_RETRIES Do
Begin
Result := DeviceIoControl(AVolumeHandle, FSCTL_LOCK_VOLUME, Nil, 0,
Nil, 0, BytesReturned, Nil);
If Result Then
Break;
Sleep(LOCK_SLEEP);
End;
End;
Function DismountVolume(AVolumeHandle: THandle): Boolean;
Const
FSCTL_DISMOUNT_VOLUME = (9 Shl 16) Or (0 Shl 14) Or (8 Shl 2) Or 0;
Var
BytesReturned : Cardinal;
Begin
Result := DeviceIoControl(AVolumeHandle, FSCTL_DISMOUNT_VOLUME, Nil, 0,
Nil, 0, BytesReturned, Nil);
If Not Result Then
RaiseLastWin32Error;
End;
Function PreventRemovalOfVolume(AVolumeHandle: THandle;
APreventRemoval: Boolean): Boolean;
Const
IOCTL_STORAGE_MEDIA_REMOVAL = ($2D Shl 16) Or (1 Shl 14) Or ($201 Shl 2) Or 0;
Type
TPreventMediaRemoval = Record
PreventMediaRemoval: BOOL;
End;
Var
BytesReturned : Cardinal;
PMRBuffer : TPreventMediaRemoval;
Begin
PMRBuffer.PreventMediaRemoval := APreventRemoval;
Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_MEDIA_REMOVAL,
@PMRBuffer, SizeOf(TPreventMediaRemoval), Nil, 0, BytesReturned, Nil);
If Not Result Then
RaiseLastWin32Error;
End;
Function AutoEjectVolume(AVolumeHandle: THandle): Boolean;
Const
IOCTL_STORAGE_EJECT_MEDIA = ($2D Shl 16) Or (1 Shl 14) Or ($202 Shl 2) Or 0;
Var
BytesReturned : Cardinal;
Begin
Result := DeviceIoControl(AVolumeHandle, IOCTL_STORAGE_EJECT_MEDIA, Nil, 0,
Nil, 0, BytesReturned, Nil);
If Not Result Then
RaiseLastWin32Error;
End;
Var
VolumeHandle : THandle;
str : String;
Begin
Result := False;
// Open the volume
VolumeHandle := OpenVolume(ADrive);
If VolumeHandle = INVALID_HANDLE_VALUE Then
Exit;
Try
// Lock and dismount the volume
If LockVolume(VolumeHandle) And DismountVolume(VolumeHandle) Then
Begin
// Set prevent removal to false and eject the volume
If PreventRemovalOfVolume(VolumeHandle, False) Then
Result := AutoEjectVolume(VolumeHandle);
End;
Finally
// Close the volume so other processes can use the dr
CloseHandle(VolumeHandle);
End;
If Result Then
Begin
str := ADrive + '\';
ShChangeNotify(
SHCNE_MEDIAREMOVED,
SHCNF_PATH,
pChar(str),
Nil);
End;
End;
Der USB-Stick wird ausgehängt, aber irgendwie scheint ShChangeNotify zu scheitern. Das Symbol in der Taskleiste bleibt erhalten, ebendso wird im Explorer noch das Laufwerk angezeigt. Wie sag ich Windows nun, dass ich den Stick ausgehängt habe?
Gruß
Sascha
|