1

Тема: AHK: Хоткей с экрана блокировки Windows

Подскажите, есть ли возможность обратится к скрипту AHK с помощью хоткея с экрана блокировки Windows?

2

Re: AHK: Хоткей с экрана блокировки Windows

Нету.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

3

Re: AHK: Хоткей с экрана блокировки Windows

Есть.
http://forum.script-coding.com/viewtopi … 03#p105903

4

Re: AHK: Хоткей с экрана блокировки Windows

Действительно, работает на экране блокировки. Но не работает в обычном режиме.

counter := 0
$!1:: SetTimer, Timer, 300

Timer:
   ToolTip % ++counter
   Return

Запускал так:

Run D:\DISTRIBUTs\PSTools\PsExec.exe /h /x /d /s "D:\OneDrive\Scripts\_Разработка\New8.exe"

от админа.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

5

Re: AHK: Хоткей с экрана блокировки Windows

Да, наверное, потому что запущено от SYSTEM.

6 (изменено: DrDron, 2018-11-02 10:29:42)

Re: AHK: Хоткей с экрана блокировки Windows

Спасибо, все работает!

7 (изменено: teadrinker, 2018-11-02 11:45:28)

Re: AHK: Хоткей с экрана блокировки Windows

Уточнение: компилировать скрипт не обязательно, можно запустить с помощью интерпретатора.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Skype dmitry_fiveg

8 (изменено: Malcev, 2020-05-11 20:26:01)

Re: AHK: Хоткей с экрана блокировки Windows

Благодаря стараниям qwerty12 такое можно провернуть и без PsExec.exe.
При нажатии f11 выскочит msgbox:

#NoEnv	; Recommended for performance and compatibility with future AutoHotkey releases.
;#Warn	; Enable warnings to assist with detecting common errors.
SendMode Input	; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%	 ; Ensures a consistent starting directory.
#SingleInstance Force
#KeyHistory 0
ListLines, Off
SetBatchLines, -1
#NoTrayIcon
#UseHook Off
DetectHiddenWindows On
CoordMode, Mouse, Screen

winlogonSessionIDs := []

if (!A_IsUnicode)
	ExitApp 1

if (LogonDesktop_IsScriptProcessSYSTEM()) { 
	if (!LogonDesktop_WaitForTermSrvInit()) ; Probably redundant since Task Scheduler starts this script so late, and probably checks itself...
		ExitApp 1

	LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)
	if (!LogonDesktop_GetTokenSessionId(hToken, scriptSessionId))
		ExitApp 1
	LogonDesktop_CloseHandle(hToken)
	if (!LogonDesktop_GetThreadDesktopName(desktopName))
		ExitApp 1

	if (scriptSessionId == 0) {
		if (!(wtsHandle := LogonDesktop_LoadWtsApi()))
		  ExitApp 1

		EnumerateSessionsAndLaunchWinlogonClient()

		if (DllCall("wtsapi32.dll\WTSRegisterSessionNotification", "Ptr", A_ScriptHwnd, "UInt", 1))
			OnMessage(WM_WTSSESSION_CHANGE := 0x2B1, "WM_WTSSESSION_CHANGE")
		
		OnExit("AtExit")
	} else {
		if (desktopName == "Winlogon") {
			Hotkey, f11, sendPassword, UseErrorLevel On
		}
	}
} else {
	if (A_IsAdmin) {
		LogonDesktop_AddTask(True, True)
	} else {
		Run *RunAs "%A_AhkPath%" "%A_ScriptFullPath%",, UseErrorLevel
	}
	ExitApp
}

sendPassword() {  
   msgbox
}

EnumerateSessionsAndLaunchWinlogonClient()
{
	global winlogonSessionIDs

	if (DllCall("wtsapi32\WTSEnumerateSessionsExW", "Ptr", 0, "UInt*", 1, "UInt", 0, "Ptr*", pSessionInfo, "UInt*", wtsSessionCount)) {
		cbWTS_SESSION_INFO_1 := A_PtrSize == 8 ? 56 : 32
		Loop % wtsSessionCount {
			currSessOffset := cbWTS_SESSION_INFO_1 * (A_Index - 1)
			;if (StrGet(NumGet(pSessionInfo+0, currSessOffset+(A_PtrSize == 8 ? 32 : 20), "Ptr"),, "UTF-16")) ; Poor person's WTSActive check
			if ((sessionId := NumGet(pSessionInfo+0, currSessOffset+8, "UInt"))) {
				if (DllCall("wtsapi32\WTSQuerySessionInformationW", "Ptr", 0, "UInt", sessionId, "UInt", WTSConnectState := 8, "Ptr*", pBuffer, "Ptr*", BytesReturned)) {
					if (BytesReturned == 4) {
						state := NumGet(pBuffer+0,, "UInt")
						if (state == 0 || state == 1) {
							foundSessionId := False
							for _, s in winlogonSessionIDs {
							  if (s == sessionId) {
								foundSessionId := True
								break
							   }
							}
							if (!foundSessionId) {
								if (LogonDesktop_LaunchOnWinlogonDesktop(DllCall("GetCommandLineW", "WStr") . " /force", sessionId))
									winlogonSessionIDs.Push(sessionId)
							}
						}
					}
					DllCall("wtsapi32\WTSFreeMemory", "Ptr", pBuffer)
				}
			}
		}
		DllCall("wtsapi32\WTSFreeMemoryExW", "UInt", 2, "Ptr", pSessionInfo, "UInt", wtsSessionCount)
	}
}

WM_WTSSESSION_CHANGE(wParam, lParam)
{
	Critical
	global winlogonSessionIDs, scriptSessionId
	if (scriptSessionId == 0) {
		if (wParam == 6) {
			winlogonSessionIDs.Delete(lParam)
		}
		else if (wParam == 1) {
			SetTimer, EnumerateSessionsAndLaunchWinlogonClient, -1000
		}
	}
	Critical Off
}

AtExit()
{
	global WM_WTSSESSION_CHANGE, wtsHandle

	OnExit(A_ThisFunc, 0)
	if (wtsHandle)
		OnMessage(WM_WTSSESSION_CHANGE, ""), DllCall("wtsapi32.dll\WTSUnRegisterSessionNotification", "Ptr", A_ScriptHwnd), LogonDesktop_UnloadWtsApi(wtsHandle), wtsHandle := 0
	return 0
}



; LogonDesktop - run scripts on the Winlogon desktop
; 26/02/17 - qwerty12

; Modified version of RunAsTask() by SKAN: https://autohotkey.com/boards/viewtopic.php?t=4334
LogonDesktop_AddTask(runNow, runOnStartup)
{
	local TaskName, XML, TaskSchd, TaskRoot, RunAsTask
	local TASK_CREATE := 0x2, TASK_LOGON_SERVICE_ACCOUNT := 5, scriptDir := A_ScriptDir

	try 
		TaskSchd := ComObjCreate("Schedule.Service"), TaskSchd.Connect(), TaskRoot := TaskSchd.GetFolder("\")
	catch
		return ""

	TaskName := "[AHKLogonDesktop]" . A_ScriptName . " - " . DllCall("NTDLL\RtlComputeCrc32", "Int", 0, "Ptr", &scriptDir, "UInt", StrLen(scriptDir) * 2, "UInt")

	try 
		RunAsTask := TaskRoot.GetTask(TaskName)
	catch
		RunAsTask := ""

	if (!RunAsTask) {
		trigger := runOnStartup ? "<Triggers><BootTrigger><Enabled>true</Enabled></BootTrigger></Triggers>" : "<Triggers />"

		XML := "
			( LTrim Join
			<?xml version=""1.0"" ?><Task xmlns=""http://schemas.microsoft.com/windows/2004/02/mit/task"">
			<RegistrationInfo />" . trigger . "<Principals><Principal id=""Author""><UserId>S-1-5-18</UserId><RunLevel>HighestAvailable</RunLevel>
			</Principal></Principals><Settings><MultipleInstancesPolicy>Parallel</MultipleInstancesPolicy>
			<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries><StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
			<AllowHardTerminate>false</AllowHardTerminate><StartWhenAvailable>false</StartWhenAvailable><RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAva
			ilable><IdleSettings><StopOnIdleEnd>false</StopOnIdleEnd><RestartOnIdle>false</RestartOnIdle></IdleS
			ettings><AllowStartOnDemand>true</AllowStartOnDemand><Enabled>true</Enabled><Hidden>false</Hidden><
			RunOnlyIfIdle>false</RunOnlyIfIdle><DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteApp
			Session><UseUnifiedSchedulingEngine>false</UseUnifiedSchedulingEngine><WakeToRun>false</WakeToRun><
			ExecutionTimeLimit>PT0S</ExecutionTimeLimit><Priority>4</Priority></Settings><Actions Context=""Author""><Exec>
			<Command>" . """" . A_AhkPath . """" . "</Command>
			<Arguments>" . (A_IsCompiled ? "" : """" . A_ScriptFullPath . """") . " /ErrorStdOut" . "</Arguments>
			<WorkingDirectory>" . scriptDir . "</WorkingDirectory></Exec></Actions></Task>
			)"
		TaskRoot.RegisterTask(TaskName, XML, TASK_CREATE, "", "", TASK_LOGON_SERVICE_ACCOUNT)
	}

	if (!RunAsTask) {
		try 
			RunAsTask := TaskRoot.GetTask(TaskName)
		catch
			return ""
	}

	if (runNow)
		RunAsTask.Run("")

	return TaskName
}

LogonDesktop_LaunchOnWinlogonDesktop(cmdLine, sessionId, ignoreSentinel := False, InheritHandles := False)
{
	static tokenPerms := 0x0100 | 0x0008 | 0x0002 | 0x0001, neededPrivs := {"SeTcbPrivilege": True, "SeImpersonatePrivilege": True, "SeAssignPrimaryTokenPrivilege": True, "SeIncreaseQuotaPrivilege": True} ; TOKEN_ADJUST_SESSIONID | TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY
	ret := False

	if (!ignoreSentinel) {
		EnvGet, _LOGON_DESKTOP_SENTINEL, _LOGON_DESKTOP_SENTINEL
		if (_LOGON_DESKTOP_SENTINEL == "1")
			return ret
	}

	if (LogonDesktop_AdjustThisProcessPrivileges(neededPrivs, PreviousState)) {
		if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), tokenPerms, hToken)) {
			if (LogonDesktop_DuplicateTokenEx(hToken, 0x02000000, 0, 1, 1, hNewToken)) { ; MAXIMUM_ALLOWED, SecurityIdentification, TokenPrimary
				if (_SetTokenInformation(hNewToken, 12, sessionId, 4, "UInt*")) { ; TokenSessionId
					EnvSet, _LOGON_DESKTOP_SENTINEL, 1
					ret := LogonDesktop_EasyCreateProcessUsingToken(hNewToken, cmdLine, "WinSta0\Winlogon", False, InheritHandles)
					EnvSet, _LOGON_DESKTOP_SENTINEL, 0
				}
				LogonDesktop_CloseHandle(hNewToken)
			}
			LogonDesktop_CloseHandle(hToken)
		}
		LogonDesktop_AdjustThisProcessPrivileges(0, PreviousState)
	}

	return ret
}

_IsSystemSid(pSid) {
	return DllCall("advapi32\IsWellKnownSid", "Ptr", pSid, "UInt", 22) ; WinLocalSystemSid
}

LogonDesktop_IsScriptProcessSYSTEM()
{
	ret := hToken := 0

	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0008, hToken)) { ; TOKEN_QUERY
		if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER))
			ret := _IsSystemSid(NumGet(TOKEN_USER,, "Ptr"))
		LogonDesktop_CloseHandle(hToken)
	}

	return ret
}

LogonDesktop_AdjustTokenPrivileges(hToken, privNames, ByRef PreviousState := 0, ByRef notAllAssigned := 0) {
	static cbTOKEN_PRIVILEGES := 16, skipPrivCount := cbTOKEN_PRIVILEGES - 4
	static LookupPrivilegeValueW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "LookupPrivilegeValueW", "Ptr"), AdjustTokenPrivileges := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "AdjustTokenPrivileges", "Ptr")
	ret := False

	DllCall("SetLastError", "UInt", 0)

	if (IsObject(privNames)) {
		if (!(privNamesOrPrevStateLen := privNames.SetCapacity(0)))
			return ret

		VarSetCapacity(TOKEN_PRIVILEGES, (sizeTp := 4 + (skipPrivCount * privNamesOrPrevStateLen)), 0)
		NumPut(privNamesOrPrevStateLen, TOKEN_PRIVILEGES,, "UInt")
		for priv, enabled in privNames {
			luidOffset := 4 + (skipPrivCount * (A_Index - 1))
			if (DllCall(LookupPrivilegeValueW, "Ptr", 0, "WStr", priv, "Ptr", &TOKEN_PRIVILEGES+luidOffset))
				if (enabled)
					NumPut(0x00000002, TOKEN_PRIVILEGES, luidOffset+8, "UInt")
		}
	} else {
		if (!privNames && !IsByRef(PreviousState))
			return ret
	}

	if (hToken) {
		psBr := IsByRef(PreviousState)
		if (privNames) {
			if (psBr)
				VarSetCapacity(PreviousState, sizeTp, 0)
			ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &TOKEN_PRIVILEGES, "UInt", psBr ? 0 : sizeTp, "Ptr", psBr ? &PreviousState : 0, "UInt*", ReturnLength)
			if (!ret && psBr && ReturnLength && A_LastError == 122) { ; ERROR_INSUFFICIENT_BUFFER
				VarSetCapacity(PreviousState, ReturnLength)
				ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &TOKEN_PRIVILEGES, "UInt", ReturnLength, "Ptr", &PreviousState, "UInt*", ReturnLength)
			}
		} else {
			if (psBr && PreviousState)
				ret := DllCall(AdjustTokenPrivileges, "Ptr", hToken, "Int", False, "Ptr", &PreviousState, "UInt", 0, "Ptr", 0, "Ptr", 0)
		}
	}

	if (ret)
		notAllAssigned := A_LastError == 1300 ; ERROR_NOT_ALL_ASSIGNED

	return ret
}

LogonDesktop_AdjustThisProcessPrivileges(privNames, ByRef PreviousState := 0, ByRef notAllAssigned := 0) {
	ret := False

	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0028, hToken)) { ; TOKEN_ADJUST_PRIVILEGES := 0x0020 | TOKEN_QUERY := 0x0008
		ret := LogonDesktop_AdjustTokenPrivileges(hToken, privNames, PreviousState, notAllAssigned)
		LogonDesktop_CloseHandle(hToken)
	}

	return ret
}

LogonDesktop_EasyCreateProcessUsingToken(hToken, cmdLine, desktop, useTokenEnvBlock, InheritHandles := False, ShowWindow := -1) {
	ret := envModule := pEnv := 0

	if (!cmdLine)
		return ret

	if (useTokenEnvBlock) {
		if (!(envModule := _PrepareEnvironmentBlockCall()))
			return ret

		; http://stackoverflow.com/a/13733317
		if (!_CreateEnvironmentBlock(pEnv, hToken, False)) {
			_EndEnvironmentBlockCall(envModule)
			return ret
		}
	}

	_PROCESS_INFORMATION(pi)
	_STARTUPINFO(si, desktop ? &desktop : 0, ShowWindow)
	dwCreationFlags := 0x01000000 | (pEnv ? 0x00000400 : 0) ; CREATE_BREAKAWAY_FROM_JOB | CREATE_UNICODE_ENVIRONMENT

	if (!(ret := _CreateProcessAsUserW(hToken, 0, &cmdLine, 0, 0, InheritHandles, dwCreationFlags, pEnv, 0, &si, &pi)))
		ret := _CreateProcessWithTokenW(hToken, 0x00000001, 0, &cmdLine, dwCreationFlags, pEnv, 0, &si, &pi) ; LOGON_WITH_PROFILE

	if (ret) {
		LogonDesktop_CloseHandle(_PROCESS_INFORMATION_hProcess(pi))
		LogonDesktop_CloseHandle(_PROCESS_INFORMATION_hThread(pi))
	}

	if (useTokenEnvBlock) {
		if (pEnv)
			_DestroyEnvironmentBlock(pEnv)

		if (envModule)
			_EndEnvironmentBlockCall(envModule)
	}

	return ret
}

LogonDesktop_WaitForTermSrvInit()
{
	ret := False
	if ((TermSrvReadyEvent := DllCall("OpenEventW", "UInt", 0x00100000, "Int", False, "WStr", "Global\TermSrvReadyEvent", "Ptr"))) { ; SYNCHRONIZE
		ret := DllCall("WaitForSingleObject", "Ptr", TermSrvReadyEvent, "UInt", -1) == 0
		LogonDesktop_CloseHandle(TermSrvReadyEvent)
	}
	return ret
}

/*
; NOTE: I don't recommend using LogonDesktop_WaitForDesktopSwitchSync(). With AutoHotkey, it's nicer to use the accessibility framework to be be notified asynchronously:
OnDesktopSwitch(hWinEventHook, event, hWnd, idObject, idChild, dwEventThread, dwmsEventTime)
{
	MsgBox Desktop switched
}
DllCall("SetWinEventHook", "UInt", (EVENT_SYSTEM_DESKTOPSWITCH := 0x0020), "UInt", EVENT_SYSTEM_DESKTOPSWITCH, "Ptr", 0, "Ptr", (lpfnWinEventProc := RegisterCallback("OnDesktopSwitch", "")), "UInt", 0, "UInt", 0, "UInt", WINEVENT_OUTOFCONTEXT := 0x0000 | WINEVENT_SKIPOWNPROCESS := 0x0002)
(You should include a corresponding call to UnhookWinEvent, and GlobalFree for the callback function pointer at exit.)
; If you really don't want to use the accessibility framework, you might be able to use RegisterWaitForSingleObject in lieu of MsgWaitForMultipleObjectsEx,
; in combination with Lexikos' RegisterSyncCallback library to be notified asynchronously, in the style of SetWinEventHook.
*/
; The following blocks the current thread unless a message is recieved, waiting fails or WinSta0_DesktopSwitch is signalled
LogonDesktop_WaitForDesktopSwitchSync()
{
	static SYNCHRONIZE := 0x00100000, evt := DllCall("OpenEventW", "UInt", SYNCHRONIZE, "Int", False, "WStr", "WinSta0_DesktopSwitch", "Ptr"), MsgWaitForMultipleObjectsEx := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "MsgWaitForMultipleObjectsEx", "Ptr")

	desktopSwitched := False
	Loop {
		r := DllCall(MsgWaitForMultipleObjectsEx, "UInt", 1, "Ptr*", evt, "UInt", -1, "UInt", 0x4FF, "UInt", 0x0002) ; INFINITE, QS_ALLINPUT, MWMO_ALERTABLE - stolen from Lexikos
		Sleep -1 ; let AutoHotkey process messages
		if (r == 0) { ; WAIT_OBJECT_0
			desktopSwitched := True
			break
		} else if (r == -1) { ; WAIT_FAILED
			break
		}
	}

	;LogonDesktop_CloseHandle(evt)
	return desktopSwitched
}

LogonDesktop_GetTokenUser(hToken, ByRef TOKEN_USER)
{
	ret := dwLengthNeeded := 0

	if (!_GetTokenInformation(hToken, TokenUser := 1, 0, 0, dwLengthNeeded))
		if (A_LastError == 122 && VarSetCapacity(TOKEN_USER, dwLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER
			ret := _GetTokenInformation(hToken, TokenUser, &TOKEN_USER, dwLengthNeeded, dwLengthNeeded)

	return ret
}

_LookupAccountSidW(lpSid, ByRef username, ByRef domain := 0, ByRef use := 0) ; thanks to jNizM: https://autohotkey.com/boards/viewtopic.php?t=4365
{
	cchName := cchReferencedDomainName := 0
	if (!DllCall("advapi32.dll\LookupAccountSidW", "Ptr", 0, "Ptr", lpSid, "Ptr", 0, "UInt*", cchName, "Ptr", 0, "UInt*", cchReferencedDomainName, "UInt*", peUse) && A_LastError == 122) {
		VarSetCapacity(n, cchName * 2), VarSetCapacity(d, cchReferencedDomainName * 2)
		ret := DllCall("advapi32.dll\LookupAccountSidW", "Ptr", 0, "Ptr", lpSid, "Ptr", &n, "UInt*", cchName, "Ptr", &d, "UInt*", cchReferencedDomainName, "UInt*", peUse)
		if (ret) {
			if (IsByRef(username))
				username := StrGet(&n,, "UTF-16")
			if (IsByRef(domain))
				domain := StrGet(&d,, "UTF-16")
			if (IsByRef(use))
				use := _use
		}
		return ret
	}
	return False
}

LogonDesktop_GetTokenUsername(hToken, ByRef username, ByRef domain := 0, ByRef use := 0)
{
	if (LogonDesktop_GetTokenUser(hToken, TOKEN_USER))
		return _LookupAccountSidW(NumGet(TOKEN_USER,, "Ptr"), username, domain, use)

	return False
}

LogonDesktop_GetProcessWindowStationName(ByRef out)
{
	ret := False

	if ((hWinSta := DllCall("GetProcessWindowStation", "Ptr"))) 
		ret := LogonDesktop_GetUserObjectName(hWinSta, out)
	
	return ret
}

LogonDesktop_GetThreadDesktopName(ByRef out, tId := -1)
{
	ret := False
	
	if ((hDesk := DllCall("GetThreadDesktop", "UInt", tId == -1 ? DllCall("GetCurrentThreadId", "UInt") : tId, "Ptr"))) 
		ret := LogonDesktop_GetUserObjectName(hDesk, out)
	
	return ret
}

LogonDesktop_ProcessIdToSessionId(dwProcessId, ByRef dwSessionId)
{
	static ProcessIdToSessionId := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "ProcessIdToSessionId", "Ptr")
	return DllCall(ProcessIdToSessionId, "UInt", dwProcessId, "UInt*", dwSessionId)
}

/*
	LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), 0x0008, hToken) ; TOKEN_QUERY
	if (!LogonDesktop_GetTokenSessionId(hToken, scriptSessionId))
		return
	LogonDesktop_CloseHandle(hToken)
*/
LogonDesktop_GetTokenSessionId(hToken, ByRef out)
{
	ret := dwLengthNeeded := 0
		
	if (hToken)
		ret := _GetTokenInformation(hToken, 12, out, 4, dwLengthNeeded, "UInt*") ; TokenSessionId

	return ret
}

LogonDesktop_PossiblyDetermineIfUnelevatedUserCanWriteToScript()
{
	AccessStatus := grantedAccess := hPrimaryToken := TokenIsElevated := hToken := dwLengthNeeded := ret := 0
	
	if ((desktopHwnd := DllCall("GetShellWindow", "Ptr"))) {
		WinGet, explorerPid, PID, ahk_id %desktopHwnd%
		if (explorerPid) {
			if ((hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_LIMITED_INFORMATION := 0x1000, "Int", False, "UInt", explorerPid, "Ptr"))) {
				if (LogonDesktop_OpenProcessToken(hProc, TOKEN_QUERY := 0x0008 | TOKEN_DUPLICATE := 0x0002, hToken)) {
					if (_GetTokenInformation(hToken, TokenElevation := 20, TokenIsElevated, 4, dwLengthNeeded, "UInt*")) {
						if (!TokenIsElevated) {
							; From Aaron Ballman @ http://blog.aaronballman.com/2011/08/how-to-check-access-rights/
							dwLengthNeeded := 0
							if (!DllCall("advapi32.dll\GetFileSecurity", "WStr", A_ScriptFullPath, "UInt", DACL_SECURITY_INFORMATION := 0x00000004 | OWNER_SECURITY_INFORMATION := 0x00000001 | GROUP_SECURITY_INFORMATION := 0x00000002, "Ptr", 0, "Ptr", 0, "UInt*", dwLengthNeeded)) {
								if (A_LastError == (ERROR_INSUFFICIENT_BUFFER := 122) && VarSetCapacity(sd, dwLengthNeeded) && DllCall("advapi32.dll\GetFileSecurity", "WStr", A_ScriptFullPath, "UInt", DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, "Ptr", &sd, "Ptr", dwLengthNeeded, "UInt*", dwLengthNeeded)) {
									VarSetCapacity(GENERIC_MAPPING, 16)
									NumPut(0x00020000 | 0x0001 | 0x0080 | 0x0008 | 0x00100000, GENERIC_MAPPING, 0, "UInt")	
									NumPut(0x00020000 | 0x0002 | 0x0100 | 0x0010 | 0x0004 | 0x00100000, GENERIC_MAPPING, 4, "UInt")
									NumPut(0x00020000 | 0x0080 | 0x0020 | 0x00100000, GENERIC_MAPPING, 8, "UInt")
									NumPut(0x000F0000 | 0x00100000 | 0x1FF, GENERIC_MAPPING, 12, "UInt")
									GENERIC_WRITE := 0x40000000

									VarSetCapacity(PRIVILEGE_SET, cbPS := 20, 0)
									DllCall("advapi32.dll\MapGenericMask", "UInt*", GENERIC_WRITE, "Ptr", &GENERIC_MAPPING)
									if (DllCall("advapi32.dll\DuplicateToken", "Ptr", hToken, "UInt", SecurityIdentification := 1, "Ptr*", hPrimaryToken)) {
										if (DllCall("advapi32.dll\AccessCheck", "Ptr", &sd, "Ptr", hPrimaryToken, "UInt", GENERIC_WRITE, "Ptr", &GENERIC_MAPPING, "Ptr", &PRIVILEGE_SET, "UInt*", cbPS, "UInt*", grantedAccess, "Int*", AccessStatus))
											ret := AccessStatus
										LogonDesktop_CloseHandle(hPrimaryToken)
									}
								}
							}
						}
					}
					LogonDesktop_CloseHandle(hToken)
				}
				LogonDesktop_CloseHandle(hProc)
			}
		}
	}
	
	return ret
}

; Pretty much from the GetEffectiveRightsFromAcl MSDN sample
LogonDesktop_AllUsersCanWriteToThisScript()
{
	; This doesn't check the allowed ACEs for users that are only part of the Users group. Bear that in mind...
	hAuthzResourceManager := hAuthzClientContext := psd := pacl := ret := 0

	SECURITY_MAX_SID_SIZE := 68
	SIDs := {"WinBuiltinUsersSid": "27", "WinWorldSid": "1"}
	for k, v in SIDs {
		cbSize := SECURITY_MAX_SID_SIZE
		SIDs.SetCapacity(k, cbSize)
		if (!_CreateWellKnownSid(v+0, 0, SIDs.GetAddress(k), cbSize))
			return ret
	}

	if (!authzMod := _LoadLibrary("Authz.dll"))
		return ret

	if (!DllCall("advapi32.dll\GetNamedSecurityInfoW", "WStr", A_ScriptFullPath, "UInt", SE_FILE_OBJECT := 1, "UInt", DACL_SECURITY_INFORMATION := 0x00000004 | OWNER_SECURITY_INFORMATION := 0x00000001 | GROUP_SECURITY_INFORMATION := 0x00000002, "Ptr", 0, "Ptr", 0, "Ptr*", pacl, "Ptr", 0, "Ptr*", psd, "UInt")) {
		if (DllCall("Authz\AuthzInitializeResourceManager", "UInt", AUTHZ_RM_FLAG_NO_AUDIT := 0x1, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr*", hAuthzResourceManager)) {
			for k, v in SIDs {
				if (DllCall("Authz\AuthzInitializeContextFromSid", "UInt", 0, "Ptr", SIDs.GetAddress(k), "Ptr", hAuthzResourceManager, "Ptr", 0, "Int64", 0, "Ptr", 0, "Ptr*", hAuthzClientContext)) {				
					VarSetCapacity(AUTHZ_ACCESS_REQUEST, 20 * (A_PtrSize == 8 ? 2 : 1), 0)
					VarSetCapacity(AUTHZ_ACCESS_REPLY, 16 * (A_PtrSize == 8 ? 2 : 1), 0)
					VarSetCapacity(buf, 1024, 0)
					
					NumPut(MAXIMUM_ALLOWED := 0x02000000, AUTHZ_ACCESS_REQUEST,, "UInt")
					NumPut(1, AUTHZ_ACCESS_REPLY,, "UInt")
					NumPut(&buf, AUTHZ_ACCESS_REPLY, A_PtrSize, "Ptr")
					NumPut(&buf+4, AUTHZ_ACCESS_REPLY, 12 * (A_PtrSize == 8 ? 2 : 1), "Ptr")

					if (DllCall("Authz\AuthzAccessCheck", "UInt", 0, "Ptr", hAuthzClientContext, "Ptr", &AUTHZ_ACCESS_REQUEST, "Ptr", 0, "Ptr", psd, "Ptr", 0, "UInt", 0, "Ptr", &AUTHZ_ACCESS_REPLY, "Ptr", 0)) {
						GrantedAccessMask := NumGet(buf,, "UInt")
						GENERIC_WRITE := 0x40000000
						FILE_GENERIC_WRITE := 0x00020000 | 0x0002 | 0x0100 | 0x0010 | 0x0004 | 0x00100000
						if (((GrantedAccessMask & GENERIC_WRITE) == GENERIC_WRITE) || ((GrantedAccessMask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
							ret := True
					}
					DllCall("Authz\AuthzFreeContext", "Ptr", hAuthzClientContext)
					VarSetCapacity(buf, 0)

					if (ret)
						break
				}
			}
			DllCall("Authz\AuthzFreeResourceManager", "Ptr", hAuthzResourceManager)
		}
	}
	
	_FreeLibrary(authzMod)
	return ret
}

LogonDesktop_SetUiAccessToken(hToken, reallyHigh) {
	; Unsure if there is more to it
	static tilSize := 8 * (A_PtrSize == 8 ? 2 : 1), SECURITY_LABEL_MEDIUM_MORE_SID := 0, SECURITY_LABEL_HIGH_SID

	if (hToken) {
		if (reallyHigh) {
			; 0x3000
			if (!VarSetCapacity(SECURITY_LABEL_HIGH_SID)) {
				VarSetCapacity(SECURITY_LABEL_HIGH_SID, cbSize := 256) ; MAX_SID_SIZE
				if (!_CreateWellKnownSid(68, 0, &SECURITY_LABEL_HIGH_SID, cbSize)) ; WinHighLabelSid
					return
			}
		} else {
			; SECURITY_MANDATORY_MEDIUM_RID (0x2000) + 0x10 - not the same thing as SECURITY_MANDATORY_MEDIUM_PLUS_RID (0x100)!
			if (!SECURITY_LABEL_MEDIUM_MORE_SID) {
				if (!DllCall("advapi32.dll\ConvertStringSidToSidW", "WStr", "S-1-16-8208", "Ptr*", SECURITY_LABEL_MEDIUM_MORE_SID)) ; "higherIntegrityLevelSidForLimitedAccounts"
					return
			}
		}

		lpSecLabel := reallyHigh ? &SECURITY_LABEL_HIGH_SID : SECURITY_LABEL_MEDIUM_MORE_SID
		if (_SetTokenInformation(hToken, 26, True, 4, "UInt*")) { ; TokenUIAccess
			; https://msdn.microsoft.com/en-us/library/bb625960.aspx
			VarSetCapacity(TOKEN_MANDATORY_LABEL, tilSize, 0), NumPut(lpSecLabel, TOKEN_MANDATORY_LABEL,, "Ptr"), NumPut(0x00000020, TOKEN_MANDATORY_LABEL, A_PtrSize, "UInt") ; SE_GROUP_INTEGRITY
			_SetTokenInformation(hToken, 25, &TOKEN_MANDATORY_LABEL, tilSize + _GetLengthSid(lpSecLabel)) ; TokenIntegrityLevel
		}
		
;		if (SECURITY_LABEL_MEDIUM_MORE_SID)
;			DllCall("LocalFree", "Ptr", SECURITY_LABEL_MEDIUM_MORE_SID, "Ptr")
	}
}

; https://code.msdn.microsoft.com/windowsapps/CppUACSelfElevation-5bfc52dd
LogonDesktop_DoesTokenContainAdminGroupDirectlyOrNot(hToken, fallBackToLegacyMethod := False)
{
	static adminSID, CheckTokenMembership := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CheckTokenMembership", "Ptr"), DuplicateToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "DuplicateToken", "Ptr")
	hTokenToCheck := fInAdminGroup := 0

	if (!hToken)
		return fInAdminGroup

	; Create the SID corresponding to the Administrators group.
	if (!VarSetCapacity(adminSID)) {
		VarSetCapacity(adminSID, cbSize := 68) ; SECURITY_MAX_SID_SIZE
		if (!_CreateWellKnownSid(26, 0, &adminSID, cbSize)) { ; WinBuiltinAdministratorsSid 
			VarSetCapacity(adminSID, 0)
			return fInAdminGroup
		}
	}

	; Determine token type: limited, elevated, or default
	if (!_GetTokenInformation(hToken, 18, elevType, 4, cbSize, "UInt*")) ; TokenElevationType
		return fInAdminGroup

	; If limited, get the linked elevated token for further check.
	if (3 == elevType) ; TokenElevationTypeLimited
	{
		if (!_GetTokenInformation(hToken, 19, hTokenToCheck, A_PtrSize, cbSize, "Ptr*")) ; TokenLinkedToken
			return fInAdminGroup
	}

	/* CheckTokenMembership requires an impersonation token. If we just got a 
	 linked token, it already is an impersonation token.  If we did not get 
	 a linked token, duplicate the original into an impersonation token for 
	 CheckTokenMembership.
	*/
	if (!hTokenToCheck)
	{
		if (!DllCall(DuplicateToken, "Ptr", hToken, "UInt", 1, "Ptr*", hTokenToCheck)) ; SecurityIdentification
			return fInAdminGroup
	}

	/* Check if the token to be checked contains admin SID.
	 http://msdn.microsoft.com/en-us/library/aa379596(VS.85).aspx:
	 To determine whether a SID is enabled in a token, that is, whether it 
	 has the SE_GROUP_ENABLED attribute, call CheckTokenMembership.
	*/
	if (!DllCall(CheckTokenMembership, "Ptr", hTokenToCheck, "Ptr", &adminSID, "Int*", fInAdminGroup) && fallBackToLegacyMethod && A_LastError == 1309) ; ERROR_NO_IMPERSONATION_TOKEN
		fInAdminGroup := _DetermineIfTheTokenHasAGroupTheNT4Way(hTokenToCheck, &adminSID)

	if (hTokenToCheck)
		LogonDesktop_CloseHandle(hTokenToCheck)

	return fInAdminGroup
}

_isTokenUiAccess(hToken)
{
	ret := False
	if (hToken)
		_GetTokenInformation(hToken, TokenUIAccess := 26, ret, 4, dwLengthNeeded, "UInt*")
	return ret
}

LogonDesktop_isThisProcessUiAccess()
{
	ret := False
	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) {
		ret := _isTokenUiAccess(hToken)
		LogonDesktop_CloseHandle(hToken)
	}
	return ret
}

LogonDesktop_isThisProcessHighIntegrity()
{
	ret := false
	if (LogonDesktop_OpenProcessToken(LogonDesktop_GetCurrentProcess(), TOKEN_QUERY := 0x0008, hToken)) {
		if (!_GetTokenInformation(hToken, TokenIntegrityLevel := 25, 0, 0, dwLengthNeeded))
			if (A_LastError == (ERROR_INSUFFICIENT_BUFFER := 122))
				if (VarSetCapacity(pTIL, dwLengthNeeded) && _GetTokenInformation(hToken, TokenIntegrityLevel, &pTIL, dwLengthNeeded, dwLengthNeeded))
					ret := (DllCall("advapi32.dll\GetSidSubAuthority", "Ptr", (pSid := NumGet(pTil,, "Ptr")), "UInt", DllCall("advapi32.dll\GetSidSubAuthorityCount", "Ptr", pSid, "UChar*")-1, "UInt*")) >= 0x00002010
		LogonDesktop_CloseHandle(hToken)
	}

	return ret
}

LogonDesktop_SessionIsLocked(sessionId)
{
	static WTS_CURRENT_SERVER_HANDLE := 0, WTSSessionInfoEx := 25, WTS_SESSIONSTATE_LOCK := 0x00000000, WTS_SESSIONSTATE_UNLOCK := 0x00000001 ;, WTS_SESSIONSTATE_UNKNOWN := 0xFFFFFFFF
	ret := False
	
	if (DllCall("wtsapi32\WTSQuerySessionInformation", "Ptr", WTS_CURRENT_SERVER_HANDLE, "UInt", sessionId, "UInt", WTSSessionInfoEx, "Ptr*", sesInfo, "Ptr*", BytesReturned)) {
		SessionFlags := NumGet(sesInfo+0, 16, "Int")
		; "Windows Server 2008 R2 and Windows 7: Due to a code defect, the usage of the WTS_SESSIONSTATE_LOCK and WTS_SESSIONSTATE_UNLOCK flags is reversed."
		ret := A_OSVersion != "WIN_7" ? SessionFlags == WTS_SESSIONSTATE_LOCK : SessionFlags == WTS_SESSIONSTATE_UNLOCK
		DllCall("wtsapi32\WTSFreeMemory", "Ptr", sesInfo)
	}

	return ret
}

LogonDesktop_WTSEnumerateProcessesEx(ByRef WTS, hServer := 0, SessionID := 0xFFFFFFFE) ; WTS_CURRENT_SERVER_HANDLE, WTS_ANY_SESSION
{ ; Todo: 32-Bit support. https://msdn.microsoft.com/en-us/library/ee621013(v=vs.85).aspx. Based on jNizM's code: https://github.com/jNizM/AHK_ProcessExplorer/blob/HEAD/src/ProcessExplorer.ahk#L112
	local PI := PI_EX := TTL := 0
	if (!DllCall("wtsapi32\WTSEnumerateProcessesEx", "ptr", hServer, "UInt*", 1, "UInt", SessionID, "Ptr*", PI_EX, "UInt*", TTL))
		return False
	PI := PI_EX, WTS := []
	loop % TTL
	{
		entry := {"SessionID": NumGet(PI+0, "UInt")
				 ,"ProcessID": NumGet(PI+4, "UInt")
				 ,"ProcessName": StrGet(NumGet(PI+8, "ptr"))
				 ,"NumberOfThreads": NumGet(PI+24, "UInt")
				 ,"HandleCount": NumGet(PI+28, "UInt")
				 ,"PagefileUsage": NumGet(PI+32, "UInt")
				 ,"PeakPagefileUsage": NumGet(PI+36, "UInt")
				 ,"WorkingSetSize": NumGet(PI+40, "UInt")
				 ,"PeakWorkingSetSize": NumGet(PI+44, "UInt")
				 ,"UserTime": NumGet(PI+48, "Int64")
				 ,"KernelTime": NumGet(PI+56, "Int64")}

		SID := NumGet(PI+16, "ptr")
		if (_IsValidSid(SID)) {
			if (_LookupAccountSidW(SID, Name, Domain)) {
				entry["UserName"] := Name
				entry["UserDomain"] := Domain
			}

			SIDLength := _GetLengthSid(SID)
			if (entry.SetCapacity("UserSID", SIDLength) >= SIDLength)
				DllCall("ntdll\RtlMoveMemory", "Ptr", entry.GetAddress("UserSID"), "Ptr", SID, "Ptr", SIDLength)
		}
		WTS.Push(entry)

		PI += 64
	}
	DllCall("wtsapi32\WTSFreeMemoryEx", "UInt", 1, "ptr", PI_EX, "UInt", TTL)
	return True
}

_DetermineIfTheTokenHasAGroupTheNT4Way(hToken, pSid) { ; Seriously, don't use this.
	static SE_GROUP_ENABLED := 0x00000004, SE_GROUP_USE_FOR_DENY_ONLY := 0x00000010, cbSID_AND_ATTRIBUTES := 8 * (A_PtrSize == 8 ? 2 : 1)
	retval := False

	if (!hToken || !pSid)
		return retval

	if (!_GetTokenInformation(hToken, TokenGroups := 2, 0, 0, dwSize))
		if (A_LastError != 122) ; ERROR_INSUFFICIENT_BUFFER
			return retval

	VarSetCapacity(groupInfo, dwSize, 0)
	if (!_GetTokenInformation(hToken, TokenGroups, &groupInfo, dwSize, dwSize))
		return retval

	GroupCount := NumGet(groupInfo,, "UInt")
	Loop % GroupCount {
		currGroupOffset := A_PtrSize + (cbSID_AND_ATTRIBUTES * (A_Index - 1)) 
		Attributes := NumGet(groupInfo, currGroupOffset + A_PtrSize, "UInt")
		if (Attributes & SE_GROUP_USE_FOR_DENY_ONLY)
			continue
		if ((Attributes & SE_GROUP_ENABLED) && _EqualSid(pSID, NumGet(groupInfo, currGroupOffset, "Ptr"))) {
			retval := true
			break
		}
	}

	return retval
}

_EqualSid(pSid1, pSid2)
{
	static EqualSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "EqualSid", "Ptr")
	return DllCall(EqualSid, "Ptr", pSid1, "Ptr", pSid2)
}

LogonDesktop_GetUserObjectName(hObj, ByRef out) {
	static GetUserObjectInformationW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "GetUserObjectInformationW", "Ptr")
	nLengthNeeded := VarSetCapacity(out)

	if (!(ret := DllCall(GetUserObjectInformationW, "Ptr", hObj, "Int", 2, "WStr", out, "UInt", nLengthNeeded, "UInt*", nLengthNeeded))) ; UOI_NAME
		if (A_LastError == 122 && VarSetCapacity(out, nLengthNeeded)) ; ERROR_INSUFFICIENT_BUFFER
			ret := DllCall(GetUserObjectInformationW, "Ptr", hObj, "Int", 2, "WStr", out, "UInt", nLengthNeeded, "Ptr", 0)

	return ret
}

_OnWinLogonDesktop()
{
	static OpenInputDesktop := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "OpenInputDesktop", "Ptr"), desktopName

	if !VarSetCapacity(desktopName)
		VarSetCapacity(desktopName, 65534)

	if hDesk := DllCall(OpenInputDesktop, "UInt", 0, "Int", False, "UInt", 0, "Ptr")
		return !LogonDesktop_GetUserObjectName(hDesk, desktopName) || desktopName == "Winlogon", LogonDesktop_CloseDesktop(hDesk)

	return True
}

LogonDesktop_LoadWtsApi() {
	static lib := "wtsapi32.dll"
	return _LoadLibrary(lib)
}

LogonDesktop_UnloadWtsApi(wtsapiModule) {
	return _FreeLibrary(wtsapiModule)
}

LogonDesktop_WTSQueryUserToken(SessionId, ByRef phToken) {
	return DllCall("wtsapi32\WTSQueryUserToken", "UInt", SessionId, "Ptr*", phToken)
}

LogonDesktop_DuplicateTokenEx(hExistingToken, dwDesiredAccess, lpTokenAttributes, ImpersonationLevel, TokenType, ByRef phNewToken) {
	static DuplicateTokenEx := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "DuplicateTokenEx", "Ptr")
	return DllCall(DuplicateTokenEx, "Ptr", hExistingToken, "UInt", dwDesiredAccess, "Ptr", lpTokenAttributes, "UInt", ImpersonationLevel, "UInt", TokenType, "Ptr*", phNewToken)
}

_CreateProcessAsUserW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation) {
	static CreateProcessAsUserW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateProcessAsUserW", "Ptr")
	return DllCall(CreateProcessAsUserW, "Ptr", hToken, "Ptr", lpApplicationName, "Ptr", lpCommandLine, "Ptr", lpProcessAttributes, "Ptr", lpThreadAttributes, "Int", bInheritHandles, "UInt", dwCreationFlags, "Ptr", lpEnvironment, "Ptr", lpCurrentDirectory, "Ptr", lpStartupInfo, "Ptr", lpProcessInformation)
}

_CreateProcessWithTokenW(hToken, dwLogonFlags, lpApplicationName, lpCommandLine, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInfo) {
	static CreateProcessWithTokenW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateProcessWithTokenW", "Ptr")
	return DllCall(CreateProcessWithTokenW, "Ptr", hToken, "UInt", dwLogonFlags, "Ptr", lpApplicationName, "Ptr", lpCommandLine, "UInt", dwCreationFlags, "Ptr", lpEnvironment, "Ptr", lpCurrentDirectory, "Ptr", lpStartupInfo, "Ptr", lpProcessInformation)
}

LogonDesktop_OpenProcessToken(ProcessHandle, DesiredAccess, ByRef TokenHandle) {
	static OpenProcessToken := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "OpenProcessToken", "Ptr")
	return DllCall(OpenProcessToken, "Ptr", ProcessHandle, "UInt", DesiredAccess, "Ptr*", TokenHandle)
}

LogonDesktop_CloseHandle(hObject) {
	static CloseHandle := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "CloseHandle", "Ptr"), INVALID_HANDLE_VALUE := -1
	return (hObject && hObject != INVALID_HANDLE_VALUE) ? DllCall(CloseHandle, "Ptr", hObject) : False
}

LogonDesktop_CloseDesktop(hDesktop) {
	static CloseDesktop := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "user32.dll", "Ptr"), "AStr", "CloseDesktop", "Ptr")
	return DllCall(CloseDesktop, "Ptr", hDesktop)
}

_PROCESS_INFORMATION(ByRef pi) {
	static piCb := A_PtrSize == 8 ? 24 : 16
	if (IsByRef(pi))
		VarSetCapacity(pi, piCb, 0)
}

_PROCESS_INFORMATION_hProcess(ByRef pi) {
	return NumGet(pi,, "Ptr")
}

_PROCESS_INFORMATION_hThread(ByRef pi) {
	return NumGet(pi, A_PtrSize, "Ptr")
}

_STARTUPINFO(ByRef si, lpDesktop := 0, ShowWindow := -1, restOneDay*) {
	static siCb := A_PtrSize == 8 ? 104 : 68
	if (IsByRef(si)) {
		dwFlags := 0
		VarSetCapacity(si, siCb, 0), NumPut(siCb, si,, "UInt")
		if (lpDesktop)
			NumPut(lpDesktop, si, A_PtrSize * 2, "Ptr")
		if (ShowWindow > -1) {
			dwFlags |= 0x00000001 ; STARTF_USESHOWWINDOW
			NumPut(ShowWindow, si, A_PtrSize == 8 ? 64 : 48, "UShort")
		}
		NumPut(dwFlags, si, A_PtrSize == 8 ? 60 : 44, "UInt")
	}
}

_PrepareEnvironmentBlockCall() {
	static lib := "userenv.dll"
	return _LoadLibrary(lib)
}

_CreateEnvironmentBlock(ByRef lpEnvironment, hToken, bInherit) {
	return DllCall("userenv.dll\CreateEnvironmentBlock", "Ptr*", lpEnvironment, "Ptr", hToken, "Int", bInherit)
}

_DestroyEnvironmentBlock(lpEnvironment) {
	return DllCall("userenv.dll\DestroyEnvironmentBlock", "Ptr", lpEnvironment)
}

_EndEnvironmentBlockCall(userenvModule) {
	return _FreeLibrary(userenvModule)
}

_GetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, ByRef ReturnLength := 0, _tokenInfoType := "Ptr") {
	static GetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetTokenInformation", "Ptr")
	return DllCall(GetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength, "UInt*", ReturnLength)
}

_SetTokenInformation(TokenHandle, TokenInformationClass, ByRef TokenInformation, TokenInformationLength, _tokenInfoType := "Ptr") {
	static SetTokenInformation := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "SetTokenInformation", "Ptr")
	return DllCall(SetTokenInformation, "Ptr", TokenHandle, "UInt", TokenInformationClass, _tokenInfoType, TokenInformation, "UInt", TokenInformationLength)
}

_CreateWellKnownSid(WellKnownSidType, DomainSid, pSid, ByRef cbSid) {
	static CreateWellKnownSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "CreateWellKnownSid", "Ptr")
	return DllCall(CreateWellKnownSid, "UInt", WellKnownSidType, "Ptr", DomainSid, "Ptr", pSid, "UInt*", cbSid)
}

_IsValidSid(pSid) {
	static IsValidSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "IsValidSid", "Ptr")
	return DllCall(IsValidSid, "Ptr", pSid)
}

_GetLengthSid(pSid) {
	static GetLengthSid := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "advapi32.dll", "Ptr"), "AStr", "GetLengthSid", "Ptr")
	return DllCall(GetLengthSid, "Ptr", pSid, "UInt")
}

_FindASystemProcessToken(TokenWantedPerms := 0xF, FilterFunc := 0, FilterFuncExtraData := 0, lookInSession := 0) { ; TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY | TOKEN_IMPERSONATE - the token returned isn't a duplicated one
	static PROCESS_QUERY_INFORMATION := 0x0400
	ret := 0

	if (LogonDesktop_AdjustThisProcessPrivileges({"SeDebugPrivilege": True}, PreviousState)) {
		if (LogonDesktop_WTSEnumerateProcessesEx(WTS,, lookInSession)) {
			FilterFuncValid := IsObject(FilterFunc) && IsFunc(FilterFunc)
			for _, proc in WTS {
				if (_IsSystemSid(proc.GetAddress("UserSID"))) {
					if ((hProc := DllCall("OpenProcess", "UInt", PROCESS_QUERY_INFORMATION, "Int", False, "UInt", proc.ProcessID, "Ptr"))) {
						if (LogonDesktop_OpenProcessToken(hProc, TokenWantedPerms, ret), LogonDesktop_CloseHandle(hProc)) {
							if (!FilterFuncValid || FilterFunc.Call(proc, ret, FilterFuncExtraData))
								break
						}
					}
				}
			}
		}
		LogonDesktop_AdjustThisProcessPrivileges(0, PreviousState)
	}
	
	return ret
}

LogonDesktop_GetCurrentProcessId() {
	static dwProcessId := DllCall("GetCurrentProcessId", "UInt") ; well, it's not like this one is going to change each time we call it
	return dwProcessId
}

LogonDesktop_GetCurrentProcess() {
	static hProc := DllCall("GetCurrentProcess", "Ptr") ; always -1
	return hProc
}

_LoadLibrary(lpFileName) {
	static LoadLibraryW := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "LoadLibraryW", "Ptr")
	return DllCall(LoadLibraryW, "WStr", lpFileName, "Ptr")
}

_FreeLibrary(hModule) {
	static FreeLibrary := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandleW", "WStr", "kernel32.dll", "Ptr"), "AStr", "FreeLibrary", "Ptr")
	return DllCall(FreeLibrary, "Ptr", hModule)
}

_TOKEN_ALL_ACCESS()
{
	return (STANDARD_RIGHTS_REQUIRED := 0x000F0000 | TOKEN_ASSIGN_PRIMARY := 0x0001 | TOKEN_DUPLICATE := 0x0002 | TOKEN_IMPERSONATE := 0x0004 | TOKEN_QUERY := 0x0008 | TOKEN_QUERY_SOURCE := 0x0010 | TOKEN_ADJUST_PRIVILEGES := 0x0020 | TOKEN_ADJUST_GROUPS := 0x0040 | TOKEN_ADJUST_DEFAULT := 0x0080 | TOKEN_ADJUST_SESSIONID := 0x0100)
}

GetParentProcessID()
{
	; Undocumented, and could break at any time, but far easier than the CreateToolhelp32Snapshot way...
	VarSetCapacity(PROCESS_BASIC_INFORMATION, pbiSz := A_PtrSize == 8 ? 48 : 24)
	if (DllCall("ntdll\NtQueryInformationProcess", "Ptr", LogonDesktop_GetCurrentProcess(), "UInt", 0, "Ptr", &PROCESS_BASIC_INFORMATION, "UInt", pbiSz, "Ptr", 0) >= 0)
		return NumGet(PROCESS_BASIC_INFORMATION, pbiSz - A_PtrSize, "UInt")
	return 0
}

GetParentProcessName()
{
	if (parentPID := GetParentProcessID()) {
		if (hProc := DllCall("OpenProcess", "UInt", 0x1000 | 0x0010, "Int", False, "UInt", parentPID, "Ptr")) { ; PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ
			VarSetCapacity(procName, (260 + 1) * 2)
			bnOK := !!DllCall("K32GetModuleBaseNameW", "Ptr", hProc, "Ptr", 0, "WStr", procName, "UInt", 260, "UInt")
			LogonDesktop_CloseHandle(hProc)
			if (bnOK)
				return procName
		}
	}
	return ""
}

https://www.autohotkey.com/boards/viewt … p?p=129830
https://www.autohotkey.com/boards/viewt … mp;t=27709

9 (изменено: EV, 2020-05-11 20:50:13)

Re: AHK: Хоткей с экрана блокировки Windows

Run, %comspec% /c psexec -i \\192.168.1.35 -u Home -p foresters cmd /c start "" "C:\Users\Home\Documents\Script\SynchronizesTime.exe",, Hide

Как можно на удаленном запустить .exe?

10

Re: AHK: Хоткей с экрана блокировки Windows

А это уже другой вопрос, к данной теме отношения не имеющий.

11

Re: AHK: Хоткей с экрана блокировки Windows

Malcev
Решения нет. Прекращайте загадочно отвечать

12

Re: AHK: Хоткей с экрана блокировки Windows

EV, прекращайте нарушать правила:

3.11. Руководствуйтесь правилом: один вопрос - одна тема, не загромождайте существующие ветки посторонними вопросами и информацией.

http://forum.script-coding.com/rules.html