Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как сделать программное безопасное извлечение флешки?


Страницы:   1 2 3 4 5

mlm68 ©   (2006-03-30 21:13:00) 

Как сделать программное безопасное извлечение флешки?


n0name   (2006-04-06 10:38:00) [41]


> А какой смысл перечислять иконки, если можно через SetupApi
> сделать (как оно и должно быть сделано) ?

Поправка [6].


Игорь Шевченко   (2006-04-05 23:41:00) [42]

n0name   (05.04.06 18:37) [47]

А какой смысл перечислять иконки, если можно через SetupApi сделать (как оно и должно быть сделано) ?


Игорь Шевченко   (2006-04-05 18:38:00) [43]

Arazel ©   (05.04.06 18:28) [46]

нет, все ошибки остались. Почитай пост 34


n0name   (2006-04-05 18:37:00) [44]


> Так не честно. Нету перечисления икон, нету поиска в трее
> :)

Хех, Так я же кидал ссылку на перечисление иконок.
Мне неохото переключаться в explorer, так бы потестил и первый способ :)


Arazel   (2006-04-05 18:28:00) [45]

Игорь Шевченко©   (05.04.06 12:18) [41]
Я лишь ошибку исправил!


Игорь Шевченко   (2006-04-05 16:50:00) [46]

n0name   (05.04.06 16:37) [43]

Так не честно. Нету перечисления икон, нету поиска в трее :)

Через setupapi в тырнете примеров много, об чем автору было сказано в одном из первых постов.


GrayFace   (2006-04-05 16:47:00) [47]

>  Handle := LoadLibrary('C:\WINDOWS\system32\Ntmsapi.DLL');
надо
h := LoadLibrary('Ntmsapi.DLL');
А Handle он и у формы есть - не ошибка, но криво.


n0name   (2006-04-05 16:37:00) [48]


> Ну я както за свои слова привык отвечать


program USBEject;

uses
Windows;

const
setupapi = 'SetupApi.dll';

type
HDEVINFO = THandle;

PSP_DEVINFO_DATA = ^SP_DEVINFO_DATA;
SP_DEVINFO_DATA = packed record
 cbSize: DWORD;
 ClassGuid: TGUID;
 DevInst: DWORD;
 Reserved: DWORD;
end;

function SetupDiGetClassDevsA(ClassGuid: PGUID; Enumerator: PChar; hwndParent: HWND; Flags: DWORD): HDEVINFO; stdcall; external setupapi;
function SetupDiEnumDeviceInfo(DeviceInfoSet: HDEVINFO; MemberIndex: DWORD; DeviceInfoData: PSP_DEVINFO_DATA): boolean; stdcall; external setupapi;
function SetupDiDestroyDeviceInfoList(DeviceInfoSet: HDEVINFO): boolean; stdcall; external setupapi;
function CM_Get_Parent(pdnDevInst: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
function CM_Get_Device_ID_Size(pulLen: PDWORD; dnDevInst: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
function CM_Get_Device_IDA(dnDevInst: DWORD; Buffer: PChar; BufferLen: DWORD; ulFlags: DWORD): DWORD; stdcall; external setupapi;
function CM_Locate_DevNodeA(pdnDevInst: PDWORD; pDeviceID: PChar; ulFlags: DWORD): DWORD; stdcall; external setupapi;
function CM_Request_Device_EjectA(dnDevInst: DWORD; pVetoType: Pointer; pszVetoName: PChar; ulNameLength: DWORD;
ulFlags: DWORD): DWORD; stdcall; external setupapi;

function IsUSBDevice(DevInst: DWORD): boolean;
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;
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_IDA(DevInst, ID, IDLen, 0) <> 0) or (not CompareMem(ID, PChar('USBSTOR'), 7)) then
 begin
  FreeMemory(ID);
  exit;
 end;
FreeMemory(ID);
result := true;
end;

procedure EjectUSB();
const
GUID_DEVCLASS_DISKDRIVE: TGUID = (D1: $4D36E967; D2: $E325; D3: $11CE; D4: ($BF, $C1, $08, $00, $2B, $E1, $03, $18));
var
hDevInfoSet: HDEVINFO;
DevInfo: SP_DEVINFO_DATA;
i: Integer;
Parent: DWORD;
VetoName: PChar;
begin
DevInfo.cbSize := sizeof(SP_DEVINFO_DATA);
hDevInfoSet := SetupDiGetClassDevsA(@GUID_DEVCLASS_DISKDRIVE, nil, 0, 2);
if hDevInfoSet = INVALID_HANDLE_VALUE then exit;
i := 0;
while (SetupDiEnumDeviceInfo(hDevInfoSet, i, @DevInfo)) do
 begin
  if (IsUSBDevice(DevInfo.DevInst)) and (CM_Get_Parent(@Parent, DevInfo.DevInst, 0) = 0) then
   begin
    VetoName := GetMemory(260);
    if (CM_Request_Device_EjectA(Parent, nil, VetoName, 260, 0) <> 0) then
     begin
      if (CM_Locate_DevNodeA(@Parent, VetoName, 0) <> 0) then
       begin
        FreeMemory(VetoName);
        continue;
       end;
      FreeMemory(VetoName);
      if (CM_Request_Device_EjectA(Parent, nil, nil, 0, 0) <> 0) then continue;
     end;
    FreeMemory(VetoName);
    break;
   end;
  inc(i);
 end;
SetupDiDestroyDeviceInfoList(hDevInfoSet);
end;

begin
if MessageBoxA(0, 'Вы действительно хотите извлечь USB-диск?', 'Подтверждение', MB_YESNO) = ID_YES then
 EjectUSB();
end.


n0name   (2006-04-05 12:43:00) [49]

>>Я не увидел в этом примере метода извлечения флешки. Если не затруднит, выложи ?
Извини, я подумал что тебе пример перечисления иконок в трее.
Извлечение сейчас напишу, только не так как писал, у меня нестандартная оболочка -> тестирование проблематично.


Игорь Шевченко   (2006-04-05 12:18:00) [50]

Arazel ©   (05.04.06 12:14) [40]

Только бледнолицый брат наступает на одни и те же грабли по нескольку раз.


Arazel   (2006-04-05 12:14:00) [51]

mlm68 ©   (04.04.06 11:24) [20]

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   lbFlashDriveList: TListBox;
   Button1: TButton;
   procedure FormCreate(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
  procedure FillFlashDriveList;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FillFlashDriveList;
const
NameSize = 4;
VolumeCount = 26;
TotalSize = NameSize * VolumeCount;
var
Buff, Volume, DosDevice: String;
lpQuery: array [0..MAXCHAR - 1] of Char;
I, Count: Integer;
begin
SetLength(Buff, TotalSize);
Count := GetLogicalDriveStrings(TotalSize, @Buff[1]) div NameSize;
if Count = 0 then
  RaiseLastOSError
else
  for I := 0 to Count - 1 do
  begin
    Volume := PChar(@Buff[(I * NameSize) + 1]);
    case GetDriveType(PChar(Volume)) of
      DRIVE_REMOVABLE:
      begin
        Volume[3] := #0;
        QueryDosDevice(PChar(Volume), @lpQuery[0], MAXCHAR);
        Volume[3] := '\';
        DosDevice := String(lpQuery);
        if (DosDevice '\Device\Floppy0') and (DosDevice '\Device\Floppy1') then
          lbFlashDriveList.Items.Add(DosDevice);
          //Volume[1]
      end;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FillFlashDriveList;
end;

procedure TForm1.Button1Click(Sender: TObject);
type
TEjectDiskFromSADrive=function(
lpComputerName:LPCWSTR ;
lpAppName:LPCWSTR;
lpDeviceName:LPCWSTR;
hWnd:HWND;
lpTitle:LPCWSTR;
lpMessage:LPCWSTR;
dwOptions:DWORD
):DWORD;

const
ERROR_LIBRARY_OFFLINE      = 4305;
ERROR_DATABASE_FAILURE     = 4313;
ERROR_DATABASE_FULL        = 4314;
ERROR_INVALID_OPERATION    = 4317;
ERROR_MEDIA_NOT_AVAILABLE  = 4318;
ERROR_DEVICE_NOT_AVAILABLE = 4319;

var
EjectDiskFromSADrive: TEjectDiskFromSADrive;
hNtMsApi:THandle;
result:dword;
begin
if lbFlashDriveList.ItemIndex


Arazel   (2006-04-05 12:08:00) [52]

И как же дорогой автор темы! Может узнать что пользователь решил
вынуть флешь носитель?
Это без толковое обсуждение и лишнее трата времени!!!

Флеш можно отключить точнее безопасное извлечение:
1) Прямое обращение к драйверу и послав спец идентификаторы
2) Использовать спец. предназначеные ф-ций
3) Просто закрыть том (Device\HardDisk1\...)

Но как я говорил это без толку!


Игорь Шевченко   (2006-04-05 10:35:00) [53]

n0name   (04.04.06 20:25) [37]

Я не увидел в этом примере метода извлечения флешки. Если не затруднит, выложи ?


n0name   (2006-04-04 20:25:00) [54]


> Пример не затруднит ? Для извлечения...

http://www.codeproject.com/shell/ctrayiconposition.asp


Игорь Шевченко   (2006-04-04 17:04:00) [55]

n0name   (04.04.06 16:52) [35]

Пример не затруднит ? Для извлечения...


n0name   (2006-04-04 16:52:00) [56]

>>А как их перебрать?
Находишь окно трей.
TB_BUTTONCOUNT
TB_GETBUTTONINFO в цикле.


Игорь Шевченко   (2006-04-04 15:05:00) [57]

mlm68 ©   (04.04.06 14:43) [33]

В жизни бы не догадался.

mlm68 ©   (04.04.06 14:32) [31]


> Все равно ошибку выдает


А чего же не выдавать-то. Вполне законные основания для выдачи имеются - первое, что объявление любой функции из MS-овских dll должно оканчиваться на stdcall, второе, что ты описываешь прототип для W-версии, а вызываешь A-версию.

Один совет - ты воспринимай код, который тебе здесь дается, как пищу для дальнейших размышлений и поисков, а не как готовое решение.


mlm68   (2006-04-04 14:43:00) [58]


> Игорь Шевченко ©   (04.04.06 13:39) [27]
> Скомпилировав и запустив твой код, вынув после нажатия на
> кнопку на форме, флешку, я получил сообщение: Небезопасное
> извлечение устроства.


Перед нажатием на кнопку выбери диск в lbFlashDriveList:TListBox


Игорь Шевченко   (2006-04-04 14:36:00) [59]

Rouse_ ©   (04.04.06 14:07) [30]


> Ну по всей видимости у тебя отключена галка в свойствах
> флешки "Enable write caching on the disk" которая стоит
> по умолчанию...


По всей вероятности надо использовать другой способ. Например, тот, который сам проводник использует.
Кстати, гаек у меня никаких не отключено.


> В списке проводника она безусловно пристутвует, но при попытке
> обращения к ней выдается надпись "Please insert dist into
> Drive ..."


Не выдается...Все нормально обращается.


mlm68   (2006-04-04 14:32:00) [60]


> Ну и объявить, желательно, как функцию - чтоб код возврата
> анализировать.


Все равно ошибку выдает

unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 StdCtrls;
type
 TEjectDiskFromSADrive=function(
 lpComputerName:LPCWSTR ;
 lpAppName:LPCWSTR;
 lpDeviceName:LPCWSTR;
 hWnd:HWND;
 lpTitle:LPCWSTR;
 lpMessage:LPCWSTR;
 dwOptions:DWORD
):DWORD;
 TForm1 = class(TForm)
   Button1: TButton;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
var
 Form1: TForm1;
 EjectDiskFromSADrive: TEjectDiskFromSADrive;
implementation

uses Unit2;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var
 Handle:THandle;
 result:dword;
begin
 Handle := LoadLibrary('C:\WINDOWS\system32\Ntmsapi.DLL');
 if Handle <> 0 then begin
    @EjectDiskFromSADrive:=GetProcAddress(Handle, 'EjectDiskFromSADriveA');
    if @EjectDiskFromSADrive <> nil then begin
       result:=EjectDiskFromSADrive(nil,nil,'\\.\Cdrom0',form2.Handle,'','',0);
    end;
    FreeLibrary(Handle);
 end;
end;
end.


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо