Handle leaking in WinAPI CreateFile?

3.2k views Asked by At

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).

4

There are 4 answers

0
Svetlana On

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.

1
MSalters On

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.

2
lsalamon On

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

2
Jason Owen On

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.