SendSAS: Send Ctrl+Alt+Del

Post your working scripts, libraries and tools for AHK v1.1 and older
qwerty12
Posts: 468
Joined: 04 Mar 2016, 04:33
Contact:

SendSAS: Send Ctrl+Alt+Del

20 Jan 2017, 06:53

  • AutoHotkey must be installed with the "Run as UI Access" option introduced with 1.1.24.02 enabled
  • sas.dll's SendSAS function requires the system be configured to let UIA programs simulate C+A+D. If this script is launched elevated, it will change the setting itself and then put it back to what it was previously when done.
  • Works only with Windows 7 and above. On Windows Vista, this might work if you find your own copy of sas.dll. On XP, running as SYSTEM (or using the Task Scheduler) and doing this should work:
    Spoiler

Code: Select all

SendSAS(processWaitTimeout := 5)
{
	SysGet, isRdp, 4096
	if (isRdp) {
		;try ShellDispatch4 := ComObjCreate("{13709620-C279-11CE-A49E-444553540000}", "{efd84b2d-4bcf-4298-be25-eb542a59fbda}")
		;if (ShellDispatch4) {
		;	DllCall(NumGet(NumGet(ShellDispatch4+0)+40*A_PtrSize), "Ptr", ShellDispatch4)
		;	ObjRelease(ShellDispatch4)
		;}
		ComObjCreate("Shell.Application").WindowsSecurity
		return
	}

	isUiAccess := writtenSsasg := False

	RegRead SoftwareSASGeneration, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, SoftwareSASGeneration
	if ((ssasgNotExisting := ErrorLevel) || !(SoftwareSASGeneration & 0x2)) {
		if (!A_IsAdmin) {
			return
		} else {
			RegWrite REG_DWORD, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, SoftwareSASGeneration, 3 ; Enable services and Ease of Access apps (i.e., uiAccess applications) to simulate SAS
			writtenSsasg := !ErrorLevel
		}
	}

	if (DllCall("Advapi32\OpenProcessToken", "Ptr", DllCall("GetCurrentProcess", "Ptr"), "UInt", TOKEN_QUERY := 0x0008, "Ptr*", hToken)) {
		DllCall("Advapi32\GetTokenInformation", "Ptr", hToken, "UInt", TokenUIAccess := 26, "UInt*", isUiAccess, "UInt", 4, "UInt*", dwLengthNeeded)
		DllCall("CloseHandle", "Ptr", hToken)
	}
		
	if (isUiAccess) {
		DllCall("sas\SendSAS", "Int", True)
	} else {
		VarSetCapacity(rawUiaCommand, (260 + 1) * (A_IsUnicode + 1))
		
		if (!DllCall("Shlwapi\AssocQueryString", "UInt", ASSOCF_INIT_IGNOREUNKNOWN := 0x00000400, "UInt", ASSOCSTR_COMMAND := 1, "Str", ".ahk", "Str", "uiAccess", "Ptr", &rawUiaCommand, "UInt*", 260)) {
			ahkUiaCommand := SubStr(ahkUiaCommand, 1 + (isQuoted := NumGet(rawUiaCommand,, "Char") == Asc("""")), InStr((ahkUiaCommand := StrGet(&rawUiaCommand, "UTF-16")), ".exe") + StrLen("exe") - isQuoted)
			if (FileExist(ahkUiaCommand)) {
				PIPE_ACCESS_OUTBOUND := 2, FILE_FLAG_OVERLAPPED := 0x40000000, PIPE_TYPE_BYTE := 0, INVALID_HANDLE_VALUE := -1
				; MsgWaitForMultipleObjectsEx constants:
				WAIT_OBJECT_0 := 0x00000000, WAIT_FAILED := INFINITE := 0xFFFFFFFF, WAIT_TIMEOUT := 258, MWMO_ALERTABLE := 0x0002, MWMO_INPUTAVAILABLE := 0x0004
				QS_INPUT := (QS_MOUSE := (QS_MOUSEMOVE := 0x0002 | QS_MOUSEBUTTON := 0x0004)) | QS_KEY := 0x0001 | QS_RAWINPUT := 0x0400 ; QS_TOUCH and QS_POINTER are included on Windows 8+
				QS_ALLINPUT := QS_INPUT | QS_POSTMESSAGE := 0x0008 | QS_TIMER := 0x0010 | QS_PAINT := 0x0020 | QS_HOTKEY := 0x0080 | QS_SENDMESSAGE := 0x0040

				pipe_name := "AHK_" . A_ThisFunc . "_" . A_TickCount
				szCmdline := """" . ahkUiaCommand . """" . " /ErrorStdOut \\.\pipe\" . pipe_name

				; Based on Lexikos' code @ https://autohotkey.com/board/topic/23575-how-to-run-dynamic-script-through-a-pipe/ and YMP's @ http://forum.script-coding.com/viewtopic.php?id=12103
				if ((pipe_ga := DllCall("CreateNamedPipe", "Str", "\\.\pipe\" . pipe_name, "UInt", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, "UInt", PIPE_TYPE_BYTE, "UInt", 255, "UInt", 0, "UInt", 0, "UInt", 0, "Ptr", 0, "Ptr")) != INVALID_HANDLE_VALUE) {
					uiAccessAhkPid := 0
					if ((pipe := DllCall("CreateNamedPipe", "Str", "\\.\pipe\" . pipe_name, "UInt", PIPE_ACCESS_OUTBOUND, "UInt", PIPE_TYPE_BYTE, "UInt", 255, "UInt", 0, "UInt", 0, "UInt", 0, "Ptr", 0, "Ptr")) != INVALID_HANDLE_VALUE) {
						if ((hEvent := DllCall("CreateEvent", "Ptr", 0, "Int", True, "Int", False, "Ptr", 0, "Ptr"))) {
							 VarSetCapacity(OVERLAPPED, 8 + 3 * A_PtrSize, 0)
							,NumPut(hEvent, OVERLAPPED, 8 + 2 * A_PtrSize, "ptr")

							Run *open %szCmdline%, %A_WinDir%\system32, UseErrorLevel Hide, uiAccessAhkPid
							if (ErrorLevel != "ERROR") {
								DllCall("ConnectNamedPipe", "Ptr", pipe_ga, "Ptr", &OVERLAPPED)
								beginTick := A_TickCount
								while (True) {
									timeout := ((processWaitTimeout * 1000) + 250) - (A_TickCount - beginTick)
									if (timeout <= 0)
										break
									r := DllCall("MsgWaitForMultipleObjectsEx", "UInt", 1, "Ptr*", hEvent, "UInt", timeout, "UInt", QS_ALLINPUT, "UInt", MWMO_ALERTABLE | MWMO_INPUTAVAILABLE, "UInt")
									Sleep -1
									if (r == WAIT_OBJECT_0) {
										DllCall("ConnectNamedPipe", "Ptr", pipe, "Ptr", 0)
										Script := (A_IsUnicode ? chr(0xfeff) : chr(239) chr(187) chr(191)) . "#NoEnv`r`n#NoTrayIcon`r`n#SingleInstance Off`r`nDllCall(""sas\SendSAS"", ""Int"", True)"
										DllCall("WriteFile", "Ptr", pipe, "Str", Script, "UInt", (StrLen(Script)+1)*(A_IsUnicode + 1), "UInt*", 0, "Ptr", 0)
										break
									} else if (r == WAIT_FAILED || r == WAIT_TIMEOUT) {
										break
									}
								}
							}
							DllCall("CloseHandle", "Ptr", hEvent)
						}
						DllCall("CloseHandle", "Ptr", pipe)
					}
					DllCall("CloseHandle", "Ptr", pipe_ga)
					if (uiAccessAhkPid)
						Process, WaitClose, %uiAccessAhkPid%, %processWaitTimeout%
				}
			}
		}
	}

	if (writtenSsasg) {
		if (ssasgNotExisting)
			RegDelete HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, SoftwareSASGeneration
		else
			RegWrite REG_DWORD, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System, SoftwareSASGeneration, %SoftwareSASGeneration%
	}
}

User avatar
WAZAAAAA
Posts: 89
Joined: 13 Jan 2015, 19:48

Re: SendSAS: Send Ctrl+Alt+Del

05 Mar 2020, 00:35

thanks for the UI Access checker, stealing it

Code: Select all

if (DllCall("Advapi32\OpenProcessToken", "Ptr", DllCall("GetCurrentProcess", "Ptr"), "UInt", TOKEN_QUERY := 0x0008, "Ptr*", hToken)) {
	DllCall("Advapi32\GetTokenInformation", "Ptr", hToken, "UInt", TokenUIAccess := 26, "UInt*", isUiAccess, "UInt", 4, "UInt*", dwLengthNeeded)
	DllCall("CloseHandle", "Ptr", hToken)
}
if (isUiAccess) {
	MsgBox,UIA=ON
} else {
	MsgBox,UIA=OFF
}
YOU'RE NOT ALEXANDER
Aenfa
Posts: 13
Joined: 15 May 2016, 18:06

Re: SendSAS: Send Ctrl+Alt+Del

16 Aug 2022, 11:31

I have UAC disabled so can't get this to work. UI Access checker says UIA is off regardless even if I use the "Run with UIA Access" option or run it with "C:\Program Files\AutoHotkey\AutoHotkeyU64_UIA.exe". Is it possible for this to work without UAC enabled?

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 31 guests