1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4  * PURPOSE:     Tests for wscript.exe
5  * COPYRIGHT:   Whindmar Saksit (whindsaks@proton.me)
6  */
7 
8 #include <apitest.h>
9 #include <windows.h>
10 #include <shlwapi.h>
11 #include <stdio.h>
12 
13 #define MYGUID "{898AC78E-BFC7-41FF-937D-EDD01E666707}"
14 
getregdw(HKEY hKey,LPCSTR sub,LPCSTR name,DWORD * out,DWORD defval)15 static DWORD getregdw(HKEY hKey, LPCSTR sub, LPCSTR name, DWORD *out, DWORD defval)
16 {
17     LRESULT e;
18     DWORD size = sizeof(*out);
19     *out = 0;
20     e = SHGetValueA(hKey, sub, name, NULL, out, &size);
21     if (e)
22         *out = defval;
23     return e;
24 }
25 
makestringfile(LPWSTR path,SIZE_T cchpath,LPCSTR ext,LPCSTR string,const BYTE * map)26 static BOOL makestringfile(LPWSTR path, SIZE_T cchpath, LPCSTR ext, LPCSTR string, const BYTE *map)
27 {
28     UINT cch = GetTempPathW(cchpath, path);
29     UINT16 i = 0;
30     if (!cch || cch > cchpath)
31         return FALSE;
32     while (++i)
33     {
34         HANDLE hFile;
35         if (_snwprintf(path + cch, cchpath - cch, L"~%u.%hs", i, ext ? ext : "tmp") >= cchpath - cch)
36             return FALSE;
37         hFile = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, 0, NULL);
38         if (hFile != INVALID_HANDLE_VALUE)
39         {
40             BOOL succ = TRUE;
41             for (; *string && succ; ++string)
42             {
43                 BYTE ch = *string;
44                 DWORD j;
45                 for (j = 0; map && map[j + 0]; j += 2)
46                 {
47                     if (ch == map[j + 0])
48                         ch = map[j + 1];
49                 }
50                 succ = WriteFile(hFile, &ch, 1, &j, NULL);
51             }
52             CloseHandle(hFile);
53             return succ;
54         }
55     }
56     return FALSE;
57 }
58 
runscriptfile(LPCWSTR path,LPCWSTR engine)59 static DWORD runscriptfile(LPCWSTR path, LPCWSTR engine)
60 {
61     STARTUPINFOW si;
62     PROCESS_INFORMATION pi;
63     LPCWSTR exe = engine ? engine : L"wscript.exe";
64     WCHAR cmd[MAX_PATH * 2];
65 
66     if (_snwprintf(cmd, _countof(cmd), L"\"%s\" //nologo \"%s\"", exe, path) >= _countof(cmd))
67         return ERROR_BUFFER_OVERFLOW;
68     ZeroMemory(&si, sizeof(si));
69     si.cb = sizeof(si);
70     if (CreateProcessW(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
71     {
72         DWORD code = ERROR_INTERNAL_ERROR;
73         WaitForSingleObject(pi.hProcess, INFINITE);
74         GetExitCodeProcess(pi.hProcess, &code);
75         CloseHandle(pi.hProcess);
76         CloseHandle(pi.hThread);
77         return code;
78     }
79     return GetLastError();
80 }
81 
runscript(LPCSTR ext,LPCSTR script,const BYTE * map)82 static DWORD runscript(LPCSTR ext, LPCSTR script, const BYTE *map)
83 {
84     DWORD code;
85     WCHAR file[MAX_PATH];
86     if (!makestringfile(file, _countof(file), ext, script, map))
87     {
88         skip("Unable to create script\n");
89         return ERROR_FILE_NOT_FOUND;
90     }
91     code = runscriptfile(file, NULL);
92     DeleteFileW(file);
93     return code;
94 }
95 
test_defaultscriptisjs(void)96 static void test_defaultscriptisjs(void)
97 {
98     LPCSTR script = ""
99     "<job>"
100     "<script>" /* No language attribute should default to Javascript */
101     "var x = 42;"
102     "WScript.Quit(x);"
103     "</script>"
104     "</job>";
105 
106     ok(runscript("wsf", script, NULL) == 42, "Script failed\n");
107 }
108 
test_simplevb(void)109 static void test_simplevb(void)
110 {
111     LPCSTR script = ""
112     "<job>"
113     "<script language=\"VBScript\">"
114     "Dim x\n"
115     "x = 42\n"
116     "WScript.Quit x\n"
117     "</script>"
118     "</job>";
119 
120     ok(runscript("wsf", script, NULL) == 42, "Script failed\n");
121 }
122 
test_defpackagejob(void)123 static void test_defpackagejob(void)
124 {
125     LPCSTR script = ""
126     "<package>"
127     "<job id=\"PickMePlease\">"
128     "<script language=\"VBScript\">"
129     "WScript.Quit 42"
130     "</script>"
131     "</job>"
132     "<job id=\"DontExecuteMe\">"
133     "<script language=\"VBScript\">"
134     "WScript.Quit 33"
135     "</script>"
136     "</job>"
137     "</package>";
138 
139     ok(runscript("wsf", script, NULL) == 42, "Script failed\n");
140 }
141 
test_objecttag(void)142 static void test_objecttag(void)
143 {
144     DWORD dw;
145     static const BYTE map[] = { '#', '\"', '$', '\\', 0, 0 };
146     LPCSTR script = ""
147     "<job>"
148     "<object id=#ws1# clsid=#{72C24DD5-D70A-438B-8A42-98424B88AFB8}# />"
149     "<script language=#JScript#>"
150     "var dontcare = ws1.ExpandEnvironmentStrings(#SystemRoot#);"
151     "var p = #HKCU/Software/" MYGUID "#.replace(/$//g,'$$');"
152     "ws2.RegWrite(p, 42, #REG_DWORD#);"
153     "</script>"
154     "<object id=#ws2# progid=#WScript.Shell# />" /* Placing the object tag after the script just for fun */
155     "</job>";
156 
157     ok(runscript("wsf", script, map) == 0, "Script failed\n");
158 
159     getregdw(HKEY_CURRENT_USER, "Software", MYGUID, &dw, 0);
160     ok(dw == 42, "Value does not match\n");
161     SHDeleteValueA(HKEY_CURRENT_USER, "Software", MYGUID);
162 }
163 
START_TEST(wsf)164 START_TEST(wsf)
165 {
166     test_defaultscriptisjs();
167     test_simplevb();
168     test_defpackagejob();
169     test_objecttag();
170 }
171