views:

647

answers:

4

CreateFile allocates 2(!!) handles and CloseHandle closes only one handle when trying to get the low-level access to cd-rom device. OS Windows XP SP3, 5 of 7 tested computers works the same.

When trying to access hdd drive letter CreateFiles works OK and allocate only one handle.

Here is the sample code:

HANDLE m_driveHandle = CreateFileW("\\\\.\\E", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(m_driveHandle);

What is the possible reason or it's just a microsoft bug?

Upd. The drive name was'nt cut&pasted.. The right string is L"\\.\E:". Bug still persists.

Upd2. Problem solved! See the answer below from me (omega).

A: 

Suggestion:
Put log begin at call CreateFileW, this confirm how many times it is executed;

lsalamon
It is the clear sample program, one string for createFile an в one for close handle.
Omega
You check the Jason Owen said about string L"\\\\.\\E:" ?
lsalamon
Yes! It is an update in the text..
Omega
+1  A: 

There seem to be a few bugs in your sample code. If it was in fact copy & pasted from your program, then there would have to be something else going on.

First, you're calling a Unicode function with a MBCS string: the first argument should either be prepended with L or surrounded with _T().

Second, and perhaps more importantly, "\\\\.\\E" is not a valid name. You're missing a trailing colon: for opening a volume, it needs to be of the form \\.\X:, or in your case "\\\\.\\E:".

After fixing those two bugs (the first preventing compilation, the second required to get anything other than INVALID_HANDLE_VALUE back), everything seemed to be working as expected. I used GetProcessHandleCount to count the number of open handles, and it was the same before and after:

HANDLE m_driveHandle = NULL;
HANDLE m_process = GetCurrentProcess();
DWORD handleCount;
GetProcessHandleCount(m_process, &handleCount);
cout << "Currently held handles: " << handleCount << endl;

for (int i = 0; i < 10; ++i) {
 m_driveHandle = CreateFileW(L"\\\\.\\E:",
  GENERIC_READ | GENERIC_WRITE,
  FILE_SHARE_READ | FILE_SHARE_WRITE,
  NULL,
  OPEN_EXISTING,
  FILE_ATTRIBUTE_NORMAL,
  NULL
 );
 if (INVALID_HANDLE_VALUE == m_driveHandle) {
  cout << "Invalid handle" << endl;
 } else {
  CloseHandle(m_driveHandle);
 }

 GetProcessHandleCount(m_process, &handleCount);
 cout << "Currently held handles: " << handleCount << endl;
}

Commenting out the CloseHandle call causes handleCount to increment as expected, as well.

Jason Owen
Omega
Does the sample program I wrote above leak handles when you compile it? Or is the number of handles open on the first line equal to the number of handles open on the last line?
Jason Owen
Yes, it still leak handles.
Omega
A: 

Have you tried SysInternals' "Handle" tool ? It can show you every handle opened by your program, not just a count. Hence, you'll know which handle remains open.

MSalters
I tried sysinternal's russinovich's tool ProcessExplorer. Here 2 handles also, it's show two handles as two kernel objects.
Omega
A: 

The problem was in the Kaspersky Antivirus software. KAV 6.0 was installed on all tested machines. After removing the software it is needed to clear the UpperFilters and LowerFilters for the cd-driver in the registry:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class{4D36E965-E325-11CE-BFC1-08002BE10318}

Only after this steps handles stop leaking.. A newest version of the software, Kaspersky Internet Security, also works without leaking.

Omega