Sign in to follow this  
Followers 0
enneract

Detect CTRL ALT DEL screen

11 posts in this topic

I hate to start multiple topics, but this is far enough afield from my other to warrant it, I think.

I'm trying to find a way to detect the presence of the ctrl-alt-del lock screen, preferably in a way that doesn't require polling, so that I can delay components of script execution until the screen is no longer present.

I've been searching for the past two hours or so, with only a reference to looking for the presence of a window titled "Program Manager" to detect if the screen is not present, but this doesn't seem to do anything.

Alternatively, a way to register WM_DISPLAYCHANGE and preform file copy operations while the lock screen is present would also work very well.

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Now don't ask me about the event "Global Const $EVENT_OPEN_DESKTOP_CHANGED = 0x0020". Found it by trial an error, otherwise it seems to be undocumented :blink:, hell, it could even mean something completely different ;) ...

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.1
 Author:         KaFu

 Script Function:
    Use a WinEventHook to detect a Desktop Change

#ce ----------------------------------------------------------------------------

HotKeySet("{ESC}", "_Exit")

#region ; WinEventHook

; Event Constants
; http://msdn.microsoft.com/en-us/library/ms697187.aspx
; http://msdn.microsoft.com/en-us/library/dd318066(VS.85).aspx
; http://mwinapi.sourceforge.net/doc/html/T_ManagedWinapi_Accessibility_AccessibleEventType.htm
; http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/accessibility/AccConst.html

Global Const $EVENT_OPEN_DESKTOP_CHANGED = 0x0020 ; Undocumented? Found by trial&error...

$h_DLL_User32 = DllOpen("User32.dll")
$h_WinEventHook_Proc = DllCallbackRegister("_WinEventHook_Proc", "none", "hwnd;int;hwnd;long;long;int;int")
If @error Then
    MsgBox(16 + 262144, "Error", "DllCallbackRegister(_WinEventHook_Proc) did not succeed. FFH will exit now.")
    Exit
EndIf
$h_Hook = _WinEventHook_Set(0x0020, 0x0020, $h_DLL_User32)
If @error Then
    MsgBox(16 + 262144, "Error", "_WinEventHook_Set() did not succeed. FFH will exit now.")
    Exit
EndIf
OnAutoItExitRegister("_WinEventHook_UnSet")
#endregion ; WinEventHook

while 1
    sleep(10)
wend

#region ; WinEventHook Functions
Func _WinEventHook_Proc($h_Hook, $iEvent, $hWnd, $idObject, $idChild, $iEventThread, $iEventTime)
    ;ConsoleWrite($hWnd & @TAB & $idObject & @CRLF)
    ConsoleWrite(TimerInit() & @tab & hex($iEvent,4) & @tab & "IsDesktopLocked()" & @tab & IsDesktopLocked() & @crlf)
EndFunc   ;==>_WinEventHook_Proc

Func _WinEventHook_Set($iEventMin, $iEventMax, $hDLLUser32)
    Local $aRet
    Local Const $WINEVENT_OUTOFCONTEXT = 0x0
    Local Const $WINEVENT_SKIPOWNPROCESS = 0x2
    If Not $hDLLUser32 Or $hDLLUser32 = -1 Then $hDLLUser32 = "User32.dll"
    $aRet = DllCall($hDLLUser32, "hwnd", "SetWinEventHook", _
            "uint", $iEventMin, _
            "uint", $iEventMax, _
            "hwnd", 0, _
            "ptr", DllCallbackGetPtr($h_WinEventHook_Proc), _
            "int", 0, _
            "int", 0, _
            "uint", $WINEVENT_OUTOFCONTEXT) ; BitOR($WINEVENT_OUTOFCONTEXT, $WINEVENT_SKIPOWNPROCESS)
    If @error Then Return SetError(@error, 0, 0)
    Return $aRet[0]
EndFunc   ;==>_WinEventHook_Set

Func _WinEventHook_UnSet()
    If $h_WinEventHook_Proc Then
        DllCallbackFree($h_WinEventHook_Proc)
    EndIf
    If $h_Hook Then DllCall($h_DLL_User32, "int", "UnhookWinEvent", "hwnd", $h_Hook)
    If $h_DLL_User32 Then DllClose($h_DLL_User32)
EndFunc   ;==>_WinEventHook_UnSet
#endregion ; WinEventHook Functions

Func IsDesktopLocked()
    Local $hDesktop
    Local $iRet
    Local $iRC
    Local $sMsg
    Local Const $DESKTOP_SWITCHDESKTOP = 0x100
    $hDesktop = DllCall("User32.dll", "int", "OpenDesktop", "str", "Default", "int", 0, "int", 0, "int", $DESKTOP_SWITCHDESKTOP)
    $iRet = DllCall("User32.dll", "int", "SwitchDesktop", "int", $hDesktop[0])
    If IsArray($iRet) Then
        If $iRet[0] = 0 Then

            $iRC = 1
        ElseIf $iRet[0] = 1 Then

            $iRC = 0
        EndIf
    Else

    EndIf
    DllCall("User32.dll", "int", "CloseDesktop", "int", $hDesktop[0]);<-- handle returned by "OpenDesktop"
    ;$iRet = DllCall("User32.dll", "int", "CloseDesktop", "int", $iRet[0])
    Return ($iRC)
EndFunc   ;==>IsDesktopLocked

Func _Exit()
    Exit
EndFunc   ;==>_Exit
Edited by KaFu

Share this post


Link to post
Share on other sites

I don't understand that code, at all.

I can copy and paste with the best of them, but I don't even see how that code interfaces with anything? I see the hook, but I don't understand what triggers it, nor how I can reference it.

Can you shed some light, or point me in the direction of some reading material?

Share this post


Link to post
Share on other sites

Maybe you say us why you need it?

I need to delay operation of a script until the lock\welcome screen is no longer present.

The script's purpose is to counteract the lack of Win7's ability to use specific logon backgrounds for widescreen resolutions, and applies backgrounds based on whatever arbitrary resolution the desktop is set to, using WM_DISPLAYCHANGE to notice when the change happens. However, none of this seems to work if the logon\lock\welcome screen is up when the display change takes place, so I need to detect when that happens and poll the desktop resolution when the screen is exited.

#NoTrayIcon
$path     = "C:\Windows\System32\oobe\info\backgrounds\"
$last     = @DesktopHeight

Func On_Start()
    GUICreate("", 0,0,0,0) 
    GUIRegisterMsg(0x007E, "Display_Changed")
    Do_Copy()
EndFunc
    

Func Do_Copy()
    If NOT FileCopy($path & "background" & @DesktopWidth & "x" & @DesktopHeight & ".jpg", $path & "backgroundDefault.jpg", 1) Then
        SoundPlay(@WindowsDir & "\media\Windows Error.wav",1)
    EndIf
EndFunc 
    

Func Display_Changed()
    If $last <> @DesktopHeight Then
        Do_Copy()
        $last = @DesktopHeight
    EndIf
EndFunc

On_Start()
While 0 < 1
WEnd

Share this post


Link to post
Share on other sites

Can you shed some light, or point me in the direction of some reading material?

Copy the code to SciTE, run the code, lock your desktop and watch the console... you'll see yourself where to log in...

Share this post


Link to post
Share on other sites

Copy the code to SciTE, run the code, lock your desktop and watch the console... you'll see yourself where to log in...

Oooh, I see. _WinEventHook_Proc() is actions to be preformed on the hook.

Gotcha. Thanks a bunch, KaFu.

Share this post


Link to post
Share on other sites

Yep, _WinEventHook_Proc() is fired only, when a Desktop Switch is detected ;), you're welcome, I love tinkering around, just discovering the power of the hooks (sounds more like Peter Pan :blink: )...

Share this post


Link to post
Share on other sites

Recalled this thread, and wanted to figure out what was going on, so I looked deeper and found the 'undocumented' message KaFu is hooking really is documented (the links give you the names of all the events, but not the numbers). The numbers are defined in WinUser.h, however. And the one you found KaFu reads as this:

#define EVENT_SYSTEM_DESKTOPSWITCH 0x0020

The only issue with this is, it only works on Vista+ (its surrounded by a version check (v. 0x0600 min. [Vista]) during preprocessing).

Anyway, just thought I'd clean up that bit of confusion and document what I came across.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Your clarification is always appreciated :) ... seems like a bad habit of mine, saying something is undocumented even if it is (see also about the /u @comspec switch ;) ), I have to be more careful with that term :idiot: .

Edited by KaFu

Share this post


Link to post
Share on other sites

No problem.. we're all fumbling our way (at some stage or another) through the huge Windows programming interface and its various iterations.

By the way - using that hook for 'EVENT_SYSTEM_DESKTOPSWITCH' also allows one to detect when UAC has locked the screen. I hadn't noticed that because I kept UAC at the 2nd-to-lowest setting (Windows 7), which only gives a query messagebox. However, any higher - or if running on Vista - and that event fires, along with the faded background/locked desktop.

Having a function that detects 3 state changes is awesome, and I'm sure that will be of good use somewhere along the line. For XP, I think the WM_WTSSESSION_CHANGE message will suffice as an alternative to detect user-switching, workstation locking, and logging off. At the lowest end (of NT-based O/S's), Win 2000 would need Terminal Services installed, which (I believe) would enable that message.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0