А>Как определить заблокирована ли машина ? (типа isWorkstationLocked)

Я знаю два способа. Первый абсолютно точный, но достаточно сложный, второй эвристический (то есть не всегда дающий верный результат), но зато гораздо более простой.

Точный метод состоит в подмене GINA DLL или написании Winlogon Notification Package (последнее возможно только на Windows 2000). Суть в том, что смена состояний Logged Out -> Logged In -> Locked производится Winlogon и точная информация о текущем состоянии доступна только от Winlogon. Помимо сложностей в программировании и отладке (которые нас, конечно, не остановят), недостатками этого метода являются необходимость наличия административных привилегий в процессе установки и неизбежная перезагрузка при установке.

Эвристический метод состоит в наблюдении за текущим активным десктопом. Когда в системе есть интерактивный пользователь и компьютер не заблокирован, текущим является десктоп Winsta0\Default. Если активным является другой десктоп, значит, либо в системе никого нет, либо компьютер заблокирован, либо на экране скринсейвер, либо на экране окно Windows NT Security. В любом случае, это значит, что приложения текущего пользователя сейчас не видны, поэтому этот метод хорошо подходит в том случае, если, например, надо подавить вывод MessageBox, когда пользователь все равно его не увидит.

Код для этого метода совсем простой:
BOOL IsWorkStationLocked()
{
    HDESK hDesk = OpenInputDesktop(0, FALSE, DESKTOP_READOBJECTS);
    if (hDesk == NULL)
    return TRUE;

    TCHAR szName[80];
    DWORD cbName;
    BOOL bLocked;
    
    bLocked = !GetUserObjectInformation(hDesk, UOI_NAME, szName, 80, &cbName)
          || lstrcmpi(szName, _T("default")) != 0;

    CloseDesktop(hDesk);
    return bLocked;
}

Эта функция будет работать в интерактивных приложениях и в сервисах, запущенных под LocalSystem. В сервисах, запущенных под другими аккаунтами, она работать не будет.
Автор: Alex Fedotov    Оценить