Page 1 of 1

detect if windows session is locked

Posted: Tue Mar 09, 2010 8:29 pm
by yabune
Hi,

How can I detect if a windows session is locked?

thanks!

Re: detect if windows session is locked

Posted: Thu May 27, 2010 10:22 pm
by SFSxOI
A widnows session can indeed be detected for lock status. The WTSRegisterSessionNotification() API in wtsapi32.dll can be used. Take a look at http://msdn.microsoft.com/en-us/library/Aa383841 There is even visual basic 8 code which you should be able to convert to PureBasic.

Another more crude way is just for lock status for the desktop which is available via OpenInputDesktop() API in user32.dll, but if memory serves me correctly its very sensitive to account privilages. Basically and real quick from memory for OpenInputDesktop, it looks something like this:

Code: Select all

Procedure MachineLocked()
lockstat.i

Lib_LockStat = LoadLibrary_("user32.dll")
*Func_OpenInputDesktop = GetProcAddress_(Lib_LockStat, "OpenInputDesktop")

hDesktopAccess.i = CallFunctionFast(*Func_OpenInputDesktop, dwFlags, fInherit, dwDesiredAccess, @lockstat)

FreeLibrary_(Lib_LockStat)

If lockstat < 1	
  ProcedureReturn #True
  Else
  ProcedureReturn #False
EndIf

EndProcedure
I've got something for WTSRegisterSessionNotification() too, somewhere and can't find it right now, but it was just the code from the MSDN link above converted anyway and its not hard to convert. Is this what you were lookin for? Hope it helps.

Re: detect if windows session is locked

Posted: Fri May 28, 2010 11:36 am
by Mr Coder
I read in another thread that GetForegroundWindow_() returns 0 if the workstation is locked, and yep, works fine here with XP and 7.

Re: detect if windows session is locked

Posted: Sat Feb 10, 2018 2:46 am
by Dude
SFSxOI wrote:real quick from memory for OpenInputDesktop, it looks something like this [snip]
SFSxOI's code crashes on Win 7 (illegal memory access). Anyone know how to fix it, to detect when the PC is locked? Thanks!

Also, why does this code return a different handle to the desktop all the time, when there's only one desktop in use?

Code: Select all

Repeat
  Debug OpenInputDesktop_(0,0,0)
  Sleep_(250)
ForEver

Re: detect if windows session is locked

Posted: Sat Feb 10, 2018 4:40 am
by RASHAD
Hi Dude

Code: Select all

GetDesktopWindow_()                    ;Return Root Desktop(Main Desktop Handle)  
OpenDesktop_(@"Default", 0, #False, 0) ;Return Thread Desktop Handle
threadID = GetCurrentThreadId_()
GetThreadDesktop_(threadID)            ;Return Thread Desktop Handle

Try

Code: Select all

Repeat
  thHwnd = OpenDesktop_(@"Default", 0, #False, #DESKTOP_SWITCHDESKTOP)
  If thHwnd
    SetThreadDesktop_(thHwnd)
    result = SwitchDesktop_(thHwnd)
    If result = 0
      Debug "Locked"
      CloseDesktop_(thHwnd)
    Else
      CloseDesktop_(thHwnd)
      Debug "Not Locked"
    EndIf
    Delay(500)
  EndIf
ForEver

Re: detect if windows session is locked

Posted: Sun Mar 11, 2018 12:40 pm
by Dude
Thank you, Rashad -- works great! 8)

Note: I had to remove SetThreadDesktop_(thHwnd) because it was making OpenWindow() and MessageRequesters() be shown on another (unseen) desktop, because I need to check the lock state every second (for a timer tool).

Re: detect if windows session is locked

Posted: Sun Oct 03, 2021 10:56 am
by BarryG
None of these examples work with Windows 10 anymore. Anyone know how to do with Win 10, but also stay compatible with at least Win 7?

I tried several different methods, and one is that when Win 10 is locked, the foreground window has a caption of "Windows Default Lock Screen", but I doubt that will be the same in all languages, and even if it were, it wouldn't work with Win 7. Kinda stuck at the moment because my app plays reminder sounds but I don't want them played if the PC is locked.

I also read that waiting for #WM_WTSSESSION_CHANGE in a callback would work, but that assumes my app is running. My app can (and will) start sometimes when the PC is already locked, so won't be able to catch this message.

Any ideas? Thanks.

Re: detect if windows session is locked

Posted: Sun Oct 03, 2021 11:59 am
by Mijikai
Try this:

Code: Select all

Macro IsLocked()
  Bool(GetForegroundWindow_() = #Null)
EndMacro

Re: detect if windows session is locked

Posted: Sun Oct 03, 2021 12:05 pm
by BarryG
Nope, that doesn't work anymore. It returns 0 even if the PC is locked, because GetForegroundWindow_() no longer returns 0 on Win 10 for a locked PC. As mentioned above, that only worked for Win XP and Win 7.

Re: detect if windows session is locked

Posted: Sun Oct 03, 2021 1:21 pm
by Mijikai
Ok here is what i came up with:

Code: Select all

EnableExplicit

Procedure.i IsLocked()
  Protected handle.i
  Protected *ProcessIdToSessionId
  Protected *WTSQuerySessionInformation
  Protected *WTSFreeMemory
  Protected sid.i 
  Protected bytes.i
  handle = LoadLibrary_("Wtsapi32.dll")
  *ProcessIdToSessionId = GetProcAddress_(GetModuleHandle_("kernel32.dll"),?ProcessIdToSessionId)
  *WTSQuerySessionInformation = GetProcAddress_(handle,?WTSQuerySessionInformation)
  *WTSFreeMemory = GetProcAddress_(handle,?WTSFreeMemory)
  If *ProcessIdToSessionId And *WTSQuerySessionInformation And *WTSFreeMemory
    If CallFunctionFast(*ProcessIdToSessionId,GetCurrentProcessId_(),@sid)
      If CallFunctionFast(*WTSQuerySessionInformation,#Null,sid,25,@handle,@bytes)
        bytes = PeekL(handle + $10)
        CallFunctionFast(*WTSFreeMemory,handle)  
        If OSVersion() = #PB_OS_Windows_7 Or OSVersion() = #PB_OS_Windows_Server_2008_R2
          ProcedureReturn bytes
        Else
          ProcedureReturn Bool(bytes = #False)
        EndIf
      EndIf
    EndIf
  Else
    handle = OpenDesktop_("Default",#Null,#False,#DESKTOP_SWITCHDESKTOP)
    If handle
      bytes = SwitchDesktop_(handle)
      CloseDesktop_(handle)
      ProcedureReturn Bool(bytes = #Null)
    EndIf
  EndIf
  ProcedureReturn #False
  ProcessIdToSessionId:
  !db 'ProcessIdToSessionId',0x0
  WTSQuerySessionInformation:
  !db 'WTSQuerySessionInformationW',0x0
  WTSFreeMemory:
  !db 'WTSFreeMemory',0x0
EndProcedure

Debug IsLocked()

End

Re: detect if windows session is locked

Posted: Fri Oct 29, 2021 12:25 pm
by BarryG
Mijikai, that works perfect on Win 10, but not on Win XP. I don't have Win 7 to test it on - can someone here with 7 and/or Vista try it?

For now, I will use Mijikai's code for Win 10 and later, and Rashad's code for anything up to but not including Win 10. Thanks, Mijikai.

[Edit] Doesn't work with the new C backend. Bug report here -> viewtopic.php?f=43&t=78145

Re: detect if windows session is locked

Posted: Fri Oct 29, 2021 2:34 pm
by juergenkulow
Hello Mijikai,
can you test this code, I am not sure.

Code: Select all

CompilerIf Defined(PB_Compiler_Backend,#PB_Constant) 
  CompilerIf #PB_Compiler_Backend=#PB_Backend_C
  DataSection
    ProcessIdToSessionId:
    Data.b 0
    WTSQuerySessionInformation:
    Data.b 0
    WTSFreeMemory:
    Data.b 0
  EndDataSection
  CompilerEndIf 
CompilerEndIf

Re: detect if windows session is locked

Posted: Sat Oct 30, 2021 3:48 pm
by infratec
I think this is the way to go;

Code: Select all

DataSection
  ProcessIdToSessionId:
  Data.a 'P','r','o','c','e','s','s','I','d','T','o','S','e','s','s','i','o','n','I','d',0
  WTSQuerySessionInformation:
  Data.a  'W','T','S','Q','u','e','r','y','S','e','s','s','i','o','n','I','n','f','o','r','m','a','t','i','o','n','W',0
  WTSFreeMemory:
  Data.a 'W','T','S','F','r','e','e','M','e','m','o','r','y',0
EndDataSection
It should work with all compilers :wink:

Re: detect if windows session is locked

Posted: Wed Mar 06, 2024 10:03 am
by BarryG
Thanks infratec! Using Data with broken-up text into characters has freed me of using ASM for this procedure! :) Don't know why I missed your reply several years ago.