![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как сделать программное безопасное извлечение флешки?
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.