Предотвращение отправки WM_DEVICECHANGE
Я разрабатываю приложение для Windows 7, которое должно предотвращать запуск WinDVD доступа к новому диску при вставке (т.е. вставке DVD).
Исходная информация:
Я работаю над небольшим приложением для компании, которая должна сравнивать два проигрывателя одновременно, воспроизводящих один и тот же DVD-диск с разных дисков.
Они проводят эвристическое тестирование качества, чтобы определить лучший DVD-плеер на данный момент для подключения его к новой линейке ПК.
На данный момент их лучшим выбором является WinDVD, поэтому все остальные тесты должны проводиться против него. Проблема в том, что когда они вставляют первый DVD, все в порядке, проигрыватель WinDVD по умолчанию запускается.
Затем, когда они вставляют второй диск, проигрыватель по умолчанию отвечает первым, поэтому они вынуждены закрыть окно и открыть другой проигрыватель, который они тестируют.
Это сделано для многих фильмов, которые представляют собой ссылку на них для точной цветопередачи и качества изображения. Пользователям становится утомительно закрывать дополнительное окно, когда оно появляется, поскольку эта операция должна повторяться сотни раз в неделю.
Моя программа пытается заблокировать второй ответ игрока по умолчанию
Я думал перехватить сообщение WM_DEVICECHANGE, чтобы каким-то образом создать для него глобальный хук.
Проблема в том, что перехват WM_DEVICECHANGE работает очень хорошо, но он не блокирует способность WinDVD инициировать вставку новых модулей, очевидно позволяя доставлять сообщение в любом случае. В связи с этим я начал думать, как предотвратить отправку этого сообщения после моего перехвата.
Чтобы реализовать этот глобальный хук, о котором я подумал, я использую следующую строку кода:
CurrentHook:=setwindowshookex(WH_CALLWNDPROC,HookProcAdd,LibHandle,0);
связан с обратным вызовом, содержащимся в моей DLL, и я вижу, что WM_DEVICECHANGE правильно перехвачен, но, как я уже сказал, сообщение все еще отправляется всей системе.
Любое предложение приветствуется.
Обновления:
@TOndrej: я пробовал, что следует:
var
rlen : DWORD;
pRelen : ^DWORD;
h : THandle;
val : Boolean;
pVal: ^Boolean;
res : Boolean;
begin
rlen := 0;
val := True;
pVal := @val;
pRelen := @val;
h := CreateFile(PChar('\\.\d:'), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil,
OPEN_EXISTING, 0, 0);
if h <> INVALID_HANDLE_VALUE then
begin
res:= DeviceIoControl(h,
IOCTL_STORAGE_MCN_CONTROL,
pVal,
SizeOf(val),
nil,
0,
rlen,
nil);
if not res then
begin
ShowMessage('Error');
end;
CloseHandle(h);
end;
end;
но Res ложно каждый раз. Что мне не хватает?
3 ответа
Для управляющего кода IOCTL_STORAGE_MCN_CONTROL файлы должны быть открыты с правом доступа FILE_READ_ATTRIBUTES:
var
rlen: DWORD;
pVal: PBOOL;
res: BOOL;
begin
rlen := 0;
GetMem(PVal,SizeOf(BOOL));
pVal^ := TRUE;
h := CreateFile(PChar('\\.\D:'),
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ OR FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0);
if h <> INVALID_HANDLE_VALUE then
begin
res:= DeviceIoControl(h,
IOCTL_STORAGE_MCN_CONTROL,
pVal,
SizeOf(BOOL),
nil,
0,
rlen,
nil);
if not res then
begin
ShowMessage('Error');
end else
begin
ShowMessage('Device Notification Disabled');
end;
// close file handle
CloseHandle(h);
// After CloseHandle, file notification is restored...
end;
end;
В моем тесте после CloseHandle уведомление устройства восстанавливается...
Правильный, официальный и документированный способ справиться с этим - программно подавить автозапуск. Если ваше приложение не на переднем плане, чтобы получить "QueryCancelAutoPlay"
сообщение, ваш глобальный хук должен иметь возможность отвечать на сообщение, не отправляя его.
Почему бы просто не отключить возможность автозапуска CD, установив ключ реестра HKLM\System\CurrentControlSet\Services\CDRom
и установить ключ Autorun
в 0
вместо 1
?
Клиент должен запускать каждое приложение отдельно или, возможно, выбрать вариант "открыть с помощью…", но это должно быть идеально подходящим для тестирования производительности. По вашему описанию они тестируют производительность во время выполнения и качество воспроизведения, а не возможность автозапуска.