rundll32加载的dll如何响应系统关机消息?

一个没有UI的ftp server程序,为响应关机消息,我使用RegisterClass、CreateWindowEx创建了一个隐藏窗口接受WM_QUERYENDSESSION、WM_ENDSESSION消息。下面是测试代码:

 LRESULT CALLBACK ShutdownDetectorWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    if (message == WM_QUERYENDSESSION)
    {
        MessageBoxA(0, 0, 0, 0);
        return TRUE;
    }
    else if (message == WM_ENDSESSION)
    {
        MessageBoxA(0, 0, 0, 0);
        return TRUE;
    }
    else if (message == WM_DESTROY)
    {
        PostQuitMessage(0);
        return 0;
    }
    else if (message == WM_CHAR)
    {
        MessageBoxA(0, 0, 0, 0);
        return TRUE;
    }
    else
    {
        return DefWindowProcA(hwnd, message, wParam, lParam);
    }
}


DWORD WINAPI Rundll32DetectLogoffThread(LPVOID lpParam)
{
    HINSTANCE *lpInstance = (HINSTANCE*)lpParam;

    HWND        hwnd;
    MSG         msg;
    WNDCLASS    wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = *lpInstance;
    wndclass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpfnWndProc = ShutdownDetectorWndProc;
    wndclass.lpszClassName = "ShutdownDetector";

    if (!RegisterClassA(&wndclass)) {
        return 1;
    }

    hwnd = CreateWindowExA(0,
                           wndclass.lpszClassName,  // window class name
                           "",              // window caption
                           WS_OVERLAPPEDWINDOW,     // window style
                           CW_USEDEFAULT,       // initial x position
                           CW_USEDEFAULT,       // initial y position
                           CW_USEDEFAULT,       // initial x size
                           CW_USEDEFAULT,       // initial y size
                           NULL,            // parent window handle
                           NULL,            // window menu handle
                           *lpInstance,         // program instance handle
                           NULL);

    if (!hwnd) {
        return 2;
    }

    ShowWindow(hwnd, SW_HIDE);
    UpdateWindow(hwnd);

    while (GetMessageA(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }

    return 0;
}

编译为EXE的时候,关机时正确的收到了消息,弹出了对话框。

但是,编译为DLL,使用rundll32执行的时候无法收到WM_QUERYENDSESSION、WM_ENDSESSION消息。但是,可以收到WM_CHAR消息。

请问这是为什么?

终于找到了原因。

其实我贴出来的代码并没有问题。不知道有没有人注意,我的Rundll32DetectLogoffThread是一个线程回调函数,所以我其实是用CreateThread新建了一个线程在接收消息。

测试结果是,只有在rundll32入口函数那个线程里,才能接收到关机消息,新建的线程收不到。但是,普通EXE新建的线程好像又可以收到。

为什么会这样还不知道,但问题总算是解决了。

看看rundll进程 它可能是system进程 不在当前用户session