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) 

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


Arazel   (2006-04-11 06:59:00) [21]

Игорь теперь ты видишь, сколько ошибок происходит!
Зачем тебе это нужно. Я лишь любитель, а вот если заглянут
профессионалы они засмеют тебя, тебе этот позор нужен? Знаток ;)

unit IO;

INTERFACE

{$I NTDDK.INC}
{$I NTOSKRNL.INC}

CONST
    DEVICE_NAME_STRING = 'IO';
    DeviceNameString   = '\DosDevices\'  +DEVICE_NAME_STRING;
    DriverNameString   = '\Device\'      +DEVICE_NAME_STRING;
    UserModeDeviceName = '\\.\Global\'   +DEVICE_NAME_STRING;

    IOCTL_BEEP   =
    (IOCTL_UNKNOWN_BASE shl 16) or
    ((FILE_READ_ACCESS) shl 14) or
    ($800 shl 2) or
    (METHOD_BUFFERED);

TYPE
    PParams     = ^TParams;
    TParams     = RECORD
      ParamType : ULONG;
      Param1    : ULONG;
      Param2    : ULONG;
      Param3    : ULONG;
    END;

 function DriverEntry(
 const DriverObject : PDRIVER_OBJECT;
 const RegistryPath : PUNICODE_STRING
 ) : NTStatus; stdcall;

IMPLEMENTATION

{$I MACROS.INC}

VAR
    DriverName    : UNICODE_STRING;
    DeviceName    : UNICODE_STRING;
    DeviceObject  : PDEVICE_OBJECT;
    Params        : TParams;

PROCEDURE ADriverUnload(const DriverObject : PDRIVER_OBJECT); stdcall;
BEGIN
  DbgPrint('DriverUnload ');
  // Удаляем символьную сылку
  IoDeleteSymbolicLink(@DeviceName);
  // Удаляем устройство
  IoDeleteDevice(DeviceObject);
END;

function CloseDispatch(
        const DeviceObject : PDEVICE_OBJECT;
        const Irp : PIRP) : NTSTATUS; stdcall;
BEGIN
 (***********************************************)
  // Если при завершений ф-ций/процедуры потеряеются данные
  // то есть, которые ниже... То это уже говорит что в драйвер
  // поступят ошибки.
  //   DbgPrint('CloseDispatch');
  //   IRP.IoStatus.Status        :=0;
  //   IRP.IoStatus.Information   :=0;
  //   IoCompleteRequest(IRP,IO_NO_INCREMENT);
  //   Result:=STATUS_SUCCESS;
 (***********************************************)
 IoCompleteRequest(IRP,IO_NO_INCREMENT);
END;

function CreateDispatch(
        const DeviceObject : PDEVICE_OBJECT;
        const Irp : PIRP) : NTSTATUS; stdcall;
BEGIN
  DbgPrint('CreateDispatch');
  IRP.IoStatus.Status        :=STATUS_SUCCESS;
  IRP.IoStatus.Information   :=0;
  IoCompleteRequest(IRP,IO_NO_INCREMENT);
  Result:=STATUS_SUCCESS;
END;

function IOCTLDispatch(
        const DeviceObject : PDEVICE_OBJECT;
        const dIrp : PIRP) : NTSTATUS; stdcall;
VAR
        IRPStack : PIO_STACK_LOCATION;
BEGIN
 DbgPrint('IOCTLDispatch');
 // Кстати, на вход могут вообще чудо-юдо поступить.
 // и система встанит по полной!
 // Просто прикол :)))
 dIrp:=nil;
 IRPStack:=IoGetCurrentIrpStackLocation(dIrp);
 CASE IRPStack^.Parameters.DeviceIoControl.IoControlCode OF
 IOCTL_BEEP :
 BEGIN
 (***********************************************)
  // Также Buffer может обнулится или передоватся не правельные данные
  // это первая ошибка твоя! Не говоря уж BSOD.
  // if  (IRPStack^.Parameters.DeviceIoControl.OutputBufferLength >= SizeOf(TParams))
  // and (dIrp.AssociatedIrp.SystemBuffer<>nil) then
 (***********************************************)
 BEGIN
 // load
  Params:=TParams(dIrp.AssociatedIrp.SystemBuffer^);
  Beep(Params.Param1,Params.Param2);

  Params.ParamType:=5;
  Params.Param1:=12345;
  Params.Param2:=54321;
  Params.Param3:=55555;

 (***********************************************)
  // Это вторая ошибка.
  // TParams(dIrp.AssociatedIrp.SystemBuffer^):=Params;
  // dIrp.IoStatus.Information:=SizeOf(TParams);
 (***********************************************)
 // report
 Result:=STATUS_SUCCESS;
 END
  ELSE Result:=STATUS_INVALID_PARAMETER;
 END;
  ELSE Result:=STATUS_NOT_IMPLEMENTED;
END;

 (***********************************************)
  // Вот сюда должны передоватся обработанные IRP пакеты
  // IoCompleteRequest(dIrp,IO_NO_INCREMENT);
 (***********************************************)
END;

function DriverEntry;
BEGIN
  DbgPrint('DriverEntry');
  RtlInitUnicodeString(DriverName,DriverNameString);
  Result:=IoCreateDevice(
           DriverObject,        // указатель на DriverObject
           0,                   // максимальный размер принимаемых данных
           @DriverName,         // имя создаваемого устройства
           FILE_DEVICE_UNKNOWN, // тип создаваемого устройства
           0,                   // метод буфферизации
           False,               // "эксклюзивное" устройство
           DeviceObject         // указатель на обьект устройства
           );

  IF (Result = STATUS_SUCCESS) THEN
  BEGIN
  RtlInitUnicodeString(DeviceName,DeviceNameString);
  Result:=IoCreateSymbolicLink(@DeviceName,@DriverName);
   IF (Result = STATUS_SUCCESS) THEN
   BEGIN
    DriverObject^.DriverUnload:=ADriverUnload;
    DriverObject^.MajorFunction[IRP_MJ_CREATE] := CreateDispatch;
    DriverObject^.MajorFunction[IRP_MJ_CLOSE]  := CloseDispatch;
    DriverObject^.MajorFunction[IRP_MJ_DEVICE_CONTROL]:= IOCTLDispatch;
   END ELSE
   Result:=STATUS_UNSUCCESSFUL;
   if (Result<>STATUS_SUCCESS) THEN
   IoDeleteSymbolicLink(@DeviceName);
  END;
  if (Result<>STATUS_SUCCESS) THEN
  IoDeleteDevice(DeviceObject);
END;

end.


Игорь Шевченко   (2006-04-10 11:16:00) [22]

Arazel ©   (08.04.06 08:05) [67]


> Сразу видно мало ты знаешь про ДРАЙВЕРА.


Может быть, я не претендую на полноту знаний.


> Если драйвер находится в режиме функционирований и в это
>
> время вынуть Флешь, то вполне вероятно, что дело дойдет
> до переустановки
> системы в целом!


Но моих знаний хватает, для того, чтобы утверждать, что процитированная фраза не совпадает с поведением системы. Либо ты приводишь пример, когда такая ситуация возможно (при извлечении флешки в неподходящий момент надо переустанавливать систему в целом), либо пишешь, что твои фантазии не имеют ничего общего с реальностью.


> Так как пакеты успешного выполнение, должны передоватся
> в конце каждой процедуры


Фразу нельзя понять по двум причинам - либо не хватает знаний, либо фраза написана непонятно. Сдается мне, что имеет место второй случай.


mlm68   (2006-04-08 23:18:00) [23]


> n0name   (08.04.06 04:55) [66]
>
> Там отключает первый попавшийся USB накопитель, немного
> модифицируй код, и всё.


Но отключается намертво (удаляет том), после вытаскивания - впихивания флешки диск система не видит, приходится вытаскивать картридер, а так как он у меня встроеный то только перезакрузка помогает.

Кстати так делает и система, когла нажимаешь в трее безопасное отключение, а код [24] делает  команду "Извлечь", которая в контекстном меню диска, и после вставления флешки, её опять видно.


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

Игорь Шевченко ©   (07.04.06 15:09) [63]
Невероятно.Сразу видно мало ты знаешь про ДРАЙВЕРА.
Переведи на русский язык.Если ты не смог понять выше строчку
то наврятли ты поймешь про IRP пакеты.
Ты можешь ответить на простой вопрос - нафига ты этот код привел, если он флешку не извлекает ?
Читай 62 пост.


n0name   (2006-04-08 04:55:00) [25]


> код [43] немного не подошел по причине того, что он отключает
> картридер, и чтобы прочитать следующую флешку нужно выдернуть
> картридер и воткнуть его снова.

Там отключает первый попавшийся USB накопитель, немного модифицируй код, и всё.


mlm68   (2006-04-08 00:03:00) [26]

Огромное спасибо всем откликнувшимся на мою просьбу!

Я когда создал тему, даже и не думал, что она так вас заинтересует.

Мне очень помог код [24] - это было собствено то что мне было нужно.
он даже CD-ROM заставляет выезжать (если в качестве параметра SafeEjectDriveуказать его), что мне тоже необходимо.

код [43] немного не подошел по причине того, что он отключает картридер, и чтобы прочитать следующую флешку нужно выдернуть картридер и воткнуть его снова.

Еще раз всем спасибо.


n0name   (2006-04-07 15:27:00) [27]


> Ну зачем тебе иметь вторую программу для извлечение?

Мало ли какие причины у автора. Это не моя идея, я лишь привёл пример реализации.

> Так как Безопасное извлечение как раз таки и заключается
> в выгрузкедрайвера.

Так зачем тебе это делать, если всё это выполняют функции SetupAPI.


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


> Если драйвер находится в режиме функционирований и в это
>
> время вынуть Флешь, то вполне вероятно, что дело дойдет
> до переустановки
> системы в целом


Невероятно.


> Так как пакеты успешного выполнение, должны передоватся
> в конце каждой процедуры


Переведи на русский язык.


> Я имел введу что выполняется правельно... а что она делает
> это ты можешь прочитать на сайте microsoft


Ты можешь ответить на простой вопрос - нафига ты этот код привел, если он флешку не извлекает ?


Arazel   (2006-04-07 14:53:00) [29]

Игорь Шевченко ©   (07.04.06 12:52) [59]
Я имел введу что выполняется правельно... а что она делает
это ты можешь прочитать на сайте microsoft
Хотя зачем я тебе это говорю :) Ты и сам сможешь с этим разобратся.
А лиш исправил приведеный код Автор(а) темы.

Думаю на этом закончим.


Arazel   (2006-04-07 14:49:00) [30]

n0name   (07.04.06 14:41) [60]
Смысл фразы малопонятен.
Ну зачем тебе иметь вторую программу для извлечение?
Только лишь для того если ты используешь другой Shell
но разве тебе этого мало?

Зачем тебе производить какие-то действия с драйверами?
Так как Безопасное извлечение как раз таки и заключается в выгрузке
драйвера. Если драйвер находится в режиме функционирований и в это
время вынуть Флешь, то вполне вероятно, что дело дойдет до переустановки
системы в целом! Так как пакеты успешного выполнение, должны передоватся
в конце каждой процедуры.


n0name   (2006-04-07 14:41:00) [31]

>>1) Проверить действительно ли это безопасное извлечение
AFAIK именно так и реализованно в Win. "Безопасное извлечение" использует hotplug.dll, в котором и используется SetupAPI.
>>2) Превести код до ума...
Гм. Все необходимые проверки выполнены. Полностью рабочий пример.
>>3) Придумать автоматическое безопасное извлечение
Смысл фразы малопонятен.
>>Сомнение:
Зачем тебе производить какие-то действия с драйверами?


Игорь Шевченко   (2006-04-07 12:52:00) [32]

Arazel ©   (07.04.06 12:46) [58]


> Вот этот код полноценно работоспособен!


Это чьи слова из поста [53] ?


> Документацию по этой ф-ций я не читал...
>
> Ф-ция работает 100%. Наверное, она не совсем для этого предназначено!
>


Нафига тогда ты пишешь код ?


Arazel   (2006-04-07 12:46:00) [33]

Игорь Шевченко ©   (07.04.06 11:37) [57]
Во первых как я уже не раз повторял, это лишь правильное определение
ф-ций. В том числе пример.
Документацию по этой ф-ций я не читал...

Ф-ция работает 100%. Наверное, она не совсем для этого предназначено!

У меня тоже не изчезает диск, хотя досуп закрыт!

Ошибки обрабатываются нормально! ПРОВЕРЕННО!


Игорь Шевченко   (2006-04-07 11:37:00) [34]


> Ну это уже мало у кого мозгов хватит


У разработчиков Explorer'а хватило.

Кстати, твой пример из [53] не работает. Пишет, что "The eject operation was successful", но ничего не извлекается. Флешка как была видна, так и остается. И файлы с нее преспокойно открываются. Более того, программа даже не выдает ошибки, если флешка открыта в другом приложении.


Arazel   (2006-04-07 11:04:00) [35]

n0name   (05.04.06 16:37) [43]
Извиний но я не заметил, ты уже решил проблему :)
Осталось:

1) Проверить действительно ли это безопасное извлечение
2) Превести код до ума...
3) Придумать автоматическое безопасное извлечение

Сомнение:
1) При извлечение драйвер должен подать сигнал о том что устройство
   освобожденно и перейти в режим ожидание... Такое нет! Драйвер
   остается ждать следующие устройство... об этом говрит сам драйвер
   тома!
2) Перечислить нужные устройста затем воспользоватся твоим кодом
   затем выгрузить драйвер тома...

3) Ну это уже мало у кого мозгов хватит. Здесь надо применять ядровые
   ф-ций.

Вообще зачем я в лип в эту историю.  :D


Arazel   (2006-04-07 10:45:00) [36]

n0name   (07.04.06 10:22) [54]
Тогда драйвер нужного ТОМА :)


n0name   (2006-04-07 10:22:00) [37]

>>не обходимо остановить драйвер  USBSTOR.SYS
И отрубятся сразу все USB-диски, а не какой-то конкретный, способ приведённый в [43] более корректен.


Arazel   (2006-04-07 07:26:00) [38]

ALL
Кое что я выяснил насчет вашей проблемы
для того что бы безопасно извлечь флешку
не обходимо остановить драйвер  USBSTOR.SYS
какторый отвечает за USB носителями
Вот и все!

Игорь Шевченко ©   (05.04.06 18:38) [48]
Извений, но я не вглядываюсь в чужой код, но ты меня вынудил :) ;)
Вот этот код полноценно работоспособен!

unit Unit1;

interface

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

type
 TForm1 = class(TForm)
   btnSafeEject: TButton;
   procedure btnSafeEjectClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

const
   NTMS_EJECT_START          = 00000000;
   NTMS_EJECT_STOP           = 00000001;

const
  ERROR_LIBRARY_OFFLINE      = 00004305;
  ERROR_DATABASE_FAILURE     = 00004313;
  ERROR_DATABASE_FULL        = 00004314;
  ERROR_INVALID_OPERATION    = 00004317;
  ERROR_MEDIA_NOT_AVAILABLE  = 00004318;
  ERROR_DEVICE_NOT_AVAILABLE = 00004319;
  ERROR_DEVICE__CAN_NOT_OPEN = 00000003;

function EjectDiskFromSADriveW(
 lpComputerName:PWideChar;
 lpAppName:PWideChar;
 lpDeviceName:PWideChar;
 hWnd:HWND;
 lpTitle:PWideChar;
 lpMessage:PWideChar;
 dwOptions:DWORD
):DWORD;stdcall; external 'NtMSAPI.DLL';

function StringToPWideChar(sStr: string): PWideChar;
var
 pwc: PWideChar;
 iSize: integer;
begin
 iSize := Length(sStr) + 1;
 pwc := AllocMem(iSize * 2);
 MultiByteToWideChar(CP_ACP, 0, PChar(sStr), iSize, pwc,iSize * 2);
 Result := pwc;
end;

Procedure FlashEjectError(ErrorCode:DWORD);

Procedure ShowText(Txt:Pchar);
Begin
 MessageBox(GetForegroundWindow,Txt,'Status eject flash drive',0);
end;

Begin
 Case ErrorCode of
    ERROR_SUCCESS              : ShowText('The eject operation was successful.');
    ERROR_ACCESS_DENIED        : ShowText('NTMS_CONTROL_ACCESS to the library is denied. Other security errors'#13#10+
                                          'are also possible, but they would indicate a security subsystem error.');
    ERROR_DATABASE_FAILURE     : ShowText('The database is inaccessible or damaged.');
    ERROR_DATABASE_FULL        : ShowText('The database is full.');
    ERROR_DEVICE_NOT_AVAILABLE : ShowText('The library is disabled.');
    ERROR_INVALID_HANDLE       : ShowText('The session ID is invalid or missing.');
    ERROR_INVALID_OPERATION    : ShowText('A stop was performed on an invalid operation ID.');
    ERROR_INVALID_PARAMETER    : ShowText('A library ID or operation ID pointer is missing.');
    ERROR_LIBRARY_OFFLINE      : ShowText('The library ID refers to an offline library that cannot eject media.');
    ERROR_MEDIA_NOT_AVAILABLE  : ShowText('The media is disabled.');
    ERROR_NOT_ENOUGH_MEMORY    : ShowText('There was an allocation failure during processing.');
    ERROR_DEVICE__CAN_NOT_OPEN : ShowText('Can''not open device.') else
    ShowText(PChar('Unknown error code: '+IntToStr(ErrorCode)));
end;
end;

procedure TForm1.btnSafeEjectClick(Sender: TObject);
begin

 FlashEjectError                                              // \\.\PhysicalDrive1
 (
  EjectDiskFromSADriveW(nil,StringToPWideChar(Caption),'\\.\PhysicalDrive1',
  Handle,'exit?', 'Exit?',NTMS_EJECT_START)
 );

end;

end.


n0name   (2006-04-06 11:48:00) [39]


> "микроскоп штука хорошая, пока не начнёшь им гвозди забивать
> - неудобства начинаются почти сразу - то по пальцам больше
> попадаешь, то гвоздики не так вбиваются.."

Ага, поэтому надо делать через SetupAPI =)


Игорь Шевченко   (2006-04-06 10:54:00) [40]


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


"микроскоп штука хорошая, пока не начнёшь им гвозди забивать - неудобства начинаются почти сразу - то по пальцам больше попадаешь, то гвоздики не так вбиваются.."


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

Наверх

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