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

C++: check if computer is locked

我想弄清楚计算机是否已锁定。

我查看了 LockWorkStation 函数,但我希望找到的函数是 IsWorkStationLocked


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

根据你给的same MSDN link,"Remarks"的第三段说:

This function has the same result as pressing Ctrl+Alt+Del and clicking Lock Workstation. To unlock the workstation, the user must log in. There is no function you can call to determine whether the workstation is locked. To receive notification when the user logs in, use the WTSRegisterSessionNotification function to receive WM_WTSSESSION_CHANGE messages. You can use session notifications to track the desktop state so you know whether it is possible to interact with the user.

对于windows7及以上的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;
}

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

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;
}

正如对 MGamsby 的 post 的改进:如果您的目标是 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);
}

注意: 我知道问题是关于 Windows 7 但您仍然可以使用 Win8.1 SDK 以 Win7 为目标,并且它可用于 VS2015 以后的版本。

编辑:糟糕。我刚刚意识到 OP 要求从 WinXP 开始,在这种情况下,是的,您确实需要弄乱 LoadLibrary() 等。对此感到抱歉。 我会在这里留下我的代码,以防它对任何人有用。