C++:检查计算机是否已锁定

ida*_*hmu 4 c++ windows-xp windows-7

我正在试图弄清楚计算机是否已锁定.

我看过LockWorkStation的功能,但我希望找到的功能是IsWorkStationLocked.


我需要支持所有windows版本> = XP

小智 11

对于Windows 7和abowe,可以使用WTS API:

bool IsSessionLocked() {
    typedef BOOL (PASCAL * WTSQuerySessionInformation)(HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned);
    typedef void (PASCAL * WTSFreeMemory)( PVOID pMemory);

    WTSINFOEXW * pInfo = NULL;
    WTS_INFO_CLASS wtsic = DW_WTSSessionInfoEx;
    bool bRet = false;
    LPTSTR ppBuffer = NULL;
    DWORD dwBytesReturned = 0;
    LONG dwFlags = 0;
    WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
    WTSFreeMemory pWTSFreeMemory = NULL;

    HMODULE hLib = LoadLibrary( _T("wtsapi32.dll") );
    if (!hLib) {
        return false;
    }
    pWTSQuerySessionInformation = (WTSQuerySessionInformation)GetProcAddress(hLib, "WTSQuerySessionInformationW" );
    if (!pWTSQuerySessionInformation) {
        goto EXIT;
    }

    pWTSFreeMemory = (WTSFreeMemory)GetProcAddress(hLib, "WTSFreeMemory" );
    if (pWTSFreeMemory == NULL) {
        goto EXIT;
    }

    if(pWTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, g_dwSessionID, wtsic, &ppBuffer, &dwBytesReturned)) {
        if(dwBytesReturned > 0) {
            pInfo =  (WTSINFOEXW*)ppBuffer; 
            if (pInfo->Level == 1) {
                dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
            }
            if (dwFlags == WTS_SESSIONSTATE_LOCK) {
                bRet = true;
            }
        }
        pWTSFreeMemory(ppBuffer);
        ppBuffer = NULL;
    }
EXIT:
    if (hLib != NULL) {
        FreeLibrary(hLib);
    }
    return bRet;
}
Run Code Online (Sandbox Code Playgroud)

有关WTSINFOEX结构支持的平台,请查看以下文章:https://technet.microsoft.com/ru-ru/sysinternals/ee621017


Pet*_*ter 5

从您提供的相同MSDN链接,"备注"的第三段说:

此功能与按Ctrl + Alt + Del并单击"锁定工作站"的结果相同.要解锁工作站,用户必须登录.没有可以调用的功能来确定工作站是否已锁定.要在用户登录时接收通知,请使用WTSRegisterSessionNotification函数接收WM_WTSSESSION_CHANGE消息.您可以使用会话通知来跟踪桌面状态,以便了解是否可以与用户进行交互.


MGa*_*sby 5

Alex Vershynin 的版本运行良好,我必须进行一些代码更改。

我必须:将 DW_WTSSessionInfoEx 更改为 WTSSessionInfoEx(回答 user586399),将“g_dwSessionID”定义为 WTSGetActiveConsoleSessionId(),包括 Wtsapi32.h。我想就是这样...

由于我无法发表评论,我将在此处粘贴整个代码。

#include "Wtsapi32.h"
bool IsSessionLocked()
{
    typedef BOOL( PASCAL * WTSQuerySessionInformation )( HANDLE hServer, DWORD SessionId, WTS_INFO_CLASS WTSInfoClass, LPTSTR* ppBuffer, DWORD* pBytesReturned );
    typedef void ( PASCAL * WTSFreeMemory )( PVOID pMemory );

    WTSINFOEXW * pInfo = NULL;
    WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
    bool bRet = false;
    LPTSTR ppBuffer = NULL;
    DWORD dwBytesReturned = 0;
    LONG dwFlags = 0;
    WTSQuerySessionInformation pWTSQuerySessionInformation = NULL;
    WTSFreeMemory pWTSFreeMemory = NULL;

    HMODULE hLib = LoadLibrary( "wtsapi32.dll" );
    if( !hLib )
    {
        return false;
    }
    pWTSQuerySessionInformation = (WTSQuerySessionInformation) GetProcAddress( hLib, "WTSQuerySessionInformationW" );
    if( pWTSQuerySessionInformation )
    {
        pWTSFreeMemory = (WTSFreeMemory) GetProcAddress( hLib, "WTSFreeMemory" );
        if( pWTSFreeMemory != NULL )
        {
            DWORD dwSessionID = WTSGetActiveConsoleSessionId();
            if( pWTSQuerySessionInformation( WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned ) )
            {
                if( dwBytesReturned > 0 )
                {
                    pInfo = (WTSINFOEXW*) ppBuffer;
                    if( pInfo->Level == 1 )
                    {
                        dwFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
                    }
                    if( dwFlags == WTS_SESSIONSTATE_LOCK )
                    {
                        bRet = true;
                    }
                }
                pWTSFreeMemory( ppBuffer );
                ppBuffer = NULL;
            }
        }
    }
    if( hLib != NULL )
    {
        FreeLibrary( hLib );
    }
    return bRet;
}
Run Code Online (Sandbox Code Playgroud)


Ins*_*nts 5

正如对 MGamsby 的帖子的改进:如果您的目标是 Win8.1 SDK 或 Win10 SDK,那么就没有必要乱用 GetProcAddress()、LoadLibrary() 和 WTSGetActiveConsoleSessionId(),并且代码会变得更加紧凑:

bool isSessionLocked()
{
    WTSINFOEXW* pInfo = NULL;
    WTS_INFO_CLASS wtsic = WTSSessionInfoEx;
    LPTSTR ppBuffer = NULL;
    DWORD dwBytesReturned = 0;
    LONG sessionFlags = WTS_SESSIONSTATE_UNKNOWN; // until we know otherwise. Prevents a false positive since WTS_SESSIONSTATE_LOCK == 0

    DWORD dwSessionID = WTSGetActiveConsoleSessionId();

    if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, dwSessionID, wtsic, &ppBuffer, &dwBytesReturned))
    {
        if (dwBytesReturned > 0)
        {
            pInfo = (WTSINFOEXW*)ppBuffer;
            if (pInfo->Level == 1)
            {
                sessionFlags = pInfo->Data.WTSInfoExLevel1.SessionFlags;
            }
        }
        WTSFreeMemory(ppBuffer);
        ppBuffer = NULL;
    }

    return (sessionFlags == WTS_SESSIONSTATE_LOCK);
}
Run Code Online (Sandbox Code Playgroud)

注意:我意识到问题是关于 Windows 7 的,但您仍然可以使用 Win8.1 SDK 以 Win7 为目标,并且它可以在 VS2015 中使用。

编辑:哎呀。我刚刚意识到OP要求WinXP以上版本,在这种情况下,是的,你确实需要搞乱LoadLibrary()等。对此感到抱歉。我将把我的代码留在这里,以防它对任何人有用。