Есть простейший код, который пишет в файл поксоренный буфер Код (Text): if ( handle != INVALID_HANDLE_VALUE ) { DWORD unused; SIZE_T toWrite = strlen( Buffer ); VOID * tmp = (VOID *)memalloc(toWrite+1); memcpy(tmp, Buffer, toWrite); toWrite = encodeXor((LPSTR)tmp, toWrite); if (toWrite != 0 ) { WriteFile(handle, tmp, toWrite, &unused, 0); memfree(tmp); } CloseHandle( handle ); } Сам файл создается без проблем, буфер нормально ксорится, но на записи буфера в файл начинаются непонятки. По непонятной для меня причине записи в файл не происходит, хотя если заменить переменную "DWORD unused" на "LPDWORD unused" буфер в файл успеет записаться, однако тут же вылетит kernel32!WriteFile с ошибкой Access Violation. Ради эксперимента попробовал использовать fopen/fputs - результат тот же самый, записи не нет Я себе весь моск уже сломал...
Проблема точно не с WriteFile. Возможно длину передаёте неверную. Также хороший тон это проверять возвращаемое значение WriteFile.
Unused обнулял, заменял просто на 0 - толку нет. Контекст: Код вызывается на старте сервиса Windows - к svchost подгружается моя сервисная dll, в ServiceMain создается отдельный поток, где вызывается ряд функций. Все эти функции отрабатывают нормально, за исключением того кода, что я показал. Этот же самый код, вызванный просто для теста из _tmain какого-то постороннего проекта нормально работает.
Сейчас проверил - WriteFile вызывается, возвращает TRUE, unused нулю не равна, но записи нет. Пойду застрелюсь нахрен...
Использование Nt*-функции, а также обращение напрямую к int 0x2e шлюзу не помогло. Причина такого поведения так и осталась непонятой. Проблема была решена путем переноса функции в другую часть модуля, правильно это или нет, хз Было: Код (Text): __declspec(dllexport) void ServiceMain(void) { ULONG unused = 0; HANDLE mainThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&ServiceInit, NULL, 0, &unused); } void ServiceInit(void) { StartServiceCtrlDispatcher(DispatchTable); // blocking call InitMainModules(); } VOID InitMainModules() { Func1(); Func2(); SaveOptions();// <------- } Стало: Код (Text): __declspec(dllexport) void ServiceMain(void) { ULONG unused = 0; SaveOptions();// <------- HANDLE mainThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&ServiceInit, NULL, 0, &unused); } void ServiceInit(void) { StartServiceCtrlDispatcher(DispatchTable); } VOID InitMainModules() { Func1(); Func2(); }
1. Вообще-то LPTHREAD_START_ROUTINE принимает один параметр и стек там может нарушаться. 2. Если encodeXor использует какие-либо строковые функции - tmp не заканчивается нулём. 3. Если toWrite=0, то память не освободится.
А AsmGuru62 в первом пункте прав оказался, ServiceInit в моем случае должна выглядеть как static VOID ServiceInit(LPVOID param), тогда все работает нормально. Проглядел, каюсь AsmGuru62, спасибо!