Здравствуйте DT, Вы писали:
DT>Здравствуйте Dront, Вы писали:
DT>>>Непонятная закавыка — при вызове ReadFile (COM-клиент на VB) в нижеприведенном методе происходит неожиданное завершение работы клиента (если сконфигурировать в Release) или выдается сообщение "Debug assertion failed!" c комментарием "_CrtIsValidHeapPointer(pUserData)" в файле dbgheap.c (если сконфигурировать в Debug), которого, кстати, на моей машине в принципе нет. Причем последнее сообщение появляется при освобождении памяти из-под буфера free (buffer), а если эту строчку убрать, то происходит то же самое, что и в Release. Если закомментировать ReadFile, ошибка исчезает, но и необходимые функции тоже. Что делать?
D>><skipped>
DT>>> char *buffer = new char [Len + 1];
DT>>> ::SetFilePointer(hFile,0,NULL,FILE_BEGIN);
DT>>> ::ReadFile(hFile, &buffer, Len, &NoB, NULL);
D>><skipped>
D>>еще бы не вылетало
надо ::ReadFile(hFile, buffer, Len, &NoB, NULL);
D>>buffer — уже указатель.
DT>Интересно, а почему тогда у меня все замечательно работало и с указателем?
Так сказали уже, что макросы конвертации изпользует стек и из-за этого всё рушится, если конвертируемий буфер больше стека. Сам когда то на это налетел (где то тут даже про это упомянуто). Из-за этого макросы A2W, W2A, A2BSTR, BSTR2A итд. лучше не изпользовать для строк, которые длиннее 8 Kb. Я обошёлся путем выковыряния нужного кода из исходников ATL. То что получилось, можно посмотреть ниже. Работает нормально, самая длинная строка, которая попалась, была ~30 Mb
STDMETHODIMP CEDSDatabase::EDSWriteDUFFile(long lRecID, BSTR bstrFile, long lWriteMode, VARIANT_BOOL *pbResult)
{
.....
TCHAR szFile[_MAX_PATH];
BSTR bstrDUF = NULL;
USES_CONVERSION;
_tcscpy(szFile, OLE2T(bstrFile));
// Load DUF from file.
HANDLE hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwLen = ::GetFileSize(hFile, NULL);
DWORD dwBytesRead;
char *pszDUF = new char[dwLen + 1]; // array + terminator char
ReadFile(hFile, pszDUF, dwLen, &dwBytesRead, NULL);
CloseHandle(hFile);
if(dwLen == dwBytesRead)
{
char *pStartDUF = NULL;
pszDUF[dwLen] = '\0'; // zero terminator
// Search loaded file for DUF declaration start position.
pStartDUF = lstrstr(pszDUF, "<DeclarationFile ");
if(pStartDUF)
bstrDUF = Ansi2BSTR(pStartDUF, -1, CP_BALTIC);
}
delete [] pszDUF;
}
if(bstrDUF == NULL)
return E_FAIL;
.....
}
// =====[ функции конвертации строк ]=====
// Convert ANSI string to unicode OLE string (BSTR).
// Code page optional, system code page is used by default.
// Return converted BSTR or NULL, if error occurs.
inline BSTR Ansi2BSTR(LPCSTR lpsz, int nLen, UINT uiCP = CP_ACP)
{
BSTR bstr = NULL;
int nCnvLen = MultiByteToWideChar(uiCP, 0, lpsz, nLen, NULL, NULL);
bstr = ::SysAllocStringLen(NULL, nCnvLen);
if (bstr != NULL)
MultiByteToWideChar(uiCP, 0, lpsz, -1, bstr, nCnvLen);
return bstr;
}
// Convert unicode OLE string (BSTR) to ANSI string.
// Code page optional, system code page is used by default.
// Return converted ANSI string and length (terminating zero
// is not included) or zero, if conversion failed.
inline int BSTR2Ansi(BSTR bstr, LPSTR *lpsz, UINT uiCP = CP_ACP)
{
int iChars = SysStringLen(bstr);
int iRet = 0;
if(iChars)
{
*lpsz = new char[++iChars];
iRet = WideCharToMultiByte(uiCP, 0, bstr, -1, *lpsz, iChars, 0, 0);
}
return (iRet == 0) ? 0 : --iRet;
}