w-mousekey 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.js +55 -0
  4. package/.jsdoc +25 -0
  5. package/AutoHotkey_2.0.19/AutoHotkey.chm +0 -0
  6. package/AutoHotkey_2.0.19/AutoHotkey32.exe +0 -0
  7. package/AutoHotkey_2.0.19/AutoHotkey64.exe +0 -0
  8. package/AutoHotkey_2.0.19/Install.cmd +2 -0
  9. package/AutoHotkey_2.0.19/UX/Templates/Minimal for v2.ahk +6 -0
  10. package/AutoHotkey_2.0.19/UX/WindowSpy.ahk +246 -0
  11. package/AutoHotkey_2.0.19/UX/inc/CommandLineToArgs.ahk +12 -0
  12. package/AutoHotkey_2.0.19/UX/inc/CreateAppShortcut.ahk +37 -0
  13. package/AutoHotkey_2.0.19/UX/inc/EnableUIAccess.ahk +246 -0
  14. package/AutoHotkey_2.0.19/UX/inc/GetGitHubReleaseAssetURL.ahk +26 -0
  15. package/AutoHotkey_2.0.19/UX/inc/HashFile.ahk +96 -0
  16. package/AutoHotkey_2.0.19/UX/inc/README.txt +3 -0
  17. package/AutoHotkey_2.0.19/UX/inc/ShellRun.ahk +7 -0
  18. package/AutoHotkey_2.0.19/UX/inc/bounce-v1.ahk +3 -0
  19. package/AutoHotkey_2.0.19/UX/inc/common.ahk +21 -0
  20. package/AutoHotkey_2.0.19/UX/inc/config.ahk +13 -0
  21. package/AutoHotkey_2.0.19/UX/inc/identify.ahk +29 -0
  22. package/AutoHotkey_2.0.19/UX/inc/identify_regex.ahk +4 -0
  23. package/AutoHotkey_2.0.19/UX/inc/launcher-common.ahk +78 -0
  24. package/AutoHotkey_2.0.19/UX/inc/spy.ico +0 -0
  25. package/AutoHotkey_2.0.19/UX/inc/ui-base.ahk +129 -0
  26. package/AutoHotkey_2.0.19/UX/install-ahk2exe.ahk +53 -0
  27. package/AutoHotkey_2.0.19/UX/install-version.ahk +109 -0
  28. package/AutoHotkey_2.0.19/UX/install.ahk +1056 -0
  29. package/AutoHotkey_2.0.19/UX/launcher.ahk +430 -0
  30. package/AutoHotkey_2.0.19/UX/reload-v1.ahk +22 -0
  31. package/AutoHotkey_2.0.19/UX/reset-assoc.ahk +38 -0
  32. package/AutoHotkey_2.0.19/UX/ui-dash.ahk +200 -0
  33. package/AutoHotkey_2.0.19/UX/ui-editor.ahk +238 -0
  34. package/AutoHotkey_2.0.19/UX/ui-launcherconfig.ahk +195 -0
  35. package/AutoHotkey_2.0.19/UX/ui-newscript.ahk +296 -0
  36. package/AutoHotkey_2.0.19/UX/ui-setup.ahk +175 -0
  37. package/AutoHotkey_2.0.19/UX/ui-uninstall.ahk +68 -0
  38. package/AutoHotkey_2.0.19/WindowSpy.ahk +2 -0
  39. package/AutoHotkey_2.0.19/license.txt +351 -0
  40. package/AutoHotkey_2.0.19/zclick.ahk +5 -0
  41. package/AutoHotkey_2.0.19/zrun_click.bat +2 -0
  42. package/AutoHotkey_2.0.19/zrun_send.bat +2 -0
  43. package/AutoHotkey_2.0.19/zsend.ahk +4 -0
  44. package/LICENSE +21 -0
  45. package/README.md +23 -0
  46. package/SECURITY.md +5 -0
  47. package/_tmp/view.all.png +0 -0
  48. package/_tmp/view.det.png +0 -0
  49. package/babel.config.js +16 -0
  50. package/dist/action.umd.js +32 -0
  51. package/dist/action.umd.js.map +1 -0
  52. package/dist/ck-pic.umd.js +7 -0
  53. package/dist/ck-pic.umd.js.map +1 -0
  54. package/dist/compare.umd.js +7 -0
  55. package/dist/compare.umd.js.map +1 -0
  56. package/dist/get-settings.umd.js +7 -0
  57. package/dist/get-settings.umd.js.map +1 -0
  58. package/dist/mousekey.umd.js +7 -0
  59. package/dist/mousekey.umd.js.map +1 -0
  60. package/dist/screen.umd.js +7 -0
  61. package/dist/screen.umd.js.map +1 -0
  62. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  63. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  64. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  65. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  66. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  67. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  68. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  69. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  70. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  71. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  72. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  73. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  74. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  75. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  76. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  77. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  78. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  79. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  80. package/docs/index.html +84 -0
  81. package/docs/scripts/collapse.js +39 -0
  82. package/docs/scripts/commonNav.js +28 -0
  83. package/docs/scripts/linenumber.js +25 -0
  84. package/docs/scripts/nav.js +12 -0
  85. package/docs/scripts/polyfill.js +4 -0
  86. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  87. package/docs/scripts/prettify/lang-css.js +2 -0
  88. package/docs/scripts/prettify/prettify.js +28 -0
  89. package/docs/scripts/search.js +99 -0
  90. package/docs/styles/jsdoc.css +776 -0
  91. package/docs/styles/prettify.css +80 -0
  92. package/g.mjs +46 -0
  93. package/g.test_opencv.mjs +36 -0
  94. package/package.json +41 -0
  95. package/pic/view.png +0 -0
  96. package/script.txt +17 -0
  97. package/src/action.mjs +132 -0
  98. package/src/ckPic.mjs +95 -0
  99. package/src/compare.mjs +201 -0
  100. package/src/getSettings.mjs +17 -0
  101. package/src/mousekey.mjs +95 -0
  102. package/src/screen.mjs +62 -0
  103. package/test/WMousekey.test.mjs +11 -0
  104. package/toolg/addVersion.mjs +4 -0
  105. package/toolg/cleanFolder.mjs +4 -0
  106. package/toolg/gDistRollup.mjs +33 -0
  107. package/toolg/modifyReadme.mjs +4 -0
package/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*]
4
+ charset = utf-8
5
+ indent_style = space
6
+ indent_size = 4
7
+ end_of_line = lf
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
package/.eslintignore ADDED
@@ -0,0 +1,3 @@
1
+ /build/
2
+ /config/
3
+ /dist/
package/.eslintrc.js ADDED
@@ -0,0 +1,55 @@
1
+ module.exports = {
2
+ 'env': {
3
+ 'browser': true,
4
+ 'es6': true,
5
+ 'mocha': true
6
+ },
7
+ 'extends': ['plugin:vue/base', 'plugin:vue/essential', 'standard'],
8
+ 'plugins': [
9
+ 'vue'
10
+ ],
11
+ 'globals': {
12
+ 'Atomics': 'readonly',
13
+ 'SharedArrayBuffer': 'readonly'
14
+ },
15
+ 'parser': 'vue-eslint-parser',
16
+ 'parserOptions': {
17
+ 'parser': '@babel/eslint-parser',
18
+ 'ecmaVersion': 2019,
19
+ 'sourceType': 'module',
20
+ },
21
+ 'rules': {
22
+ 'generator-star-spacing': 'off',
23
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
24
+ 'indent': ['error', 4],
25
+ 'no-console': 'off',
26
+ 'comma-dangle': ['error', {
27
+ 'arrays': 'ignore',
28
+ 'objects': 'ignore',
29
+ 'imports': 'never',
30
+ 'exports': 'never',
31
+ 'functions': 'ignore'
32
+ }],
33
+ 'no-multiple-empty-lines': ['error', { 'max': 2, 'maxEOF': 2 }],
34
+ //'space-before-function-paren': ['error', { 'anonymous': 'always', 'named': 'never' }],
35
+ 'space-before-function-paren': 'off',
36
+ 'spaced-comment': 'off',
37
+ 'brace-style': ['error', 'stroustrup'],
38
+ 'padded-blocks': 'off',
39
+ 'no-constant-condition': 'off',
40
+ 'camelcase': 'off',
41
+ 'no-new': 'off',
42
+ 'prefer-const': 'off',
43
+ 'quote-props': ['error', 'consistent'],
44
+ 'dot-notation': 'off',
45
+ 'standard/no-callback-literal': 'off',
46
+ 'quotes': ['error', 'single', { 'allowTemplateLiterals': true }],
47
+ 'prefer-promise-reject-errors': 'off',
48
+ 'no-unused-vars': ['error', { 'args': 'none', 'ignoreRestSiblings': true, 'argsIgnorePattern': '^_' }],
49
+ 'node/no-callback-literal': 'off',
50
+ 'prefer-regex-literals': 'off',
51
+ 'array-callback-return': 'off',
52
+ 'no-unreachable-loop': 'off',
53
+ 'vue/multi-word-component-names': 'off',
54
+ }
55
+ }
package/.jsdoc ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "tags": {
3
+ "allowUnknownTags": false
4
+ },
5
+ "source": {
6
+ "include": ["src/", "server/"],
7
+ "includePattern": ".+\\.(js(doc|x)?|mjs|vue)$",
8
+ "excludePattern": "(node_modules/|docs)"
9
+ },
10
+ "plugins": [
11
+ "plugins/markdown",
12
+ "node_modules/jsdoc-vuejs"
13
+ ],
14
+ "opts": {
15
+ "template": "node_modules/docdash",
16
+ "encoding": "utf8",
17
+ "destination": "docs/",
18
+ "recurse": true,
19
+ "verbose": true
20
+ },
21
+ "templates": {
22
+ "cleverLinks": false,
23
+ "monospaceLinks": false
24
+ }
25
+ }
Binary file
@@ -0,0 +1,2 @@
1
+ @echo off
2
+ start "" "%~dp0AutoHotkey32.exe" "%~dp0UX\ui-setup.ahk"
@@ -0,0 +1,6 @@
1
+ /*
2
+ [NewScriptTemplate]
3
+ Description = Just #Requires v2.0
4
+ */
5
+ #Requires AutoHotkey v2.0
6
+
@@ -0,0 +1,246 @@
1
+ ;
2
+ ; Window Spy for AHKv2
3
+ ;
4
+
5
+ #Requires AutoHotkey v2.0
6
+
7
+ #NoTrayIcon
8
+ #SingleInstance Ignore
9
+ SetWorkingDir A_ScriptDir
10
+ CoordMode "Pixel", "Screen"
11
+
12
+ Global oGui
13
+
14
+ WinSpyGui()
15
+
16
+ WinSpyGui() {
17
+ Global oGui
18
+
19
+ try TraySetIcon "inc\spy.ico"
20
+ DllCall("shell32\SetCurrentProcessExplicitAppUserModelID", "wstr", "AutoHotkey.WindowSpy")
21
+
22
+ oGui := Gui("AlwaysOnTop Resize MinSize +DPIScale","Window Spy for AHKv2")
23
+ oGui.OnEvent("Close",WinSpyClose)
24
+ oGui.OnEvent("Size",WinSpySize)
25
+
26
+ oGui.SetFont('s9', "Segoe UI")
27
+
28
+ oGui.Add("Text",,"Window Title, Class and Process:")
29
+ oGui.Add("Checkbox","yp xp+200 w120 Right vCtrl_FollowMouse","Follow Mouse").Value := 1
30
+ oGui.Add("Edit","xm w320 r5 ReadOnly -Wrap vCtrl_Title")
31
+ oGui.Add("Text",,"Mouse Position:")
32
+ oGui.Add("Edit","w320 r4 ReadOnly vCtrl_MousePos")
33
+ oGui.Add("Text","w320 vCtrl_CtrlLabel",(txtFocusCtrl := "Focused Control") ":")
34
+ oGui.Add("Edit","w320 r4 ReadOnly vCtrl_Ctrl")
35
+ oGui.Add("Text",,"Active Window Position:")
36
+ oGui.Add("Edit","w320 r2 ReadOnly vCtrl_Pos")
37
+ oGui.Add("Text",,"Status Bar Text:")
38
+ oGui.Add("Edit","w320 r2 ReadOnly vCtrl_SBText")
39
+ oGui.Add("Checkbox","vCtrl_IsSlow","Slow TitleMatchMode")
40
+ oGui.Add("Text",,"Visible Text:")
41
+ oGui.Add("Edit","w320 r2 ReadOnly vCtrl_VisText")
42
+ oGui.Add("Text",,"All Text:")
43
+ oGui.Add("Edit","w320 r2 ReadOnly vCtrl_AllText")
44
+ oGui.Add("Text","w320 r1 vCtrl_Freeze",(txtNotFrozen := "(Hold Ctrl or Shift to suspend updates)"))
45
+
46
+ oGui.Show("NoActivate")
47
+ WinGetClientPos(&x_temp, &y_temp2,,,"ahk_id " oGui.hwnd)
48
+
49
+ ; oGui.horzMargin := x_temp*96//A_ScreenDPI - 320 ; now using oGui.MarginX
50
+
51
+ oGui.txtNotFrozen := txtNotFrozen ; create properties for futur use
52
+ oGui.txtFrozen := "(Updates suspended)"
53
+ oGui.txtMouseCtrl := "Control Under Mouse Position"
54
+ oGui.txtFocusCtrl := txtFocusCtrl
55
+
56
+ SetTimer Update, 250
57
+ }
58
+
59
+ WinSpySize(GuiObj, MinMax, Width, Height) {
60
+ Global oGui
61
+
62
+ If !oGui.HasProp("txtNotFrozen") ; WinSpyGui() not done yet, return until it is
63
+ return
64
+
65
+ SetTimer Update, (MinMax=0)?250:0 ; suspend updates on minimize
66
+
67
+ ctrlW := Width - (oGui.MarginX * 2) ; ctrlW := Width - horzMargin
68
+ list := "Title,MousePos,Ctrl,Pos,SBText,VisText,AllText,Freeze"
69
+ Loop Parse list, ","
70
+ oGui["Ctrl_" A_LoopField].Move(,,ctrlW)
71
+ }
72
+
73
+ WinSpyClose(GuiObj) {
74
+ ExitApp
75
+ }
76
+
77
+ Update() { ; timer, no params
78
+ Try TryUpdate() ; Try
79
+ }
80
+
81
+ TryUpdate() {
82
+ Global oGui
83
+
84
+ If !oGui.HasProp("txtNotFrozen") ; WinSpyGui() not done yet, return until it is
85
+ return
86
+
87
+ Ctrl_FollowMouse := oGui["Ctrl_FollowMouse"].Value
88
+ CoordMode "Mouse", "Screen"
89
+ MouseGetPos &msX, &msY, &msWin, &msCtrl, 2 ; get ClassNN and hWindow
90
+ actWin := WinExist("A")
91
+
92
+ if (Ctrl_FollowMouse) {
93
+ curWin := msWin, curCtrl := msCtrl
94
+ WinExist("ahk_id " curWin) ; updating LastWindowFound?
95
+ } else {
96
+ curWin := actWin
97
+ curCtrl := ControlGetFocus() ; get focused control hwnd from active win
98
+ }
99
+ curCtrlClassNN := ""
100
+ Try curCtrlClassNN := ControlGetClassNN(curCtrl)
101
+
102
+ t1 := WinGetTitle(), t2 := WinGetClass()
103
+ if (curWin = oGui.hwnd || t2 = "MultitaskingViewFrame") { ; Our Gui || Alt-tab
104
+ UpdateText("Ctrl_Freeze", oGui.txtFrozen)
105
+ return
106
+ }
107
+
108
+ UpdateText("Ctrl_Freeze", oGui.txtNotFrozen)
109
+ t3 := WinGetProcessName(), t4 := WinGetPID()
110
+
111
+ WinDataText := t1 "`n" ; ZZZ
112
+ . "ahk_class " t2 "`n"
113
+ . "ahk_exe " t3 "`n"
114
+ . "ahk_pid " t4 "`n"
115
+ . "ahk_id " curWin
116
+
117
+ UpdateText("Ctrl_Title", WinDataText)
118
+ CoordMode "Mouse", "Window"
119
+ MouseGetPos &mrX, &mrY
120
+ CoordMode "Mouse", "Client"
121
+ MouseGetPos &mcX, &mcY
122
+ mClr := PixelGetColor(msX,msY,"RGB")
123
+ mClr := SubStr(mClr, 3)
124
+
125
+ mpText := "Screen:`t" msX ", " msY "`n"
126
+ . "Window:`t" mrX ", " mrY "`n"
127
+ . "Client:`t" mcX ", " mcY " (default)`n"
128
+ . "Color:`t" mClr " (Red=" SubStr(mClr, 1, 2) " Green=" SubStr(mClr, 3, 2) " Blue=" SubStr(mClr, 5) ")"
129
+
130
+ UpdateText("Ctrl_MousePos", mpText)
131
+
132
+ UpdateText("Ctrl_CtrlLabel", (Ctrl_FollowMouse ? oGui.txtMouseCtrl : oGui.txtFocusCtrl) ":")
133
+
134
+ if (curCtrl) {
135
+ ctrlTxt := ControlGetText(curCtrl)
136
+ WinGetClientPos(&sX, &sY, &sW, &sH, curCtrl)
137
+ ControlGetPos &cX, &cY, &cW, &cH, curCtrl
138
+
139
+ cText := "ClassNN:`t" curCtrlClassNN "`n"
140
+ . "Text:`t" textMangle(ctrlTxt) "`n"
141
+ . "Screen:`tx: " sX "`ty: " sY "`tw: " sW "`th: " sH "`n"
142
+ . "Client:`tx: " cX "`ty: " cY "`tw: " cW "`th: " cH
143
+ } else
144
+ cText := ""
145
+
146
+ UpdateText("Ctrl_Ctrl", cText)
147
+ wX := "", wY := "", wW := "", wH := ""
148
+ WinGetPos &wX, &wY, &wW, &wH, "ahk_id " curWin
149
+ WinGetClientPos(&wcX, &wcY, &wcW, &wcH, "ahk_id " curWin)
150
+
151
+ wText := "Screen:`tx: " wX "`ty: " wY "`tw: " wW "`th: " wH "`n"
152
+ . "Client:`tx: " wcX "`ty: " wcY "`tw: " wcW "`th: " wcH
153
+
154
+ UpdateText("Ctrl_Pos", wText)
155
+ sbTxt := ""
156
+
157
+ Loop {
158
+ ovi := ""
159
+ Try ovi := StatusBarGetText(A_Index)
160
+ if (ovi = "")
161
+ break
162
+ sbTxt .= "(" A_Index "):`t" textMangle(ovi) "`n"
163
+ }
164
+
165
+ sbTxt := SubStr(sbTxt,1,-1) ; StringTrimRight, sbTxt, sbTxt, 1
166
+ UpdateText("Ctrl_SBText", sbTxt)
167
+ bSlow := oGui["Ctrl_IsSlow"].Value ; GuiControlGet, bSlow,, Ctrl_IsSlow
168
+
169
+ if (bSlow) {
170
+ DetectHiddenText False
171
+ ovVisText := WinGetText() ; WinGetText, ovVisText
172
+ DetectHiddenText True
173
+ ovAllText := WinGetText() ; WinGetText, ovAllText
174
+ } else {
175
+ ovVisText := WinGetTextFast(false)
176
+ ovAllText := WinGetTextFast(true)
177
+ }
178
+
179
+ UpdateText("Ctrl_VisText", ovVisText)
180
+ UpdateText("Ctrl_AllText", ovAllText)
181
+ }
182
+
183
+ ; ===========================================================================================
184
+ ; WinGetText ALWAYS uses the "slow" mode - TitleMatchMode only affects
185
+ ; WinText/ExcludeText parameters. In "fast" mode, GetWindowText() is used
186
+ ; to retrieve the text of each control.
187
+ ; ===========================================================================================
188
+ WinGetTextFast(detect_hidden) {
189
+ controls := WinGetControlsHwnd()
190
+
191
+ static WINDOW_TEXT_SIZE := 32767 ; Defined in AutoHotkey source.
192
+
193
+ buf := Buffer(WINDOW_TEXT_SIZE * 2,0)
194
+
195
+ text := ""
196
+
197
+ Loop controls.Length {
198
+ hCtl := controls[A_Index]
199
+ if !detect_hidden && !DllCall("IsWindowVisible", "ptr", hCtl)
200
+ continue
201
+ if !DllCall("GetWindowText", "ptr", hCtl, "Ptr", buf.ptr, "int", WINDOW_TEXT_SIZE)
202
+ continue
203
+
204
+ text .= StrGet(buf) "`r`n" ; text .= buf "`r`n"
205
+ }
206
+ return text
207
+ }
208
+
209
+ ; ===========================================================================================
210
+ ; Unlike using a pure GuiControl, this function causes the text of the
211
+ ; controls to be updated only when the text has changed, preventing periodic
212
+ ; flickering (especially on older systems).
213
+ ; ===========================================================================================
214
+ UpdateText(vCtl, NewText) {
215
+ Global oGui
216
+ static OldText := {}
217
+ ctl := oGui[vCtl], hCtl := Integer(ctl.hwnd)
218
+
219
+ if (!oldText.HasProp(hCtl) Or OldText.%hCtl% != NewText) {
220
+ ctl.Value := NewText
221
+ OldText.%hCtl% := NewText
222
+ }
223
+ }
224
+
225
+ textMangle(x) {
226
+ elli := false
227
+ if (pos := InStr(x, "`n"))
228
+ x := SubStr(x, 1, pos-1), elli := true
229
+ else if (StrLen(x) > 40)
230
+ x := SubStr(x,1,40), elli := true
231
+ if elli
232
+ x .= " (...)"
233
+ return x
234
+ }
235
+
236
+ suspend_timer() {
237
+ Global oGui
238
+ SetTimer Update, 0
239
+ UpdateText("Ctrl_Freeze", oGui.txtFrozen)
240
+ }
241
+
242
+ ~*Shift::
243
+ ~*Ctrl::suspend_timer()
244
+
245
+ ~*Ctrl up::
246
+ ~*Shift up::SetTimer Update, 250
@@ -0,0 +1,12 @@
1
+
2
+ CommandLineToArgs(cmd) {
3
+ argv := DllCall("shell32\CommandLineToArgvW", "wstr", cmd, 'int*', &narg:=0, "ptr")
4
+ try {
5
+ args := []
6
+ Loop args.Capacity := narg
7
+ args.Push(StrGet(NumGet(argv, (A_Index-1)*A_PtrSize, "ptr"), "UTF-16"))
8
+ }
9
+ finally
10
+ DllCall("LocalFree", "ptr", argv)
11
+ return args
12
+ }
@@ -0,0 +1,37 @@
1
+ CreateAppShortcut(linkFile, p) {
2
+ ;target, args, description, aumid, uninst?
3
+ lnk := ComObject('{00021401-0000-0000-C000-000000000046}' ; CLSID_ShellLink
4
+ ,'{000214F9-0000-0000-C000-000000000046}') ; IID_IShellLink
5
+
6
+ ComCall(20, lnk, 'wstr', p.target)
7
+ ComCall(11, lnk, 'wstr', p.HasProp('args') ? p.args : "")
8
+ ComCall(7, lnk, 'wstr', p.desc)
9
+ if p.HasProp('icon')
10
+ ComCall(17, lnk, 'wstr', p.icon, 'int', p.HasProp('iconIndex') ? p.iconIndex : 0)
11
+
12
+ ; Set the System.AppUserModel.ID property via IPropertyStore
13
+ props := ComObjQuery(lnk, '{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}')
14
+ static PKEY_AppUserModel_ID := PKEY('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', 5)
15
+ static PKEY_AppUserModel_UninstallCommand := PKEY('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', 37)
16
+ setProp PKEY_AppUserModel_ID, p.aumid
17
+ if p.HasProp('uninst')
18
+ setProp PKEY_AppUserModel_UninstallCommand, p.uninst
19
+
20
+ ; Save via IPersistFile
21
+ pf := ComObjQuery(lnk, '{0000010B-0000-0000-C000-000000000046}')
22
+ ComCall(6, pf, 'wstr', linkFile, 'int', true)
23
+
24
+ setProp(key, value) {
25
+ propvar := Buffer(24, 0), propref := ComValue(0x400C, propvar.ptr)
26
+ propref[] := String(value)
27
+ ComCall(6, props, 'ptr', key, 'ptr', propvar)
28
+ propref[] := 0
29
+ }
30
+
31
+ PKEY(sguid, propID) {
32
+ pk := Buffer(20)
33
+ DllCall('ole32\IIDFromString', 'wstr', sguid, 'ptr', pk, 'hresult')
34
+ NumPut('int', propID, pk, 16)
35
+ return pk
36
+ }
37
+ }
@@ -0,0 +1,246 @@
1
+ EnableUIAccess(ExePath) {
2
+ static CertName := "AutoHotkey"
3
+ hStore := DllCall("Crypt32\CertOpenStore", "ptr", 10 ; STORE_PROV_SYSTEM_W
4
+ , "uint", 0, "ptr", 0, "uint", 0x20000 ; SYSTEM_STORE_LOCAL_MACHINE
5
+ , "wstr", "Root", "ptr")
6
+ if !hStore
7
+ throw OSError()
8
+ store := CertStore(hStore)
9
+ ; Find or create certificate for signing.
10
+ cert := CertContext()
11
+ while (cert.ptr := DllCall("Crypt32\CertFindCertificateInStore", "ptr", hStore
12
+ , "uint", 0x10001 ; X509_ASN_ENCODING|PKCS_7_ASN_ENCODING
13
+ , "uint", 0, "uint", 0x80007 ; FIND_SUBJECT_STR
14
+ , "wstr", CertName, "ptr", cert.ptr, "ptr"))
15
+ && !(DllCall("Crypt32\CryptAcquireCertificatePrivateKey"
16
+ , "ptr", cert, "uint", 5 ; CRYPT_ACQUIRE_CACHE_FLAG|CRYPT_ACQUIRE_COMPARE_KEY_FLAG
17
+ , "ptr", 0, "ptr*", 0, "uint*", &keySpec:=0, "ptr", 0)
18
+ && (keySpec & 2)) { ; AT_SIGNATURE
19
+ ; Keep looking for a certificate with a private key.
20
+ }
21
+ if !cert.ptr
22
+ cert := EnableUIAccess_CreateCert(CertName, hStore)
23
+ ; Set uiAccess attribute in manifest.
24
+ EnableUIAccess_SetManifest(ExePath)
25
+ ; Sign the file (otherwise uiAccess attribute is ignored).
26
+ EnableUIAccess_SignFile(ExePath, cert, CertName)
27
+ }
28
+
29
+ EnableUIAccess_SetManifest(ExePath) {
30
+ xml := ComObject("Msxml2.DOMDocument")
31
+ xml.async := false
32
+ xml.setProperty("SelectionLanguage", "XPath")
33
+ xml.setProperty("SelectionNamespaces"
34
+ , "xmlns:v1='urn:schemas-microsoft-com:asm.v1' "
35
+ . "xmlns:v3='urn:schemas-microsoft-com:asm.v3'")
36
+ try
37
+ if !xml.loadXML(EnableUIAccess_ReadManifest(ExePath))
38
+ throw Error("Invalid manifest")
39
+ catch as e
40
+ throw Error("Error loading manifest from " ExePath,, e.Message "`n @ " e.File ":" e.Line)
41
+
42
+
43
+ node := xml.selectSingleNode("/v1:assembly/v3:trustInfo/v3:security"
44
+ . "/v3:requestedPrivileges/v3:requestedExecutionLevel")
45
+ if !node ; Not AutoHotkey?
46
+ throw Error("Manifest is missing required elements")
47
+
48
+ node.setAttribute("uiAccess", "true")
49
+ xml := RTrim(xml.xml, "`r`n")
50
+
51
+ data := Buffer(StrPut(xml, "utf-8") - 1)
52
+ StrPut(xml, data, "utf-8")
53
+
54
+ if !(hupd := DllCall("BeginUpdateResource", "str", ExePath, "int", false))
55
+ throw OSError()
56
+ r := DllCall("UpdateResource", "ptr", hupd, "ptr", 24, "ptr", 1
57
+ , "ushort", 1033, "ptr", data, "uint", data.size)
58
+
59
+ ; Retry loop to work around file locks (especially by antivirus)
60
+ for delay in [0, 100, 500, 1000, 3500] {
61
+ Sleep delay
62
+ if DllCall("EndUpdateResource", "ptr", hupd, "int", !r) || !r
63
+ return
64
+ if !(A_LastError = 5 || A_LastError = 110) ; ERROR_ACCESS_DENIED || ERROR_OPEN_FAILED
65
+ break
66
+ }
67
+ throw OSError(A_LastError, "EndUpdateResource")
68
+ }
69
+
70
+ EnableUIAccess_ReadManifest(ExePath) {
71
+ if !(hmod := DllCall("LoadLibraryEx", "str", ExePath, "ptr", 0, "uint", 2, "ptr"))
72
+ throw OSError()
73
+ try {
74
+ if !(hres := DllCall("FindResource", "ptr", hmod, "ptr", 1, "ptr", 24, "ptr"))
75
+ throw OSError()
76
+ size := DllCall("SizeofResource", "ptr", hmod, "ptr", hres, "uint")
77
+ if !(hglb := DllCall("LoadResource", "ptr", hmod, "ptr", hres, "ptr"))
78
+ throw OSError()
79
+ if !(pres := DllCall("LockResource", "ptr", hglb, "ptr"))
80
+ throw OSError()
81
+ return StrGet(pres, size, "utf-8")
82
+ }
83
+ finally
84
+ DllCall("FreeLibrary", "ptr", hmod)
85
+ }
86
+
87
+ EnableUIAccess_CreateCert(Name, hStore) {
88
+ ; Here Name is used as the key container name.
89
+ prov := CryptContext()
90
+ if !DllCall("Advapi32\CryptAcquireContext", "ptr*", prov
91
+ , "str", Name, "ptr", 0, "uint", 1, "uint", 0) { ; PROV_RSA_FULL=1, open existing=0
92
+ if !DllCall("Advapi32\CryptAcquireContext", "ptr*", prov
93
+ , "str", Name, "ptr", 0, "uint", 1, "uint", 8) ; PROV_RSA_FULL=1, CRYPT_NEWKEYSET=8
94
+ throw OSError()
95
+ if !DllCall("Advapi32\CryptGenKey", "ptr", prov
96
+ , "uint", 2, "uint", 0x4000001, "ptr*", CryptKey()) ; AT_SIGNATURE=2, EXPORTABLE=..01
97
+ throw OSError()
98
+ }
99
+
100
+ ; Here Name is used as the certificate subject and name.
101
+ Loop 2 {
102
+ if A_Index = 1
103
+ pbName := cbName := 0
104
+ else
105
+ bName := Buffer(cbName), pbName := bName.ptr
106
+ if !DllCall("Crypt32\CertStrToName", "uint", 1, "str", "CN=" Name
107
+ , "uint", 3, "ptr", 0, "ptr", pbName, "uint*", &cbName, "ptr", 0) ; X509_ASN_ENCODING=1, CERT_X500_NAME_STR=3
108
+ throw OSError()
109
+ }
110
+ cnb := Buffer(2*A_PtrSize), NumPut("ptr", cbName, "ptr", pbName, cnb)
111
+
112
+ ; Set expiry to 9999-01-01 12pm +0.
113
+ NumPut("short", 9999, "sort", 1, "short", 5, "short", 1, "short", 12, endTime := Buffer(16, 0))
114
+
115
+ StrPut("2.5.29.4", szOID_KEY_USAGE_RESTRICTION := Buffer(9),, "cp0")
116
+ StrPut("2.5.29.37", szOID_ENHANCED_KEY_USAGE := Buffer(10),, "cp0")
117
+ StrPut("1.3.6.1.5.5.7.3.3", szOID_PKIX_KP_CODE_SIGNING := Buffer(18),, "cp0")
118
+
119
+ ; CERT_KEY_USAGE_RESTRICTION_INFO key_usage;
120
+ key_usage := Buffer(6*A_PtrSize, 0)
121
+ NumPut('ptr', 0, 'ptr', 0, 'ptr', 1, 'ptr', key_usage.ptr + 5*A_PtrSize, 'ptr', 0
122
+ , 'uchar', (CERT_DATA_ENCIPHERMENT_KEY_USAGE := 0x10)
123
+ | (CERT_DIGITAL_SIGNATURE_KEY_USAGE := 0x80), key_usage)
124
+
125
+ ; CERT_ENHKEY_USAGE enh_usage;
126
+ enh_usage := Buffer(3*A_PtrSize)
127
+ NumPut("ptr", 1, "ptr", enh_usage.ptr + 2*A_PtrSize, "ptr", szOID_PKIX_KP_CODE_SIGNING.ptr, enh_usage)
128
+
129
+ key_usage_data := EncodeObject(szOID_KEY_USAGE_RESTRICTION, key_usage)
130
+ enh_usage_data := EncodeObject(szOID_ENHANCED_KEY_USAGE, enh_usage)
131
+
132
+ EncodeObject(structType, structInfo) {
133
+ encoder := DllCall.Bind("Crypt32\CryptEncodeObject", "uint", X509_ASN_ENCODING := 1
134
+ , "ptr", structType, "ptr", structInfo)
135
+ if !encoder("ptr", 0, "uint*", &enc_size := 0)
136
+ throw OSError()
137
+ enc_data := Buffer(enc_size)
138
+ if !encoder("ptr", enc_data, "uint*", &enc_size)
139
+ throw OSError()
140
+ enc_data.Size := enc_size
141
+ return enc_data
142
+ }
143
+
144
+ ; CERT_EXTENSION extension[2]; CERT_EXTENSIONS extensions;
145
+ NumPut("ptr", szOID_KEY_USAGE_RESTRICTION.ptr, "ptr", true, "ptr", key_usage_data.size, "ptr", key_usage_data.ptr
146
+ , "ptr", szOID_ENHANCED_KEY_USAGE.ptr, "ptr", true, "ptr", enh_usage_data.size, "ptr", enh_usage_data.ptr
147
+ , extension := Buffer(8*A_PtrSize))
148
+ NumPut("ptr", 2, "ptr", extension.ptr, extensions := Buffer(2*A_PtrSize))
149
+
150
+ if !hCert := DllCall("Crypt32\CertCreateSelfSignCertificate"
151
+ , "ptr", prov, "ptr", cnb, "uint", 0, "ptr", 0
152
+ , "ptr", 0, "ptr", 0, "ptr", endTime, "ptr", extensions, "ptr")
153
+ throw OSError()
154
+ cert := CertContext(hCert)
155
+
156
+ if !DllCall("Crypt32\CertAddCertificateContextToStore", "ptr", hStore
157
+ , "ptr", hCert, "uint", 1, "ptr", 0) ; STORE_ADD_NEW=1
158
+ throw OSError()
159
+
160
+ return cert
161
+ }
162
+
163
+ EnableUIAccess_DeleteCertAndKey(Name) {
164
+ ; This first call "acquires" the key container but also deletes it.
165
+ DllCall("Advapi32\CryptAcquireContext", "ptr*", 0, "str", Name
166
+ , "ptr", 0, "uint", 1, "uint", 16) ; PROV_RSA_FULL=1, CRYPT_DELETEKEYSET=16
167
+ if !hStore := DllCall("Crypt32\CertOpenStore", "ptr", 10 ; STORE_PROV_SYSTEM_W
168
+ , "uint", 0, "ptr", 0, "uint", 0x20000 ; SYSTEM_STORE_LOCAL_MACHINE
169
+ , "wstr", "Root", "ptr")
170
+ throw OSError()
171
+ store := CertStore(hStore)
172
+ deleted := 0
173
+ ; Multiple certificates might be created over time as keys become inaccessible.
174
+ while p := DllCall("Crypt32\CertFindCertificateInStore", "ptr", hStore
175
+ , "uint", 0x10001 ; X509_ASN_ENCODING|PKCS_7_ASN_ENCODING
176
+ , "uint", 0, "uint", 0x80007 ; FIND_SUBJECT_STR
177
+ , "wstr", Name, "ptr", 0, "ptr") {
178
+ if !DllCall("Crypt32\CertDeleteCertificateFromStore", "ptr", p)
179
+ throw OSError()
180
+ deleted++
181
+ }
182
+ return deleted
183
+ }
184
+
185
+ class CryptPtrBase {
186
+ __new(p:=0) => this.ptr := p
187
+ __delete() => this.ptr && this.Dispose()
188
+ }
189
+ class CryptContext extends CryptPtrBase {
190
+ Dispose() => DllCall("Advapi32\CryptReleaseContext", "ptr", this, "uint", 0)
191
+ }
192
+ class CertContext extends CryptPtrBase {
193
+ Dispose() => DllCall("Crypt32\CertFreeCertificateContext", "ptr", this)
194
+ }
195
+ class CertStore extends CryptPtrBase {
196
+ Dispose() => DllCall("Crypt32\CertCloseStore", "ptr", this, "uint", 0)
197
+ }
198
+ class CryptKey extends CryptPtrBase {
199
+ Dispose() => DllCall("Advapi32\CryptDestroyKey", "ptr", this)
200
+ }
201
+
202
+ EnableUIAccess_SignFile(ExePath, CertCtx, Name) {
203
+ file_info := struct( ; SIGNER_FILE_INFO
204
+ "ptr", A_PtrSize*3, "ptr", StrPtr(ExePath))
205
+ dwIndex := Buffer(4, 0) ; DWORD
206
+ subject_info := struct( ; SIGNER_SUBJECT_INFO
207
+ "ptr", A_PtrSize*4, "ptr", dwIndex.ptr, "ptr", SIGNER_SUBJECT_FILE:=1,
208
+ "ptr", file_info.ptr)
209
+ cert_store_info := struct( ; SIGNER_CERT_STORE_INFO
210
+ "ptr", A_PtrSize*4, "ptr", CertCtx.ptr, "ptr", SIGNER_CERT_POLICY_CHAIN:=2)
211
+ cert_info := struct( ; SIGNER_CERT
212
+ "uint", 8+A_PtrSize*2, "uint", SIGNER_CERT_STORE:=2,
213
+ "ptr", cert_store_info.ptr)
214
+ authcode_attr := struct( ; SIGNER_ATTR_AUTHCODE
215
+ "uint", 8+A_PtrSize*3, "int", false, "ptr", true, "ptr", StrPtr(Name))
216
+ sig_info := struct( ; SIGNER_SIGNATURE_INFO
217
+ "uint", 8+A_PtrSize*4, "uint", CALG_SHA1:=0x8004,
218
+ "ptr", SIGNER_AUTHCODE_ATTR:=1, "ptr", authcode_attr.ptr)
219
+
220
+ DllCall("MSSign32\SignerSign"
221
+ , "ptr", subject_info, "ptr", cert_info, "ptr", sig_info
222
+ , "ptr", 0, "ptr", 0, "ptr", 0, "ptr", 0, "hresult")
223
+
224
+ struct(args*) => (
225
+ args.Push(b := Buffer(args[2], 0)),
226
+ NumPut(args*),
227
+ b
228
+ )
229
+ }
230
+
231
+ ; Verifies a signed executable file. Returns 0 on success, or a standard OS error number.
232
+ EnableUIAccess_Verify(ExePath) {
233
+ wfi := Buffer(4*A_PtrSize) ; WINTRUST_FILE_INFO
234
+ NumPut('ptr', wfi.size, 'ptr', StrPtr(ExePath), 'ptr', 0, 'ptr', 0, wfi)
235
+
236
+ ; WINTRUST_ACTION_GENERIC_VERIFY_V2
237
+ NumPut('int64', 0x11d0cd4400aac56b, 'int64', 0xee95c24fc000c28c, actionID := Buffer(16))
238
+
239
+ wtd := Buffer(9*A_PtrSize+16) ; WINTRUST_DATA
240
+ NumPut(
241
+ 'ptr', wtd.Size, 'ptr', 0, 'ptr', 0, 'int', WTD_UI_NONE:=2, 'int', WTD_REVOKE_NONE:=0,
242
+ 'ptr', WTD_CHOICE_FILE:=1, 'ptr', wfi.ptr, 'ptr', WTD_STATEACTION_VERIFY:=1,
243
+ 'ptr', 0, 'ptr', 0, 'int', 0, 'int', 0, 'ptr', 0, wtd
244
+ )
245
+ return DllCall('wintrust\WinVerifyTrust', 'ptr', 0, 'ptr', actionID, 'ptr', wtd, 'int')
246
+ }