powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Безопасное извлечение USB-устройства
3 сообщений из 3, страница 1 из 1
Безопасное извлечение USB-устройства
    #39506572
vladimir412
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте!
Есть программа в Delphi для безопасного извлечения флешки.
Как ее можно переделать чтоб она извлекала только одну конкретную флешку?
Заранее спасибо!
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls,setupAPI;

type
  TForm1 = class(TForm)
    LogMemo: TMemo;
    Button3: TButton;
    Label1: TLabel;
    DrivesListBox: TListBox;
    Button7: TButton;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
  private
    { Private declarations }
  public   
    procedure OnDeviceChange(var Msg: TMessage); message WM_DEVICECHANGE;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}  



function GetDeviceName(PnPHandle: HDEVINFO; const DevData: TSPDevInfoData): string;
var
  BytesReturned: DWORD;
  RegDataType: DWORD;
  Buffer: array [0..256] of CHAR;
begin
  BytesReturned := 0;
  RegDataType := 0;
  Buffer[0] := #0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_FRIENDLYNAME,
    RegDataType, PByte(@Buffer[0]), SizeOf(Buffer), BytesReturned);
  Result := Buffer;
  if Result<>'' then exit;
  BytesReturned := 0;
  RegDataType := 0;
  Buffer[0] := #0;
  SetupDiGetDeviceRegistryProperty(PnPHandle, DevData, SPDRP_DEVICEDESC,
    RegDataType, PByte(@Buffer[0]), SizeOf(Buffer), BytesReturned);
  Result:=Buffer;
end;

function DWORDtoDiskNames(val:DWORD):string;
var
  _i: integer;
begin
  Result:='';
  for _i := 0 to 25 do
   begin
    if ((val mod 2)=1) then Result:=result+ chr(_i + 65);
    val:=val shr 1;
   end;
end;

procedure TForm1.OnDeviceChange(var Msg: TMessage);
var
  MSGSTR:String;
begin
  if Msg.WParam=DBT_DEVICEARRIVAL then
   begin
    case PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype of
     DBT_DEVTYP_DEVICEINTERFACE:
      LogMemo.Lines.Add('вставлен новый интерфейс: '+pchar(@PDEV_BROADCAST_DEVICEINTERFACE(Msg.LParam)^.dbcc_name[0])); 
    DBT_DEVTYP_VOLUME:
     begin
      MSGSTR:='новый диск'+MSGSTR;
      LogMemo.Lines.Add(MSGSTR+' '+DWORDtoDiskNames(PDEV_BROADCAST_VOLUME(Msg.LParam)^.dbcv_unitmask)+':');
     end;
    end;
   end;
  if Msg.WParam=DBT_DEVICEREMOVECOMPLETE then
   begin
    case PDEV_BROADCAST_HDR(Msg.LParam)^.dbch_devicetype of
     DBT_DEVTYP_DEVICEINTERFACE:
      LogMemo.Lines.Add('извлечён интерфейс: '+pchar(@PDEV_BROADCAST_DEVICEINTERFACE(Msg.LParam)^.dbcc_name[0]));
     DBT_DEVTYP_VOLUME:
      begin
       MSGSTR:='извлечён диск'+MSGSTR;
       LogMemo.Lines.Add(MSGSTR+' '+DWORDtoDiskNames(PDEV_BROADCAST_VOLUME(Msg.LParam)^.dbcv_unitmask)+':');
      end;
    end;
   end;
 if Msg.WParam=DBT_DEVNODES_CHANGED then
  begin
   LogMemo.Lines.Add('конфигурация изменена');
  end;
  Button6Click(nil);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  NF:TDEV_BROADCAST_DEVICEINTERFACE;
begin
  LogMemo.Clear;
  NF.dbcc_size:=sizeof(TDEV_BROADCAST_DEVICEINTERFACE);
  NF.dbcc_devicetype:=DBT_DEVTYP_DEVICEINTERFACE;
  RegisterDeviceNotification(Handle,@NF,DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
 LogMemo.Clear;
end;

function CompareMem(p1, p2: Pointer; len: DWORD): boolean;
var
  i: DWORD;
begin
  result := false;
  if len = 0 then exit;
  for i := 0 to len-1 do
   if PByte(DWORD(p1) + i)^ <> PByte(DWORD(p2) + i)^ then exit;
  result := true;
end;

function IsUSBDevice(DevInst: DWORD): boolean;  
var
  IDLen: DWORD;
  ID: PChar;
begin
  result := false;
  if (CM_Get_Device_ID_Size(IDLen, DevInst, 0) <> 0) or (IDLen = 0) then exit;
  inc(IDLen);
  ID := GetMemory(IDLen);
  if ID = nil then exit;
  if (CM_Get_Device_ID(DevInst, ID, IDLen, 0) <> 0) or (not CompareMem(ID, PChar('USBSTOR'), 7)) then
   begin
    FreeMemory(ID);
    exit;
   end;
  FreeMemory(ID);
  result := true;
end;

procedure RemoveDrive(index:integer);
var
  DrivesPnPHandle: HDEVINFO;
  DevInfo: SP_DEVINFO_DATA;
  Parent: DWORD;
  VetoName:array[0..MAX_PATH] of char;
begin
  DevInfo.cbSize := sizeof(SP_DEVINFO_DATA);
  DrivesPnPHandle := SetupDiGetClassDevsA(@GUID_DEVCLASS_DISKDRIVE, nil, 0, 2);
  if DrivesPnPHandle = INVALID_HANDLE_VALUE then exit;
  if SetupDiEnumDeviceInfo(DrivesPnPHandle, index, DevInfo) then
   begin
    if (IsUSBDevice(DevInfo.DevInst)) and (CM_Get_Parent(Parent, DevInfo.DevInst, 0) = CR_SUCCESS)
     then
      begin
       CM_Request_Device_Eject(Parent, nil, @VetoName, MAX_PATH, 0);
       if VetoName='' then
        ShowMessage('Устройство может быть извлечено')
                      else
        ShowMessage('Устройство не может быть извлечено');
      end
     else
      ShowMessage('Это не USB устройство');
   end;
  SetupDiDestroyDeviceInfoList(DrivesPnPHandle);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  Button6Click(nil);
end;

procedure TForm1.Button6Click(Sender: TObject);
var
  DrivePnPHandle: HDEVINFO;
  DeviceNumber:DWORD;
  DevData: TSPDevInfoData;
  DeviceInterfaceData: TSPDeviceInterfaceData;
  RES:BOOL;
begin
  DrivesListBox.Clear;
  DrivePnPHandle := SetupDiGetClassDevs(@GUID_DEVCLASS_DISKDRIVE, nil, 0, DIGCF_PRESENT);
  if DrivePnPHandle = INVALID_HANDLE_VALUE then  Exit;
  DeviceNumber := 0;
  repeat
   DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
   DevData.cbSize := SizeOf(TSPDevInfoData);
   RES := SetupDiEnumDeviceInfo(DrivePnPHandle, DeviceNumber, DevData);
   if (RES) then
    begin
     DrivesListBox.Items.Add(GetDeviceName(DrivePnPHandle, DevData));
     Inc(DeviceNumber);
    end;
  until not RES;
  SetupDiDestroyDeviceInfoList(DrivePnPHandle);
  DrivesListBox.Enabled:=true;
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
  if DrivesListBox.ItemIndex<0 then exit;
  RemoveDrive(DrivesListBox.ItemIndex);
  DrivesListBox.Clear;
  DrivesListBox.Enabled:=false;
  Button6Click(nil);
end;

end.



Модератор: Как мне оформить свое сообщение?
...
Рейтинг: 0 / 0
Безопасное извлечение USB-устройства
    #39506579
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vladimir412,

Например, так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
#include <windows.h>
#include <winioctl.h>
#include <tchar.h>
#include <stdio.h>

// Prototypes

BOOL EjectVolume(TCHAR cDriveLetter);

HANDLE OpenVolume(TCHAR cDriveLetter);
BOOL LockVolume(HANDLE hVolume);
BOOL DismountVolume(HANDLE hVolume);
BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPrevent);
BOOL AutoEjectVolume(HANDLE hVolume);
BOOL CloseVolume(HANDLE hVolume);

LPTSTR szVolumeFormat = TEXT("\\\\.\\%c:");
LPTSTR szRootFormat = TEXT("%c:\\");
LPTSTR szErrorFormat = TEXT("Error %d: %s\n");

void ReportError(LPTSTR szMsg)
{
  _tprintf(szErrorFormat, GetLastError(), szMsg);
}

HANDLE OpenVolume(TCHAR cDriveLetter)
{
  HANDLE hVolume;
  UINT uDriveType;
  TCHAR szVolumeName[8];
  TCHAR szRootName[5];
  DWORD dwAccessFlags;

  wsprintf(szRootName, szRootFormat, cDriveLetter);

  uDriveType = GetDriveType(szRootName);
  switch(uDriveType) {
  case DRIVE_REMOVABLE:
    dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
    break;
  case DRIVE_CDROM:
    dwAccessFlags = GENERIC_READ;
    break;
  default:
    _tprintf(TEXT("Cannot eject.  Drive type is incorrect.\n"));
    return INVALID_HANDLE_VALUE;
  }
  wsprintf(szVolumeName, szVolumeFormat, cDriveLetter);
  hVolume = CreateFile(   szVolumeName,
                               dwAccessFlags,
                               FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL,
                               OPEN_EXISTING,
                               0,
                               NULL );
  if (hVolume == INVALID_HANDLE_VALUE)
    ReportError(TEXT("CreateFile"));
  return hVolume;
}

BOOL CloseVolume(HANDLE hVolume)
{
  return CloseHandle(hVolume);
}

#define LOCK_TIMEOUT        10000       // 10 Seconds
#define LOCK_RETRIES        20

BOOL LockVolume(HANDLE hVolume)
{
  DWORD dwBytesReturned;
  DWORD dwSleepAmount;
  int nTryCount;

  dwSleepAmount = LOCK_TIMEOUT / LOCK_RETRIES;
  // Do this in a loop until a timeout period has expired
  for (nTryCount = 0; nTryCount < LOCK_RETRIES; nTryCount++) {
    if (DeviceIoControl(hVolume,
                               FSCTL_LOCK_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL))
      return TRUE;

    Sleep(dwSleepAmount);
  }
  return FALSE;
}

BOOL DismountVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               FSCTL_DISMOUNT_VOLUME,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL PreventRemovalOfVolume(HANDLE hVolume, BOOL fPreventRemoval)
   {
       DWORD dwBytesReturned;
       PREVENT_MEDIA_REMOVAL PMRBuffer;

       PMRBuffer.PreventMediaRemoval = fPreventRemoval;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_MEDIA_REMOVAL,
                               &PMRBuffer, sizeof(PREVENT_MEDIA_REMOVAL),
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   AutoEjectVolume(HANDLE hVolume)
   {
       DWORD dwBytesReturned;

       return DeviceIoControl( hVolume,
                               IOCTL_STORAGE_EJECT_MEDIA,
                               NULL, 0,
                               NULL, 0,
                               &dwBytesReturned,
                               NULL);
   }

   BOOL EjectVolume(TCHAR cDriveLetter)
   {
       HANDLE hVolume;

       BOOL fRemoveSafely = FALSE;
       BOOL fAutoEject = FALSE;

       // Open the volume.
       hVolume = OpenVolume(cDriveLetter);
       if (hVolume == INVALID_HANDLE_VALUE)
           return FALSE;

       // Lock and dismount the volume.
       if (LockVolume(hVolume) && DismountVolume(hVolume)) {
           fRemoveSafely = TRUE;

           // Set prevent removal to false and eject the volume.
           if (PreventRemovalOfVolume(hVolume, FALSE) &&
               AutoEjectVolume(hVolume))
               fAutoEject = TRUE;
       }

       // Close the volume so other processes can use the drive.
       if (!CloseVolume(hVolume))
           return FALSE;

       if (fAutoEject)
           printf("Media in Drive %c has been ejected safely.\n",
                  cDriveLetter);
       else {
           if (fRemoveSafely)
               printf("Media in Drive %c can be safely removed.\n",
               cDriveLetter);
       }

       return TRUE;
   }

void Usage()
{
  printf("Usage: Eject <drive letter>\n\n");
  return ;
}

void main(int argc, char * argv[])
{
  if (argc != 2) {
    Usage();
    return ;
  }
  if (!EjectVolume(argv[1][0]))
    printf("Failure ejecting drive %c.\n", argv[1][0]);
    return ;
} 

...
Рейтинг: 0 / 0
Безопасное извлечение USB-устройства
    #39506640
vladimir412
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
schi,

и что это?
...
Рейтинг: 0 / 0
3 сообщений из 3, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Безопасное извлечение USB-устройства
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]