@neuvybe/jarvis 0.68.0 → 0.70.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.
@@ -0,0 +1,135 @@
1
+ # Windows hand-off for the `open` tool (packages/core/src/tools/open-launch.ts).
2
+ # One request per process: it reads one binary spec from standard input, asks the running
3
+ # Explorer to open the target, and exits with a fixed code. Explorer creates the app as its own
4
+ # child, with Explorer's environment, outside every Jarvis container. It writes nothing; its
5
+ # exit code is all it tells the core. Operations: 0 open, 1 probe (is a desktop shell there?),
6
+ # 2 check (the second look alone, no COM). Fixed codes: 0 opened (a probe: a shell is there; a
7
+ # check: accepted), 0x6A560011 restricted language mode, 0x6A560012 the compile failed, 0x6A560013 the
8
+ # spec was rejected, 0x6A560014 no desktop shell, 0x6A560015 Explorer refused, 0x6A560016 an
9
+ # internal failure. With no desktop shell window it activates nothing, so it never starts
10
+ # Explorer itself.
11
+ $ErrorActionPreference = 'Stop'
12
+ $ProgressPreference = 'SilentlyContinue'
13
+ $PSModuleAutoLoadingPreference = 'None'
14
+ # Restricted language mode blocks the compile below, so it exits with no output at all.
15
+ if ($ExecutionContext.SessionState.LanguageMode -ne 'FullLanguage') { exit 0x6A560011 }
16
+ $code = @'
17
+ using System;
18
+ using System.IO;
19
+ using System.Runtime.InteropServices;
20
+ using System.Text;
21
+
22
+ public static class JarvisOpen {
23
+ const int Opened = 0;
24
+ const int Spec = 0x6A560013;
25
+ const int NoDesktop = 0x6A560014;
26
+ const int Refused = 0x6A560015;
27
+ const int Internal = 0x6A560016;
28
+ const int MaxSpec = 64 * 1024;
29
+ const int MaxField = 32 * 1024;
30
+
31
+ [DllImport("user32.dll")]
32
+ static extern IntPtr GetShellWindow();
33
+
34
+ public static int Run() {
35
+ try {
36
+ byte[] spec = ReadSpec();
37
+ if (spec == null || spec.Length < 5) return Spec;
38
+ if (spec[0] != (byte)'J' || spec[1] != (byte)'V' || spec[2] != (byte)'O' || spec[3] != (byte)'1') return Spec;
39
+ int op = spec[4];
40
+ int offset = 5;
41
+ string file = ReadField(spec, ref offset);
42
+ string args = ReadField(spec, ref offset);
43
+ if (file == null || args == null || offset != spec.Length) return Spec;
44
+ // A check runs only the second look below: no COM, nothing opened (tests, diagnostics).
45
+ if (op == 2) return Acceptable(file, args) ? Opened : Spec;
46
+ if (op == 1) return ShellApplication() == null ? NoDesktop : Opened;
47
+ if (op != 0 || !Acceptable(file, args)) return Spec;
48
+ object shell = ShellApplication();
49
+ if (shell == null) return NoDesktop;
50
+ try {
51
+ dynamic dispatch = shell;
52
+ dispatch.ShellExecute(file, args, "", "open", 1);
53
+ } catch {
54
+ return Refused;
55
+ }
56
+ return Opened;
57
+ } catch {
58
+ return Internal;
59
+ }
60
+ }
61
+
62
+ static byte[] ReadSpec() {
63
+ using (Stream input = Console.OpenStandardInput())
64
+ using (MemoryStream buffer = new MemoryStream()) {
65
+ byte[] chunk = new byte[4096];
66
+ int read;
67
+ while ((read = input.Read(chunk, 0, chunk.Length)) > 0) {
68
+ if (buffer.Length + read > MaxSpec) return null;
69
+ buffer.Write(chunk, 0, read);
70
+ }
71
+ return buffer.ToArray();
72
+ }
73
+ }
74
+
75
+ static string ReadField(byte[] spec, ref int offset) {
76
+ if (offset + 4 > spec.Length) return null;
77
+ int length = BitConverter.ToInt32(spec, offset);
78
+ offset += 4;
79
+ if (length < 0 || length > MaxField || length % 2 != 0 || offset + length > spec.Length) return null;
80
+ string text = Encoding.Unicode.GetString(spec, offset, length);
81
+ offset += length;
82
+ return text;
83
+ }
84
+
85
+ // The core checks every target first; this is the second, narrower look: a page, a drive
86
+ // path, or a vetted program with one quoted path as its argument. Nothing here is echoed.
87
+ static bool Acceptable(string file, string args) {
88
+ foreach (char c in file + args) if (c < ' ' || c == (char)127) return false;
89
+ if (args.Length == 0) return IsPage(file) || IsDrivePath(file);
90
+ if (!IsDrivePath(file) || !file.EndsWith(".exe", StringComparison.OrdinalIgnoreCase)) return false;
91
+ if (args.Length < 3 || args[0] != '"' || args[args.Length - 1] != '"') return false;
92
+ string inner = args.Substring(1, args.Length - 2);
93
+ return inner.IndexOf('"') < 0 && IsDrivePath(inner.TrimEnd('\\') + "\\");
94
+ }
95
+
96
+ static bool IsPage(string file) {
97
+ bool scheme = file.StartsWith("http://", StringComparison.Ordinal)
98
+ || file.StartsWith("https://", StringComparison.Ordinal);
99
+ return scheme && file.IndexOf('"') < 0 && file.IndexOf(' ') < 0 && file.IndexOf('\\') < 0;
100
+ }
101
+
102
+ static bool IsDrivePath(string path) {
103
+ if (path.Length < 3 || !char.IsLetter(path[0]) || path[1] != ':' || path[2] != '\\') return false;
104
+ if (path.IndexOf(':', 2) >= 0 || path.IndexOf('%') >= 0 || path.IndexOf('"') >= 0) return false;
105
+ if (path.IndexOf("shell:", StringComparison.OrdinalIgnoreCase) >= 0) return false;
106
+ return path.IndexOfAny(new char[] { '<', '>', '|', '?', '*' }) < 0;
107
+ }
108
+
109
+ // The running Explorer's shell automation object for the desktop, or null with no desktop
110
+ // shell. GetShellWindow comes first: with no shell window nothing is activated, so this
111
+ // never starts Explorer.
112
+ static object ShellApplication() {
113
+ if (GetShellWindow() == IntPtr.Zero) return null;
114
+ Type type = Type.GetTypeFromCLSID(new Guid("9BA05972-F6A8-11CF-A442-00A0C90A8F39"));
115
+ dynamic windows = Activator.CreateInstance(type);
116
+ object location = 0;
117
+ object root = null;
118
+ int hwnd;
119
+ dynamic desktop = windows.FindWindowSW(ref location, ref root, 8, out hwnd, 1);
120
+ if (desktop == null) return null;
121
+ dynamic view = desktop.Document;
122
+ if (view == null) return null;
123
+ return view.Application;
124
+ }
125
+ }
126
+ '@
127
+ try {
128
+ # Add-Type lives in this one module. Importing it by path, with auto-loading off (as the host's
129
+ # privacy helper does), spares a new profile the analysis of every installed module.
130
+ Import-Module "$PSHOME\Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1"
131
+ Add-Type -TypeDefinition $code -Language CSharp -ReferencedAssemblies 'Microsoft.CSharp', 'System.Core'
132
+ } catch {
133
+ exit 0x6A560012
134
+ }
135
+ exit [JarvisOpen]::Run()