Slow response to drive state(DVD,SD) if no disk in drive
Moderators: white, Hacker, petermad, Stefan2
Slow response to drive state(DVD,SD) if no disk in drive
Hello,
If "no disk" in drive - after click to any removable drive icon(DVD,SD), TCMD has very slow response to drive state.(similar as link to network drive)
Windows explorer response is fast.
TCMD use history and trying link to latest(removed) medium inserted to removable drive. Restart TCMD solve problem with (no)linked medium, but this is not optimal solution - response to drive(no medium) state is always slow.
FDD drive(with no floppy) response is OK in TCMD.
TCMD912/XP32
If "no disk" in drive - after click to any removable drive icon(DVD,SD), TCMD has very slow response to drive state.(similar as link to network drive)
Windows explorer response is fast.
TCMD use history and trying link to latest(removed) medium inserted to removable drive. Restart TCMD solve problem with (no)linked medium, but this is not optimal solution - response to drive(no medium) state is always slow.
FDD drive(with no floppy) response is OK in TCMD.
TCMD912/XP32
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I don't think there is anything I can do. TC uses functions like FindFirstFile or SetCurrentDirectory, and they sometimes have a long timeout. TC should show a wait dialog after about 1 second where you can cancel the operation.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I can confirm the problem.
My DVD drive is E: - when it is empty:
- when I call FindFirst('E:\*.*', ...) - it immediately returns ERROR_NOT_READY
- when I call SetCurrentDirectory('E:') - it immediately fails with ERROR_NOT_READY
- when I select E: in 32-bit or 64-bit TC, mouse cursor is changed to a waiting state and TC is thinking for about 3 seconds before displaying an error message.
Regards
My DVD drive is E: - when it is empty:
- when I call FindFirst('E:\*.*', ...) - it immediately returns ERROR_NOT_READY
- when I call SetCurrentDirectory('E:') - it immediately fails with ERROR_NOT_READY
- when I select E: in 32-bit or 64-bit TC, mouse cursor is changed to a waiting state and TC is thinking for about 3 seconds before displaying an error message.
Regards
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
I cannot reproduce your report: When FindFirstFile and/or SetCurrentDirectory is fast, TC is fast too. Tried with two different CD drives, one internal and one connected via USB.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I found the reason: TC assumes a default CDCloseDoor=1 configuration seting. After adding CDCloseDoor=0 to [Configuration] in wincmd.ini, the problem is solved.
For CDCloseDoor=1 setting (Totalcmd.exe, 9.20 Beta 5):
1) at 0x0041C20E, a call is executed: mciSendStringA('open e: type cdaudio alias ding', nil, 0, 0) - this call blocks execution for about 2 seconds
2) at 0x0041C20E, a call is executed: mciSendStringA('set ding door closed wait', nil, 0, 0) - this call blocks execution for about 0.5 second
3) at 0x0041C20E, a call is executed: mciSendStringA('close ding', nil, 0, 0)
4) at 0x0041C2EC, Sleep(500) is executed
5) at 0x0041C431, Sleep(1000) is executed
What is a purpose of these MCI calls?
Regards
For CDCloseDoor=1 setting (Totalcmd.exe, 9.20 Beta 5):
1) at 0x0041C20E, a call is executed: mciSendStringA('open e: type cdaudio alias ding', nil, 0, 0) - this call blocks execution for about 2 seconds
2) at 0x0041C20E, a call is executed: mciSendStringA('set ding door closed wait', nil, 0, 0) - this call blocks execution for about 0.5 second
3) at 0x0041C20E, a call is executed: mciSendStringA('close ding', nil, 0, 0)
4) at 0x0041C2EC, Sleep(500) is executed
5) at 0x0041C431, Sleep(1000) is executed
What is a purpose of these MCI calls?
Regards
With CDCloseDoor=0 is response the same as windows explorer. This solve problem with "response to drive state"
MarcinW: thank
MCI call: I also noticed it's. I am not programmer, but when testing TCMD in Dependency Walker i found MCI call, when make door closed/open .TCMD sounds are not associated with eject/close-here is no relation.
Here is relation with CD audio. TCMD tests if audioCD inserted and load/unload anytime mcicda.dll. Probably therefore is slow response(?). I mean, that TCMD first check for audioCD,no for data.This should be optimized.
MarcinW: thank
MCI call: I also noticed it's. I am not programmer, but when testing TCMD in Dependency Walker i found MCI call, when make door closed/open .TCMD sounds are not associated with eject/close-here is no relation.
Here is relation with CD audio. TCMD tests if audioCD inserted and load/unload anytime mcicda.dll. Probably therefore is slow response(?). I mean, that TCMD first check for audioCD,no for data.This should be optimized.
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
TC calls these to close an open CD drawer, so you can just open the drawer, put the CD/DVD in, and then switch to it in TC without closing the CD drawer manually.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
OK, thank for ifo about MCI function in this case.
For me is this function here unnecessary, but in some cases this may be usefull.
Therefore any switch for CDCloseDoor in TCMD config bar is need.
When I have to strain my hand to the DVD mechanic to insert or remove the media, it will make it easier for me to press the button on the mechanics before somewhere to catch something with the mouse.![Very Happy :D](./images/smilies/icon_biggrin.gif)
For me is this function here unnecessary, but in some cases this may be usefull.
Therefore any switch for CDCloseDoor in TCMD config bar is need.
When I have to strain my hand to the DVD mechanic to insert or remove the media, it will make it easier for me to press the button on the mechanics before somewhere to catch something with the mouse.
![Very Happy :D](./images/smilies/icon_biggrin.gif)
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
You can disable it:
wincmd.ini
[Configuration]
CdCloseDoor=0
wincmd.ini
[Configuration]
CdCloseDoor=0
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
I found some info here: https://ws0.org/windows-how-to-get-the-tray-status-of-the-optical-drive/
By using DeviceIoControl API with IOCTL_STORAGE_CHECK_VERIFY2 and IOCTL_SCSI_PASS_THROUGH_DIRECT control codes, we can check if:
- tray is ejected,
- tray is closed with some media inside,
- tray is closed with no media inside.
In opposite to MCI calls, IOCTL calls return immediately.
I created a piece of test code by using a sample code from the article mentioned above (I made some corrections though). Curently TC code looks like:
This could be improved in the following way:
Thanks to this change, TC could respond immediately, even for CDCloseDoor=1. The IsCDTrayEjected() function always returns True in case of any errors, so it will not break compatibility. It may even work on Win 9x systems, if the CD driver supports needed IOCTL codes (in other cases just True is returned). The code below has been sucessfully tested on two physical machines with DVD drives, where TC hangs for few seconds when accessing the drive - on Win 98, Win 2000 and Win 7 64-bit (both as 32-bit and 64-bit code).
Regards
By using DeviceIoControl API with IOCTL_STORAGE_CHECK_VERIFY2 and IOCTL_SCSI_PASS_THROUGH_DIRECT control codes, we can check if:
- tray is ejected,
- tray is closed with some media inside,
- tray is closed with no media inside.
In opposite to MCI calls, IOCTL calls return immediately.
I created a piece of test code by using a sample code from the article mentioned above (I made some corrections though). Curently TC code looks like:
Code: Select all
if CDCloseDoor <> 0 then
call MCI functions to close the CD tray
Code: Select all
if CDCloseDoor <> 0 then
if IsCDTrayEjected(DriveNum) then
call MCI functions to close the CD tray
Thanks to this change, TC could respond immediately, even for CDCloseDoor=1. The IsCDTrayEjected() function always returns True in case of any errors, so it will not break compatibility. It may even work on Win 9x systems, if the CD driver supports needed IOCTL codes (in other cases just True is returned). The code below has been sucessfully tested on two physical machines with DVD drives, where TC hangs for few seconds when accessing the drive - on Win 98, Win 2000 and Win 7 64-bit (both as 32-bit and 64-bit code).
Code: Select all
program CDTest;
uses
Windows;
type
SCSI_PASS_THROUGH_DIRECT = record
Length : Word;
ScsiStatus : Byte;
PathId : Byte;
TargetId : Byte;
Lun : Byte;
CdbLength : Byte;
SenseInfoLength : Byte;
DataIn : Byte;
DataTransferLength : Cardinal;
TimeOutValue : Cardinal;
DataBuffer : Pointer;
SenseInfoOffset : Cardinal;
Cdb : array[0..15] of Byte;
end;
const
IOCTL_STORAGE_CHECK_VERIFY2 = $002D0800;
IOCTL_SCSI_PASS_THROUGH_DIRECT = $0004D014;
const
SCSI_IOCTL_DATA_IN = 1;
const
FILE_SHARE_DELETE = 4;
// DriveNum: 0=A:, 1=B:, 2=C:, ...
function IsCDTrayEjected(DriveNum : Byte) : Boolean;
var
DeviceName : array[0..6] of WideChar;
HDevice : THandle;
BytesReturned : DWORD;
SCSIBuffer : record
SPTD : SCSI_PASS_THROUGH_DIRECT;
SenseBuffer : array[0..17] of Byte;
end;
DataBuffer : array[0..7] of Byte;
begin
Result:=True; // Return True in case of any errors
DeviceName[0]:='\';
DeviceName[1]:='\';
DeviceName[2]:='.';
DeviceName[3]:='\';
DeviceName[4]:=WideChar(Ord('A')+DriveNum);
DeviceName[5]:=':';
DeviceName[6]:=#0;
HDevice:=CreateFileW(DeviceName,0,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if HDevice = INVALID_HANDLE_VALUE then
Exit;
try
Result:=not DeviceIoControl(HDevice,IOCTL_STORAGE_CHECK_VERIFY2,nil,0,nil,0,BytesReturned,nil);
finally
CloseHandle(hDevice);
end;
if not Result then // Tray closed, media present
Exit;
HDevice:=CreateFileW(DeviceName,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if HDevice = INVALID_HANDLE_VALUE then
Exit;
try
FillChar(SCSIBuffer,SizeOf(SCSIBuffer),0);
with SCSIBuffer do
begin
SPTD.Length:=SizeOf(SPTD);
SPTD.CdbLength:=10;
SPTD.SenseInfoLength:=SizeOf(SenseBuffer);
SPTD.DataIn:=SCSI_IOCTL_DATA_IN;
SPTD.DataTransferLength:=SizeOf(DataBuffer);
SPTD.TimeOutValue:=1;
SPTD.DataBuffer:=@DataBuffer;
SPTD.SenseInfoOffset:=HINST(@SenseBuffer)-HINST(@SCSIBuffer);
SPTD.Cdb[0]:=$4A;
SPTD.Cdb[1]:=$01;
SPTD.Cdb[4]:=$10;
SPTD.Cdb[8]:=$08;
end;
FillChar(DataBuffer,SizeOf(DataBuffer),0);
BytesReturned:=0;
Result:=DeviceIoControl(HDevice,IOCTL_SCSI_PASS_THROUGH_DIRECT,@SCSIBuffer,SizeOf(SCSIBuffer),@SCSIBuffer,SizeOf(SCSIBuffer),BytesReturned,nil);
finally
CloseHandle(hDevice);
end;
if (not Result) or (BytesReturned < SizeOf(SCSIBuffer.SPTD)) then // Error
begin
Result:=True;
Exit;
end;
case DataBuffer[5] of
0 : Result:=False; // Tray closed, no media
1 : Result:=True; // Tray ejected
else Result:=False; // Tray closed, media present
end;
end;
var
DriveNum : Byte; // 0=A:, 1=B:, 2=C:, ...
begin
DriveNum:=0;
while True do
begin
if GetDriveType(PChar(string(Char(Ord('A')+DriveNum))+':')) = DRIVE_CDROM then
Break;
if DriveNum = 26 then
begin
MessageBox(0,'No CD drive found','Error',MB_ICONSTOP);
Exit;
end;
Inc(DriveNum);
end;
if IsCDTrayEjected(DriveNum) then
MessageBox(0,'Tray ejected (or error occured)',PChar('Drive '+Char(Ord('A')+DriveNum)+':'),MB_ICONINFORMATION)
else
MessageBox(0,'Tray closed',PChar('Drive '+Char(Ord('A')+DriveNum)+':'),MB_ICONINFORMATION);
end.
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact:
Unfortunately I have had mixed results with ioctl calls, it really depends on the driver and hardware. I'm using some calls to check whether a medium is in the drive or not when using HideRemovableNoMedia options. But I had to disable this because some users had complete lockups or long delays when this was enabled. The functions I use with CDCloseDoor have worked for many years. I prefer not to change them. The user can just set CdCloseDoor=0 if he doesn't need this function.
Author of Total Commander
https://www.ghisler.com
https://www.ghisler.com
- ghisler(Author)
- Site Admin
- Posts: 48088
- Joined: 2003-02-04, 09:46 UTC
- Location: Switzerland
- Contact: