Question

I'm developing a Windows 7 application which has to prevent WinDVD from triggering new disc availability when inserted (i.e. inserting a DVD).

Background information:

I'm working out this little application for a company which has to compare two movie players at a time playing simultaneously the same DVD, from different drives.

They're doing heuristic quality testing to determine best DVD player at the moment to bundle it into their new line of PCs.

At the moment their best choice seem to be WinDVD, so every other test has to be conducted against it. Problem is, when they insert first DVD, it's all right the default player WinDVD starts.

Then when they insert the second disc, the default player responds first, so they are forced to close the window and open the other player they're testing.

This is done for many movies that represent a reference to them to spot color rendering and image quality. It becomes tedious for users to close the additional window when it shows up, as this operation is due to be repeated hundreds of times a week.

My program is trying to inhibit default player' second response

I thought to intercept a WM_DEVICECHANGE message to somehow create a global hook for it.

Problem is, intercepting WM_DEVICECHANGE works very well, but it doesn't block WinDVD's ability to trigger new units insertion, evidently letting the message being delivered anyways. Due to this I started thinking how to prevent that message being dispatched after my interception.

In order to realize this global hook I thought of, I'm using this line of code:

CurrentHook:=setwindowshookex(WH_CALLWNDPROC,HookProcAdd,LibHandle,0);

linked to the callback contained within a DLL of mine and I can see that WM_DEVICECHANGE is correctly intercepted, but as I said the message is still dispatched to the whole system.

Any suggestion appreciated.

Updates:

@TOndrej : I've tried what follows:

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;

but res is false every time. What am I missing?

Was it helpful?

Solution

For IOCTL_STORAGE_MCN_CONTROL control code, files must be opened with the FILE_READ_ATTRIBUTES access right:

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;

In my test, after CloseHandle, device notification is restored...

OTHER TIPS

The correct, official, and documented way to handle this is to suppress AutoRun programmably. If your app is not in the foreground to receive the "QueryCancelAutoPlay" message, your global hook should be able to respond to the message without dispatching it.

Why not just disable the CD autorun capability by setting the registry key HKLM\System\CurrentControlSet\Services\CDRom and set the key Autorun to 0 instead of 1?

The customer must launch each application separately, or maybe choose an "open with..." option, but that should be perfectly suitable for benchmark testing. By your description they are testing runtime performance and playback quality, not autorun capability.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top