C++ RDP连接钩子对每个连接调用两次

C++ RDP连接钩子对每个连接调用两次,c++,windows,winapi,C++,Windows,Winapi,我希望我的应用程序钩住指定计算机上所有会话的远程连接和断开连接事件 根据文档,我应该首先调用WTSRegisterSessionNotification函数: WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_ALL_SESSIONS); 然后在messages processor回调中,我应该在WM\u WTSSESSION\u CHANGE消息类型上执行所需的操作: LRESULT CALLBACK WndProc(HWND hWnd, UIN

我希望我的应用程序钩住指定计算机上所有会话的远程连接和断开连接事件

根据文档,我应该首先调用
WTSRegisterSessionNotification
函数:

WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_ALL_SESSIONS);
然后在messages processor回调中,我应该在
WM\u WTSSESSION\u CHANGE
消息类型上执行所需的操作:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_WTSSESSION_CHANGE:
    {
      // do stuff
      break;
    }
    }
}
然而,它的工作原理非常奇怪。每次我连接或断开与运行我的应用程序的计算机的连接时,
WTS\u REMOTE\u connect
WTS\u REMOTE\u disconnect
调用两次——在其中一个调用中,我可以获得用户名,在另一个调用中,我无法获得用户名(只是一个空字符串)

我发现了这个问题,但它有一个非常奇怪的公认答案:

嗯,答案似乎是这些领域是相当正常的 在终端服务/RDP会话上为空


我不明白为什么它实际上是这样工作的。

这里有一个猜测:既然您请求了所有会话的通知,那么您可能还会收到会话0(非交互式会话)的回调?没有用户名将是一个强烈的迹象。@IInspectable好吧,这种连接和断开连接的会话ID与0不同(可以是2、5或任何值)@IInspectable的点仍然有效。系统可以为每个用户连接建立多个连接,其中一些连接可能是非交互式的。作为旁注,您使用ANSI版本的
WTSQuerySessionInformation
有什么原因吗?这里有一个猜测:既然您请求了所有会话的通知,可能您也会收到会话0(非交互式会话)的回调?没有用户名将是一个强烈的迹象。@IInspectable好吧,这种连接和断开连接的会话ID与0不同(可以是2、5或任何值)@IInspectable的点仍然有效。系统可以为每个用户连接建立多个连接,其中一些连接可能是非交互式的。作为旁注,您使用ANSI版本的
WTSQuerySessionInformation
有什么原因吗?
  case WM_WTSSESSION_CHANGE:
  {
    const int reason = (int)wParam;
    const DWORD sessionId = (DWORD)lParam;
    switch (reason)
    {
    case WTS_REMOTE_CONNECT:
    {
        DWORD bytesReturned = 0;
        LPSTR pData = NULL;
        if (WTSQuerySessionInformationA(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, &pData, &bytesReturned) == 0)
        {
          // Handle error
          break;
        }

        const std::string username = pData;
        WTSFreeMemory(pData);

        // do other stuff