1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Copyright 2011 Jacek Caban for CodeWeavers
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
5c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
6c2c66affSColin Finck  * License as published by the Free Software Foundation; either
7c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
8c2c66affSColin Finck  *
9c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
10c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12c2c66affSColin Finck  * Lesser General Public License for more details.
13c2c66affSColin Finck  *
14c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
15c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
16c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17c2c66affSColin Finck  */
18c2c66affSColin Finck 
19c2c66affSColin Finck #include <stdio.h>
20c2c66affSColin Finck 
21c2c66affSColin Finck #define COBJMACROS
22c2c66affSColin Finck #define CONST_VTABLE
23c2c66affSColin Finck 
243c774903SAmine Khaldi #define PSAPI_VERSION 1
253c774903SAmine Khaldi #include <initguid.h>
263c774903SAmine Khaldi #include <windows.h>
27c2c66affSColin Finck #include <psapi.h>
283c774903SAmine Khaldi #include <oaidl.h>
29c2c66affSColin Finck 
303c774903SAmine Khaldi #include "wine/test.h"
31c2c66affSColin Finck 
32c2c66affSColin Finck #define DEFINE_EXPECT(func) \
33c2c66affSColin Finck     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34c2c66affSColin Finck 
35c2c66affSColin Finck #define SET_EXPECT(func) \
36c2c66affSColin Finck     expect_ ## func = TRUE
37c2c66affSColin Finck 
38c2c66affSColin Finck #define CLEAR_CALLED(func) \
39c2c66affSColin Finck     expect_ ## func = called_ ## func = FALSE
40c2c66affSColin Finck 
41c2c66affSColin Finck #define CHECK_EXPECT2(func) \
42c2c66affSColin Finck     do { \
43c2c66affSColin Finck         ok(expect_ ##func, "unexpected call " #func "\n"); \
44c2c66affSColin Finck         called_ ## func = TRUE; \
45c2c66affSColin Finck     }while(0)
46c2c66affSColin Finck 
47c2c66affSColin Finck #define CHECK_EXPECT(func) \
48c2c66affSColin Finck     do { \
49c2c66affSColin Finck         CHECK_EXPECT2(func); \
50c2c66affSColin Finck         expect_ ## func = FALSE; \
51c2c66affSColin Finck     }while(0)
52c2c66affSColin Finck 
53c2c66affSColin Finck #define CHECK_CALLED(func) \
54c2c66affSColin Finck     do { \
55c2c66affSColin Finck         ok(called_ ## func, "expected " #func "\n"); \
56c2c66affSColin Finck         expect_ ## func = called_ ## func = FALSE; \
57c2c66affSColin Finck     }while(0)
58c2c66affSColin Finck 
59c2c66affSColin Finck DEFINE_EXPECT(reportSuccess);
60c2c66affSColin Finck 
61c2c66affSColin Finck #define DISPID_TESTOBJ_OK                        10000
62c2c66affSColin Finck #define DISPID_TESTOBJ_TRACE                     10001
63c2c66affSColin Finck #define DISPID_TESTOBJ_REPORTSUCCESS             10002
64c2c66affSColin Finck #define DISPID_TESTOBJ_WSCRIPTFULLNAME           10003
65c2c66affSColin Finck #define DISPID_TESTOBJ_WSCRIPTPATH               10004
66c2c66affSColin Finck #define DISPID_TESTOBJ_WSCRIPTSCRIPTNAME         10005
67c2c66affSColin Finck #define DISPID_TESTOBJ_WSCRIPTSCRIPTFULLNAME     10006
68c2c66affSColin Finck 
69c2c66affSColin Finck #define TESTOBJ_CLSID "{178fc166-f585-4e24-9c13-4bb7faf80646}"
70c2c66affSColin Finck 
71c2c66affSColin Finck static const GUID CLSID_TestObj =
72c2c66affSColin Finck     {0x178fc166,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xfa,0xf8,0x06,0x46}};
73c2c66affSColin Finck 
74c2c66affSColin Finck static const char *script_name;
75c2c66affSColin Finck static HANDLE wscript_process;
76c2c66affSColin Finck 
strcmp_wa(LPCWSTR strw,const char * stra)77c2c66affSColin Finck static int strcmp_wa(LPCWSTR strw, const char *stra)
78c2c66affSColin Finck {
79c2c66affSColin Finck     WCHAR buf[512];
80*f2df3bf0SAmine Khaldi     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, ARRAY_SIZE(buf));
81c2c66affSColin Finck     return lstrcmpW(strw, buf);
82c2c66affSColin Finck }
83c2c66affSColin Finck 
mystrrchr(const WCHAR * str,WCHAR ch)84c2c66affSColin Finck static const WCHAR* mystrrchr(const WCHAR *str, WCHAR ch)
85c2c66affSColin Finck {
86c2c66affSColin Finck     const WCHAR *pos = NULL, *current = str;
87c2c66affSColin Finck     while(*current != 0) {
88c2c66affSColin Finck         if(*current == ch)
89c2c66affSColin Finck             pos = current;
90c2c66affSColin Finck         ++current;
91c2c66affSColin Finck     }
92c2c66affSColin Finck     return pos;
93c2c66affSColin Finck }
94c2c66affSColin Finck 
a2bstr(const char * str)95c2c66affSColin Finck static BSTR a2bstr(const char *str)
96c2c66affSColin Finck {
97c2c66affSColin Finck     BSTR ret;
98c2c66affSColin Finck     int len;
99c2c66affSColin Finck 
100c2c66affSColin Finck     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
101c2c66affSColin Finck     ret = SysAllocStringLen(NULL, len-1);
102c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
103c2c66affSColin Finck 
104c2c66affSColin Finck     return ret;
105c2c66affSColin Finck }
106c2c66affSColin Finck 
Dispatch_QueryInterface(IDispatch * iface,REFIID riid,void ** ppv)107c2c66affSColin Finck static HRESULT WINAPI Dispatch_QueryInterface(IDispatch *iface, REFIID riid, void **ppv)
108c2c66affSColin Finck {
109c2c66affSColin Finck     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDispatch)) {
110c2c66affSColin Finck         *ppv = iface;
111c2c66affSColin Finck 	return S_OK;
112c2c66affSColin Finck     }
113c2c66affSColin Finck 
114c2c66affSColin Finck     *ppv = NULL;
115c2c66affSColin Finck     return E_NOINTERFACE;
116c2c66affSColin Finck }
117c2c66affSColin Finck 
Dispatch_AddRef(IDispatch * iface)118c2c66affSColin Finck static ULONG WINAPI Dispatch_AddRef(IDispatch *iface)
119c2c66affSColin Finck {
120c2c66affSColin Finck     return 2;
121c2c66affSColin Finck }
122c2c66affSColin Finck 
Dispatch_Release(IDispatch * iface)123c2c66affSColin Finck static ULONG WINAPI Dispatch_Release(IDispatch *iface)
124c2c66affSColin Finck {
125c2c66affSColin Finck     return 1;
126c2c66affSColin Finck }
127c2c66affSColin Finck 
Dispatch_GetTypeInfoCount(IDispatch * iface,UINT * pctinfo)128c2c66affSColin Finck static HRESULT WINAPI Dispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
129c2c66affSColin Finck {
130c2c66affSColin Finck     ok(0, "unexpected call\n");
131c2c66affSColin Finck     return E_NOTIMPL;
132c2c66affSColin Finck }
133c2c66affSColin Finck 
Dispatch_GetTypeInfo(IDispatch * iface,UINT iTInfo,LCID lcid,ITypeInfo ** ppTInfo)134c2c66affSColin Finck static HRESULT WINAPI Dispatch_GetTypeInfo(IDispatch *iface, UINT iTInfo,
135c2c66affSColin Finck 	LCID lcid, ITypeInfo **ppTInfo)
136c2c66affSColin Finck {
137c2c66affSColin Finck     ok(0, "unexpected call\n");
138c2c66affSColin Finck     return E_NOTIMPL;
139c2c66affSColin Finck }
140c2c66affSColin Finck 
Dispatch_GetIDsOfNames(IDispatch * iface,REFIID riid,LPOLESTR * rgszNames,UINT cNames,LCID lcid,DISPID * rgDispId)141c2c66affSColin Finck static HRESULT WINAPI Dispatch_GetIDsOfNames(IDispatch *iface, REFIID riid,
142c2c66affSColin Finck         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
143c2c66affSColin Finck {
144c2c66affSColin Finck     unsigned i;
145c2c66affSColin Finck 
146c2c66affSColin Finck     for(i=0; i<cNames; i++) {
147c2c66affSColin Finck         if(!strcmp_wa(rgszNames[i], "ok")) {
148c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_OK;
149c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "trace")) {
150c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_TRACE;
151c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "reportSuccess")) {
152c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_REPORTSUCCESS;
153c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "wscriptFullName")) {
154c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_WSCRIPTFULLNAME;
155c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "wscriptPath")) {
156c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_WSCRIPTPATH;
157c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "wscriptScriptName")) {
158c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_WSCRIPTSCRIPTNAME;
159c2c66affSColin Finck         }else if(!strcmp_wa(rgszNames[i], "wscriptScriptFullName")) {
160c2c66affSColin Finck             rgDispId[i] = DISPID_TESTOBJ_WSCRIPTSCRIPTFULLNAME;
161c2c66affSColin Finck         }else {
162c2c66affSColin Finck             ok(0, "unexpected name %s\n", wine_dbgstr_w(rgszNames[i]));
163c2c66affSColin Finck             return DISP_E_UNKNOWNNAME;
164c2c66affSColin Finck         }
165c2c66affSColin Finck     }
166c2c66affSColin Finck 
167c2c66affSColin Finck     return S_OK;
168c2c66affSColin Finck }
169c2c66affSColin Finck 
Dispatch_Invoke(IDispatch * iface,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS * pdp,VARIANT * pVarResult,EXCEPINFO * pExcepInfo,UINT * puArgErr)170c2c66affSColin Finck static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
171c2c66affSColin Finck 				      WORD wFlags, DISPPARAMS *pdp, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
172c2c66affSColin Finck {
173c2c66affSColin Finck     switch(dispIdMember) {
174c2c66affSColin Finck     case DISPID_TESTOBJ_OK: {
175c2c66affSColin Finck         VARIANT *expr, *msg;
176c2c66affSColin Finck 
177c2c66affSColin Finck         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
178c2c66affSColin Finck         ok(pdp->cArgs == 2, "cArgs = %d\n", pdp->cArgs);
179c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
180c2c66affSColin Finck 
181c2c66affSColin Finck         expr = pdp->rgvarg+1;
182c2c66affSColin Finck         if(V_VT(expr) == (VT_VARIANT|VT_BYREF))
183c2c66affSColin Finck             expr = V_VARIANTREF(expr);
184c2c66affSColin Finck 
185c2c66affSColin Finck         msg = pdp->rgvarg;
186c2c66affSColin Finck         if(V_VT(msg) == (VT_VARIANT|VT_BYREF))
187c2c66affSColin Finck             msg = V_VARIANTREF(msg);
188c2c66affSColin Finck 
189c2c66affSColin Finck         ok(V_VT(msg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(msg));
190c2c66affSColin Finck         ok(V_VT(expr) == VT_BOOL, "V_VT(psp->rgvargs+1) = %d\n", V_VT(expr));
191c2c66affSColin Finck         ok(V_BOOL(expr), "%s: %s\n", script_name, wine_dbgstr_w(V_BSTR(msg)));
192c2c66affSColin Finck         if(pVarResult)
193c2c66affSColin Finck             V_VT(pVarResult) = VT_EMPTY;
194c2c66affSColin Finck         break;
195c2c66affSColin Finck     }
196c2c66affSColin Finck     case DISPID_TESTOBJ_TRACE:
197c2c66affSColin Finck         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
198c2c66affSColin Finck         ok(pdp->cArgs == 1, "cArgs = %d\n", pdp->cArgs);
199c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
200c2c66affSColin Finck         ok(V_VT(pdp->rgvarg) == VT_BSTR, "V_VT(psp->rgvargs) = %d\n", V_VT(pdp->rgvarg));
201c2c66affSColin Finck         trace("%s: %s\n", script_name, wine_dbgstr_w(V_BSTR(pdp->rgvarg)));
202c2c66affSColin Finck         if(pVarResult)
203c2c66affSColin Finck             V_VT(pVarResult) = VT_EMPTY;
204c2c66affSColin Finck         break;
205c2c66affSColin Finck     case DISPID_TESTOBJ_REPORTSUCCESS:
206c2c66affSColin Finck         CHECK_EXPECT(reportSuccess);
207c2c66affSColin Finck 
208c2c66affSColin Finck         ok(wFlags == INVOKE_FUNC, "wFlags = %x\n", wFlags);
209c2c66affSColin Finck         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
210c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
211c2c66affSColin Finck         if(pVarResult)
212c2c66affSColin Finck             V_VT(pVarResult) = VT_EMPTY;
213c2c66affSColin Finck         break;
214c2c66affSColin Finck     case DISPID_TESTOBJ_WSCRIPTFULLNAME:
215c2c66affSColin Finck     {
216c2c66affSColin Finck         WCHAR fullName[MAX_PATH];
217c2c66affSColin Finck         DWORD res;
218c2c66affSColin Finck 
219c2c66affSColin Finck         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
220c2c66affSColin Finck         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
221c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
222c2c66affSColin Finck         V_VT(pVarResult) = VT_BSTR;
223*f2df3bf0SAmine Khaldi         res = GetModuleFileNameExW(wscript_process, NULL, fullName, ARRAY_SIZE(fullName));
224c2c66affSColin Finck         if(res == 0)
225c2c66affSColin Finck             return E_FAIL;
226c2c66affSColin Finck         if(!(V_BSTR(pVarResult) = SysAllocString(fullName)))
227c2c66affSColin Finck             return E_OUTOFMEMORY;
228c2c66affSColin Finck         break;
229c2c66affSColin Finck     }
230c2c66affSColin Finck     case DISPID_TESTOBJ_WSCRIPTPATH:
231c2c66affSColin Finck     {
232c2c66affSColin Finck         WCHAR fullPath[MAX_PATH];
233c2c66affSColin Finck         DWORD res;
234c2c66affSColin Finck         const WCHAR *pos;
235c2c66affSColin Finck 
236c2c66affSColin Finck         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
237c2c66affSColin Finck         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
238c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
239c2c66affSColin Finck         V_VT(pVarResult) = VT_BSTR;
240*f2df3bf0SAmine Khaldi         res = GetModuleFileNameExW(wscript_process, NULL, fullPath, ARRAY_SIZE(fullPath));
241c2c66affSColin Finck         if(res == 0)
242c2c66affSColin Finck             return E_FAIL;
243c2c66affSColin Finck         pos = mystrrchr(fullPath, '\\');
244c2c66affSColin Finck         if(!(V_BSTR(pVarResult) = SysAllocStringLen(fullPath, pos-fullPath)))
245c2c66affSColin Finck             return E_OUTOFMEMORY;
246c2c66affSColin Finck         break;
247c2c66affSColin Finck     }
248c2c66affSColin Finck     case DISPID_TESTOBJ_WSCRIPTSCRIPTNAME:
249c2c66affSColin Finck     {
250c2c66affSColin Finck         char fullPath[MAX_PATH];
251c2c66affSColin Finck         char *pos;
252c2c66affSColin Finck         long res;
253c2c66affSColin Finck 
254c2c66affSColin Finck         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
255c2c66affSColin Finck         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
256c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
257c2c66affSColin Finck         V_VT(pVarResult) = VT_BSTR;
258c2c66affSColin Finck         res = GetFullPathNameA(script_name, sizeof(fullPath), fullPath, &pos);
259c2c66affSColin Finck         if(!res || res > sizeof(fullPath))
260c2c66affSColin Finck             return E_FAIL;
261c2c66affSColin Finck         if(!(V_BSTR(pVarResult) = a2bstr(pos)))
262c2c66affSColin Finck             return E_OUTOFMEMORY;
263c2c66affSColin Finck         break;
264c2c66affSColin Finck     }
265c2c66affSColin Finck     case DISPID_TESTOBJ_WSCRIPTSCRIPTFULLNAME:
266c2c66affSColin Finck     {
267c2c66affSColin Finck         char fullPath[MAX_PATH];
268c2c66affSColin Finck         long res;
269c2c66affSColin Finck 
270c2c66affSColin Finck         ok(wFlags == INVOKE_PROPERTYGET, "wFlags = %x\n", wFlags);
271c2c66affSColin Finck         ok(pdp->cArgs == 0, "cArgs = %d\n", pdp->cArgs);
272c2c66affSColin Finck         ok(!pdp->cNamedArgs, "cNamedArgs = %d\n", pdp->cNamedArgs);
273c2c66affSColin Finck         V_VT(pVarResult) = VT_BSTR;
274c2c66affSColin Finck         res = GetFullPathNameA(script_name, sizeof(fullPath), fullPath, NULL);
275c2c66affSColin Finck         if(!res || res > sizeof(fullPath))
276c2c66affSColin Finck             return E_FAIL;
277c2c66affSColin Finck         if(!(V_BSTR(pVarResult) = a2bstr(fullPath)))
278c2c66affSColin Finck             return E_OUTOFMEMORY;
279c2c66affSColin Finck         break;
280c2c66affSColin Finck     }
281c2c66affSColin Finck     default:
282c2c66affSColin Finck         ok(0, "unexpected dispIdMember %d\n", dispIdMember);
283c2c66affSColin Finck         return E_NOTIMPL;
284c2c66affSColin Finck     }
285c2c66affSColin Finck 
286c2c66affSColin Finck     return S_OK;
287c2c66affSColin Finck }
288c2c66affSColin Finck 
289c2c66affSColin Finck static IDispatchVtbl testobj_vtbl = {
290c2c66affSColin Finck     Dispatch_QueryInterface,
291c2c66affSColin Finck     Dispatch_AddRef,
292c2c66affSColin Finck     Dispatch_Release,
293c2c66affSColin Finck     Dispatch_GetTypeInfoCount,
294c2c66affSColin Finck     Dispatch_GetTypeInfo,
295c2c66affSColin Finck     Dispatch_GetIDsOfNames,
296c2c66affSColin Finck     Dispatch_Invoke
297c2c66affSColin Finck };
298c2c66affSColin Finck 
299c2c66affSColin Finck static IDispatch testobj = { &testobj_vtbl };
300c2c66affSColin Finck 
ClassFactory_QueryInterface(IClassFactory * iface,REFIID riid,void ** ppv)301c2c66affSColin Finck static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
302c2c66affSColin Finck {
303c2c66affSColin Finck     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
304c2c66affSColin Finck         *ppv = iface;
305c2c66affSColin Finck         return S_OK;
306c2c66affSColin Finck     }
307c2c66affSColin Finck 
308c2c66affSColin Finck     *ppv = NULL;
309c2c66affSColin Finck     return E_NOINTERFACE;
310c2c66affSColin Finck }
311c2c66affSColin Finck 
ClassFactory_AddRef(IClassFactory * iface)312c2c66affSColin Finck static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
313c2c66affSColin Finck {
314c2c66affSColin Finck     return 2;
315c2c66affSColin Finck }
316c2c66affSColin Finck 
ClassFactory_Release(IClassFactory * iface)317c2c66affSColin Finck static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
318c2c66affSColin Finck {
319c2c66affSColin Finck     return 1;
320c2c66affSColin Finck }
321c2c66affSColin Finck 
ClassFactory_CreateInstance(IClassFactory * iface,IUnknown * outer,REFIID riid,void ** ppv)322c2c66affSColin Finck static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
323c2c66affSColin Finck {
324c2c66affSColin Finck     ok(!outer, "outer = %p\n", outer);
325c2c66affSColin Finck     return IDispatch_QueryInterface(&testobj, riid, ppv);
326c2c66affSColin Finck }
327c2c66affSColin Finck 
ClassFactory_LockServer(IClassFactory * iface,BOOL dolock)328c2c66affSColin Finck static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
329c2c66affSColin Finck {
330c2c66affSColin Finck     return S_OK;
331c2c66affSColin Finck }
332c2c66affSColin Finck 
333c2c66affSColin Finck static const IClassFactoryVtbl ClassFactoryVtbl = {
334c2c66affSColin Finck     ClassFactory_QueryInterface,
335c2c66affSColin Finck     ClassFactory_AddRef,
336c2c66affSColin Finck     ClassFactory_Release,
337c2c66affSColin Finck     ClassFactory_CreateInstance,
338c2c66affSColin Finck     ClassFactory_LockServer
339c2c66affSColin Finck };
340c2c66affSColin Finck 
341c2c66affSColin Finck static IClassFactory testobj_cf = { &ClassFactoryVtbl };
342c2c66affSColin Finck 
run_script_file(const char * file_name,DWORD expected_exit_code)343c2c66affSColin Finck static void run_script_file(const char *file_name, DWORD expected_exit_code)
344c2c66affSColin Finck {
345c2c66affSColin Finck     char command[MAX_PATH];
346c2c66affSColin Finck     STARTUPINFOA si = {sizeof(si)};
347c2c66affSColin Finck     PROCESS_INFORMATION pi;
348c2c66affSColin Finck     DWORD exit_code;
349c2c66affSColin Finck     BOOL bres;
350c2c66affSColin Finck 
351c2c66affSColin Finck     script_name = file_name;
352c2c66affSColin Finck     sprintf(command, "wscript.exe %s arg1 2 ar3", file_name);
353c2c66affSColin Finck 
354c2c66affSColin Finck     SET_EXPECT(reportSuccess);
355c2c66affSColin Finck 
356c2c66affSColin Finck     bres = CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
357c2c66affSColin Finck     if(!bres) {
358c2c66affSColin Finck         win_skip("script.exe is not available\n");
359c2c66affSColin Finck         CLEAR_CALLED(reportSuccess);
360c2c66affSColin Finck         return;
361c2c66affSColin Finck     }
362c2c66affSColin Finck 
363c2c66affSColin Finck     wscript_process = pi.hProcess;
364c2c66affSColin Finck     WaitForSingleObject(pi.hProcess, INFINITE);
365c2c66affSColin Finck 
366c2c66affSColin Finck     bres = GetExitCodeProcess(pi.hProcess, &exit_code);
367c2c66affSColin Finck     ok(bres, "GetExitCodeProcess failed: %u\n", GetLastError());
368c2c66affSColin Finck     ok(exit_code == expected_exit_code, "exit_code = %u, expected %u\n", exit_code, expected_exit_code);
369c2c66affSColin Finck 
370c2c66affSColin Finck     CloseHandle(pi.hThread);
371c2c66affSColin Finck     CloseHandle(pi.hProcess);
372c2c66affSColin Finck 
373c2c66affSColin Finck     CHECK_CALLED(reportSuccess);
374c2c66affSColin Finck }
375c2c66affSColin Finck 
run_script(const char * name,const char * script_data,size_t script_size,DWORD expected_exit_code)376c2c66affSColin Finck static void run_script(const char *name, const char *script_data, size_t script_size, DWORD expected_exit_code)
377c2c66affSColin Finck {
378c2c66affSColin Finck     char file_name[MAX_PATH];
379c2c66affSColin Finck     const char *ext;
380c2c66affSColin Finck     HANDLE file;
381c2c66affSColin Finck     DWORD size;
382c2c66affSColin Finck     BOOL res;
383c2c66affSColin Finck 
384c2c66affSColin Finck     ext = strrchr(name, '.');
385c2c66affSColin Finck     ok(ext != NULL, "no script extension\n");
386c2c66affSColin Finck     if(!ext)
387c2c66affSColin Finck       return;
388c2c66affSColin Finck 
389c2c66affSColin Finck     sprintf(file_name, "test%s", ext);
390c2c66affSColin Finck 
391c2c66affSColin Finck     file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
392c2c66affSColin Finck             FILE_ATTRIBUTE_NORMAL, NULL);
393c2c66affSColin Finck     ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
394c2c66affSColin Finck     if(file == INVALID_HANDLE_VALUE)
395c2c66affSColin Finck         return;
396c2c66affSColin Finck 
397c2c66affSColin Finck     res = WriteFile(file, script_data, script_size, &size, NULL);
398c2c66affSColin Finck     CloseHandle(file);
399c2c66affSColin Finck     ok(res, "Could not write to file: %u\n", GetLastError());
400c2c66affSColin Finck     if(!res)
401c2c66affSColin Finck         return;
402c2c66affSColin Finck 
403c2c66affSColin Finck     run_script_file(file_name, expected_exit_code);
404c2c66affSColin Finck 
405c2c66affSColin Finck     DeleteFileA(file_name);
406c2c66affSColin Finck }
407c2c66affSColin Finck 
run_simple_script(const char * script,DWORD expected_exit_code)408c2c66affSColin Finck static void run_simple_script(const char *script, DWORD expected_exit_code)
409c2c66affSColin Finck {
410c2c66affSColin Finck     run_script("simple.js", script, strlen(script), expected_exit_code);
411c2c66affSColin Finck }
412c2c66affSColin Finck 
test_enum_proc(HMODULE module,LPCSTR type,LPSTR name,LONG_PTR param)413c2c66affSColin Finck static BOOL WINAPI test_enum_proc(HMODULE module, LPCSTR type, LPSTR name, LONG_PTR param)
414c2c66affSColin Finck {
415c2c66affSColin Finck     const char *script_data;
416c2c66affSColin Finck     DWORD script_size;
417c2c66affSColin Finck     HRSRC src;
418c2c66affSColin Finck 
419c2c66affSColin Finck     trace("running %s test...\n", name);
420c2c66affSColin Finck 
421c2c66affSColin Finck     src = FindResourceA(NULL, name, type);
422c2c66affSColin Finck     ok(src != NULL, "Could not find resource %s: %u\n", name, GetLastError());
423c2c66affSColin Finck     if(!src)
424c2c66affSColin Finck         return TRUE;
425c2c66affSColin Finck 
426c2c66affSColin Finck     script_data = LoadResource(NULL, src);
427c2c66affSColin Finck     script_size = SizeofResource(NULL, src);
428c2c66affSColin Finck     while(script_size && !script_data[script_size-1])
429c2c66affSColin Finck         script_size--;
430c2c66affSColin Finck 
431c2c66affSColin Finck     run_script(name, script_data, script_size, 0);
432c2c66affSColin Finck     return TRUE;
433c2c66affSColin Finck }
434c2c66affSColin Finck 
init_key(const char * key_name,const char * def_value,BOOL init)435c2c66affSColin Finck static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
436c2c66affSColin Finck {
437c2c66affSColin Finck     HKEY hkey;
438c2c66affSColin Finck     DWORD res;
439c2c66affSColin Finck 
440c2c66affSColin Finck     if(!init) {
441c2c66affSColin Finck         RegDeleteKeyA(HKEY_CLASSES_ROOT, key_name);
442c2c66affSColin Finck         return TRUE;
443c2c66affSColin Finck     }
444c2c66affSColin Finck 
445c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
446c2c66affSColin Finck     if(res != ERROR_SUCCESS)
447c2c66affSColin Finck         return FALSE;
448c2c66affSColin Finck 
449c2c66affSColin Finck     if(def_value)
450c2c66affSColin Finck         res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
451c2c66affSColin Finck 
452c2c66affSColin Finck     RegCloseKey(hkey);
453c2c66affSColin Finck     return res == ERROR_SUCCESS;
454c2c66affSColin Finck }
455c2c66affSColin Finck 
init_registry(BOOL init)456c2c66affSColin Finck static BOOL init_registry(BOOL init)
457c2c66affSColin Finck {
458c2c66affSColin Finck     return init_key("Wine.Test\\CLSID", TESTOBJ_CLSID, init);
459c2c66affSColin Finck }
460c2c66affSColin Finck 
register_activex(void)461c2c66affSColin Finck static BOOL register_activex(void)
462c2c66affSColin Finck {
463c2c66affSColin Finck     DWORD regid;
464c2c66affSColin Finck     HRESULT hres;
465c2c66affSColin Finck 
466c2c66affSColin Finck     if(!init_registry(TRUE)) {
467c2c66affSColin Finck         init_registry(FALSE);
468c2c66affSColin Finck         return FALSE;
469c2c66affSColin Finck     }
470c2c66affSColin Finck 
471c2c66affSColin Finck     hres = CoRegisterClassObject(&CLSID_TestObj, (IUnknown *)&testobj_cf,
472c2c66affSColin Finck             CLSCTX_SERVER, REGCLS_MULTIPLEUSE, &regid);
473c2c66affSColin Finck     ok(hres == S_OK, "Could not register script engine: %08x\n", hres);
474c2c66affSColin Finck     return TRUE;
475c2c66affSColin Finck }
476c2c66affSColin Finck 
START_TEST(run)477c2c66affSColin Finck START_TEST(run)
478c2c66affSColin Finck {
479c2c66affSColin Finck     char **argv;
480c2c66affSColin Finck     int argc;
481c2c66affSColin Finck 
482c2c66affSColin Finck     CoInitializeEx(NULL, COINIT_MULTITHREADED);
483c2c66affSColin Finck 
484c2c66affSColin Finck     if(!register_activex()) {
485c2c66affSColin Finck         skip("Could not register ActiveX object.\n");
486c2c66affSColin Finck         CoUninitialize();
487c2c66affSColin Finck         return;
488c2c66affSColin Finck     }
489c2c66affSColin Finck 
490c2c66affSColin Finck     argc = winetest_get_mainargs(&argv);
491c2c66affSColin Finck     if(argc > 2) {
492c2c66affSColin Finck         run_script_file(argv[2], 0);
493c2c66affSColin Finck     }else {
494c2c66affSColin Finck         EnumResourceNamesA(NULL, "TESTSCRIPT", test_enum_proc, 0);
495c2c66affSColin Finck 
496c2c66affSColin Finck         run_simple_script("var winetest = new ActiveXObject('Wine.Test');\n"
497c2c66affSColin Finck                            "winetest.reportSuccess();\n"
498c2c66affSColin Finck                            "WScript.Quit(3);\n"
499c2c66affSColin Finck                            "winetest.ok(false, 'not quit?');\n", 3);
500c2c66affSColin Finck }
501c2c66affSColin Finck 
502c2c66affSColin Finck     init_registry(FALSE);
503c2c66affSColin Finck     CoUninitialize();
504c2c66affSColin Finck }
505