Следующий код скопирован из MS Async Filter. Предполагается, что следующий код вызывает либо CancelIo, либо CancelIoEx. В любом случае я не вижу, где вызывается CancelIoEx. Предполагается, что typedef представляет CancelIoEx, но никогда не вызывается. Какая именно линия bResult = (pfnCancelIoEx)(m_hFile, NULL);
делается?
// Cancel: Cancels pending I/O requests.
HRESULT CFileStream::Cancel()
{
CAutoLock lock(&m_CritSec);
// Use CancelIoEx if available, otherwise use CancelIo.
typedef BOOL (*CANCELIOEXPROC)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
BOOL bResult = 0;
CANCELIOEXPROC pfnCancelIoEx = NULL;HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll");
if (hKernel32){
//propably bad code !!! Take Care.
bResult = (pfnCancelIoEx)(m_hFile, NULL);
FreeLibrary(hKernel32);
}
else {
bResult = CancelIo(m_hFile);
}
if (!bResult) {
return HRESULT_FROM_WIN32(GetLastError());
}
return S_OK;
}
Предполагая, что это весь код, в нем есть серьезная ошибка. Это:
CANCELIOEXPROC pfnCancelIoEx = NULL;
определяет pfnCancelIoEx
как указатель на функцию, чья подпись совпадает с сигнатурой CancelIoEx
, Указатель инициализируется нулевым значением, и очевидным намерением является указать его на CancelIoEx
потом.
Эта функция определена в Kernel32.dll
так что загрузка это логичный следующий шаг. Если это удастся, код следует продолжить делая это:
pfnCancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
И тогда он должен проверить результат. Тем не мение, это не делает ни того, ни другого.
Далее по этой строке:
bResult = (pfnCancelIoEx)(m_hFile, NULL);
он пытается вызвать функцию, указанную pfnCancelIoEx
, Однако этот указатель никогда не изменяется от своего начального нулевого значения, поэтому он будет пытаться разыменовать нулевой указатель, что приведет к неопределенному поведению и вероятности сбоя.
Других решений пока нет …