gdi32/uniscribe: Ensure the cache is initialised.
[wine.git] / dlls / jsproxy / main.c
blob9506b7153cfabf50e09ab702ee760686428418cf
1 /*
2 * Copyright 2014 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include <stdarg.h>
20 #include <sys/types.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "winsock2.h"
25 #include "ws2ipdef.h"
26 #include "ws2tcpip.h"
27 #include "winnls.h"
28 #include "wininet.h"
29 #define COBJMACROS
30 #include "ole2.h"
31 #include "dispex.h"
32 #include "activscp.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(jsproxy);
37 static CRITICAL_SECTION cs_jsproxy;
38 static CRITICAL_SECTION_DEBUG critsect_debug =
40 0, 0, &cs_jsproxy,
41 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
42 0, 0, { (DWORD_PTR)(__FILE__ ": cs_jsproxy") }
44 static CRITICAL_SECTION cs_jsproxy = { &critsect_debug, -1, 0, 0, 0, 0 };
46 static inline WCHAR *strdupAW( const char *src, int len )
48 WCHAR *dst = NULL;
49 if (src)
51 int dst_len = MultiByteToWideChar( CP_ACP, 0, src, len, NULL, 0 );
52 if ((dst = malloc( (dst_len + 1) * sizeof(WCHAR) )))
54 len = MultiByteToWideChar( CP_ACP, 0, src, len, dst, dst_len );
55 dst[dst_len] = 0;
58 return dst;
61 static inline char *strdupWA( const WCHAR *src )
63 char *dst = NULL;
64 if (src)
66 int len = WideCharToMultiByte( CP_ACP, 0, src, -1, NULL, 0, NULL, NULL );
67 if ((dst = malloc( len ))) WideCharToMultiByte( CP_ACP, 0, src, -1, dst, len, NULL, NULL );
69 return dst;
72 static struct pac_script
74 WCHAR *text;
75 } pac_script;
76 static struct pac_script *global_script = &pac_script;
78 /******************************************************************
79 * InternetDeInitializeAutoProxyDll (jsproxy.@)
81 BOOL WINAPI InternetDeInitializeAutoProxyDll( LPSTR mime, DWORD reserved )
83 TRACE( "%s, %lu\n", debugstr_a(mime), reserved );
85 EnterCriticalSection( &cs_jsproxy );
87 free( global_script->text );
88 global_script->text = NULL;
90 LeaveCriticalSection( &cs_jsproxy );
91 return TRUE;
94 static WCHAR *load_script( const char *filename )
96 HANDLE handle;
97 DWORD size, bytes_read;
98 char *buffer;
99 int len;
100 WCHAR *script = NULL;
102 handle = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
103 if (handle == INVALID_HANDLE_VALUE) return NULL;
105 size = GetFileSize( handle, NULL );
106 if (!(buffer = malloc( size ))) goto done;
107 if (!ReadFile( handle, buffer, size, &bytes_read, NULL ) || bytes_read != size) goto done;
109 len = MultiByteToWideChar( CP_ACP, 0, buffer, size, NULL, 0 );
110 if (!(script = malloc( (len + 1) * sizeof(WCHAR) ))) goto done;
111 MultiByteToWideChar( CP_ACP, 0, buffer, size, script, len );
112 script[len] = 0;
114 done:
115 CloseHandle( handle );
116 free( buffer );
117 return script;
120 /******************************************************************
121 * InternetInitializeAutoProxyDll (jsproxy.@)
123 BOOL WINAPI JSPROXY_InternetInitializeAutoProxyDll( DWORD version, LPSTR tmpfile, LPSTR mime,
124 AutoProxyHelperFunctions *callbacks,
125 LPAUTO_PROXY_SCRIPT_BUFFER buffer )
127 BOOL ret = FALSE;
129 TRACE( "%lu, %s, %s, %p, %p\n", version, debugstr_a(tmpfile), debugstr_a(mime), callbacks, buffer );
131 if (callbacks) FIXME( "callbacks not supported\n" );
133 EnterCriticalSection( &cs_jsproxy );
135 if (buffer && buffer->dwStructSize == sizeof(*buffer) && buffer->lpszScriptBuffer)
137 if (!buffer->dwScriptBufferSize)
139 SetLastError( ERROR_INVALID_PARAMETER );
140 LeaveCriticalSection( &cs_jsproxy );
141 return FALSE;
143 free( global_script->text );
144 if ((global_script->text = strdupAW( buffer->lpszScriptBuffer,
145 buffer->dwScriptBufferSize ))) ret = TRUE;
147 else
149 free( global_script->text );
150 if ((global_script->text = load_script( tmpfile ))) ret = TRUE;
153 LeaveCriticalSection( &cs_jsproxy );
154 return ret;
157 static HRESULT WINAPI dispex_QueryInterface(
158 IDispatchEx *iface, REFIID riid, void **ppv )
160 *ppv = NULL;
162 if (IsEqualGUID( riid, &IID_IUnknown ) ||
163 IsEqualGUID( riid, &IID_IDispatch ) ||
164 IsEqualGUID( riid, &IID_IDispatchEx ))
165 *ppv = iface;
166 else
167 return E_NOINTERFACE;
169 return S_OK;
172 static ULONG WINAPI dispex_AddRef(
173 IDispatchEx *iface )
175 return 2;
178 static ULONG WINAPI dispex_Release(
179 IDispatchEx *iface )
181 return 1;
184 static HRESULT WINAPI dispex_GetTypeInfoCount(
185 IDispatchEx *iface, UINT *info )
187 return E_NOTIMPL;
190 static HRESULT WINAPI dispex_GetTypeInfo(
191 IDispatchEx *iface, UINT info, LCID lcid, ITypeInfo **type_info )
193 return E_NOTIMPL;
196 static HRESULT WINAPI dispex_GetIDsOfNames(
197 IDispatchEx *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *id )
199 return E_NOTIMPL;
202 static HRESULT WINAPI dispex_Invoke(
203 IDispatchEx *iface, DISPID member, REFIID riid, LCID lcid, WORD flags,
204 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excep, UINT *err )
206 return E_NOTIMPL;
209 static HRESULT WINAPI dispex_DeleteMemberByName(
210 IDispatchEx *iface, BSTR name, DWORD flags )
212 return E_NOTIMPL;
215 static HRESULT WINAPI dispex_DeleteMemberByDispID(
216 IDispatchEx *iface, DISPID id )
218 return E_NOTIMPL;
221 static HRESULT WINAPI dispex_GetMemberProperties(
222 IDispatchEx *iface, DISPID id, DWORD flags_fetch, DWORD *flags )
224 return E_NOTIMPL;
227 static HRESULT WINAPI dispex_GetMemberName(
228 IDispatchEx *iface, DISPID id, BSTR *name )
230 return E_NOTIMPL;
233 static HRESULT WINAPI dispex_GetNextDispID(
234 IDispatchEx *iface, DWORD flags, DISPID id, DISPID *next )
236 return E_NOTIMPL;
239 static HRESULT WINAPI dispex_GetNameSpaceParent(
240 IDispatchEx *iface, IUnknown **unk )
242 return E_NOTIMPL;
245 #define DISPID_GLOBAL_DNSRESOLVE 0x1000
247 static HRESULT WINAPI dispex_GetDispID(
248 IDispatchEx *iface, BSTR name, DWORD flags, DISPID *id )
250 if (!lstrcmpW( name, L"dns_resolve" ))
252 *id = DISPID_GLOBAL_DNSRESOLVE;
253 return S_OK;
255 return DISP_E_UNKNOWNNAME;
258 static char *get_computer_name( COMPUTER_NAME_FORMAT format )
260 char *ret;
261 DWORD size = 0;
263 GetComputerNameExA( format, NULL, &size );
264 if (GetLastError() != ERROR_MORE_DATA) return NULL;
265 if (!(ret = malloc( size ))) return NULL;
266 if (!GetComputerNameExA( format, ret, &size ))
268 free( ret );
269 return NULL;
271 return ret;
274 static void printf_addr( const WCHAR *fmt, WCHAR *buf, SIZE_T size, struct sockaddr_in *addr )
276 swprintf( buf, size, fmt,
277 (unsigned int)(ntohl( addr->sin_addr.s_addr ) >> 24 & 0xff),
278 (unsigned int)(ntohl( addr->sin_addr.s_addr ) >> 16 & 0xff),
279 (unsigned int)(ntohl( addr->sin_addr.s_addr ) >> 8 & 0xff),
280 (unsigned int)(ntohl( addr->sin_addr.s_addr ) & 0xff) );
283 static HRESULT dns_resolve( const WCHAR *hostname, VARIANT *result )
285 WCHAR addr[16];
286 struct addrinfo *ai, *elem;
287 char *hostnameA;
288 int res;
290 if (hostname[0])
291 hostnameA = strdupWA( hostname );
292 else
293 hostnameA = get_computer_name( ComputerNamePhysicalDnsFullyQualified );
295 if (!hostnameA) return E_OUTOFMEMORY;
296 res = getaddrinfo( hostnameA, NULL, NULL, &ai );
297 free( hostnameA );
298 if (res) return S_FALSE;
300 elem = ai;
301 while (elem && elem->ai_family != AF_INET) elem = elem->ai_next;
302 if (!elem)
304 freeaddrinfo( ai );
305 return S_FALSE;
307 printf_addr( L"%u.%u.%u.%u", addr, ARRAY_SIZE(addr), (struct sockaddr_in *)elem->ai_addr );
308 freeaddrinfo( ai );
309 V_VT( result ) = VT_BSTR;
310 V_BSTR( result ) = SysAllocString( addr );
311 return S_OK;
314 static HRESULT WINAPI dispex_InvokeEx(
315 IDispatchEx *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
316 VARIANT *result, EXCEPINFO *exep, IServiceProvider *caller )
318 if (id == DISPID_GLOBAL_DNSRESOLVE)
320 if (params->cArgs != 1) return DISP_E_BADPARAMCOUNT;
321 if (V_VT(&params->rgvarg[0]) != VT_BSTR) return DISP_E_BADVARTYPE;
322 return dns_resolve( V_BSTR(&params->rgvarg[0]), result );
324 return DISP_E_MEMBERNOTFOUND;
327 static const IDispatchExVtbl dispex_vtbl =
329 dispex_QueryInterface,
330 dispex_AddRef,
331 dispex_Release,
332 dispex_GetTypeInfoCount,
333 dispex_GetTypeInfo,
334 dispex_GetIDsOfNames,
335 dispex_Invoke,
336 dispex_GetDispID,
337 dispex_InvokeEx,
338 dispex_DeleteMemberByName,
339 dispex_DeleteMemberByDispID,
340 dispex_GetMemberProperties,
341 dispex_GetMemberName,
342 dispex_GetNextDispID,
343 dispex_GetNameSpaceParent
346 static IDispatchEx global_dispex = { &dispex_vtbl };
348 static HRESULT WINAPI site_QueryInterface(
349 IActiveScriptSite *iface, REFIID riid, void **ppv )
351 *ppv = NULL;
353 if (IsEqualGUID( &IID_IUnknown, riid ))
354 *ppv = iface;
355 else if (IsEqualGUID( &IID_IActiveScriptSite, riid ))
356 *ppv = iface;
357 else
358 return E_NOINTERFACE;
360 IUnknown_AddRef( (IUnknown *)*ppv );
361 return S_OK;
364 static ULONG WINAPI site_AddRef(
365 IActiveScriptSite *iface )
367 return 2;
370 static ULONG WINAPI site_Release(
371 IActiveScriptSite *iface )
373 return 1;
376 static HRESULT WINAPI site_GetLCID(
377 IActiveScriptSite *iface, LCID *lcid )
379 return E_NOTIMPL;
382 static HRESULT WINAPI site_GetItemInfo(
383 IActiveScriptSite *iface, LPCOLESTR name, DWORD mask,
384 IUnknown **item, ITypeInfo **type_info )
386 if (!lstrcmpW( name, L"global_funcs" ) && mask == SCRIPTINFO_IUNKNOWN)
388 *item = (IUnknown *)&global_dispex;
389 return S_OK;
391 return E_NOTIMPL;
394 static HRESULT WINAPI site_GetDocVersionString(
395 IActiveScriptSite *iface, BSTR *version )
397 return E_NOTIMPL;
400 static HRESULT WINAPI site_OnScriptTerminate(
401 IActiveScriptSite *iface, const VARIANT *result, const EXCEPINFO *info )
403 return E_NOTIMPL;
406 static HRESULT WINAPI site_OnStateChange(
407 IActiveScriptSite *iface, SCRIPTSTATE state )
409 return E_NOTIMPL;
412 static HRESULT WINAPI site_OnScriptError(
413 IActiveScriptSite *iface, IActiveScriptError *error )
415 return E_NOTIMPL;
418 static HRESULT WINAPI site_OnEnterScript(
419 IActiveScriptSite *iface )
421 return E_NOTIMPL;
424 static HRESULT WINAPI site_OnLeaveScript(
425 IActiveScriptSite *iface )
427 return E_NOTIMPL;
430 static const IActiveScriptSiteVtbl site_vtbl =
432 site_QueryInterface,
433 site_AddRef,
434 site_Release,
435 site_GetLCID,
436 site_GetItemInfo,
437 site_GetDocVersionString,
438 site_OnScriptTerminate,
439 site_OnStateChange,
440 site_OnScriptError,
441 site_OnEnterScript,
442 site_OnLeaveScript
445 static IActiveScriptSite script_site = { &site_vtbl };
447 static BSTR include_pac_utils( const WCHAR *script )
449 HMODULE hmod = GetModuleHandleA( "jsproxy.dll" );
450 HRSRC rsrc;
451 DWORD size;
452 const char *data;
453 BSTR ret;
454 int len;
456 if (!(rsrc = FindResourceW( hmod, L"pac.js", (LPCWSTR)40 ))) return NULL;
457 size = SizeofResource( hmod, rsrc );
458 data = LoadResource( hmod, rsrc );
460 len = MultiByteToWideChar( CP_ACP, 0, data, size, NULL, 0 );
461 if (!(ret = SysAllocStringLen( NULL, len + lstrlenW( script ) + 1 ))) return NULL;
462 MultiByteToWideChar( CP_ACP, 0, data, size, ret, len );
463 lstrcpyW( ret + len, script );
464 return ret;
467 #ifdef _WIN64
468 #define IActiveScriptParse_Release IActiveScriptParse64_Release
469 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
470 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
471 #else
472 #define IActiveScriptParse_Release IActiveScriptParse32_Release
473 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
474 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
475 #endif
477 static BOOL run_script( const WCHAR *script, const WCHAR *url, const WCHAR *hostname, char **result_str, DWORD *result_len )
479 IActiveScriptParse *parser = NULL;
480 IActiveScript *engine = NULL;
481 IDispatch *dispatch = NULL;
482 BOOL ret = FALSE;
483 CLSID clsid;
484 DISPID dispid;
485 BSTR func = NULL, full_script = NULL;
486 VARIANT args[2], retval;
487 DISPPARAMS params;
488 HRESULT hr, init;
490 init = CoInitialize( NULL );
491 hr = CLSIDFromProgID( L"JScript", &clsid );
492 if (hr != S_OK) goto done;
494 hr = CoCreateInstance( &clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
495 &IID_IActiveScript, (void **)&engine );
496 if (hr != S_OK) goto done;
498 hr = IActiveScript_QueryInterface( engine, &IID_IActiveScriptParse, (void **)&parser );
499 if (hr != S_OK) goto done;
501 hr = IActiveScriptParse_InitNew( parser );
502 if (hr != S_OK) goto done;
504 hr = IActiveScript_SetScriptSite( engine, &script_site );
505 if (hr != S_OK) goto done;
507 hr = IActiveScript_AddNamedItem( engine, L"global_funcs", SCRIPTITEM_GLOBALMEMBERS );
508 if (hr != S_OK) goto done;
510 if (!(full_script = include_pac_utils( script ))) goto done;
512 hr = IActiveScriptParse_ParseScriptText( parser, full_script, NULL, NULL, NULL, 0, 0, 0, NULL, NULL );
513 if (hr != S_OK) goto done;
515 hr = IActiveScript_SetScriptState( engine, SCRIPTSTATE_STARTED );
516 if (hr != S_OK) goto done;
518 hr = IActiveScript_GetScriptDispatch( engine, NULL, &dispatch );
519 if (hr != S_OK) goto done;
521 if (!(func = SysAllocString( L"FindProxyForURL" ))) goto done;
522 hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &func, 1, LOCALE_SYSTEM_DEFAULT, &dispid );
523 if (hr != S_OK) goto done;
525 V_VT( &args[0] ) = VT_BSTR;
526 V_BSTR( &args[0] ) = SysAllocString( hostname );
527 V_VT( &args[1] ) = VT_BSTR;
528 V_BSTR( &args[1] ) = SysAllocString( url );
530 params.rgvarg = args;
531 params.rgdispidNamedArgs = NULL;
532 params.cArgs = 2;
533 params.cNamedArgs = 0;
534 hr = IDispatch_Invoke( dispatch, dispid, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
535 &params, &retval, NULL, NULL );
536 VariantClear( &args[0] );
537 VariantClear( &args[1] );
538 if (hr != S_OK)
540 WARN("script failed 0x%08lx\n", hr);
541 goto done;
543 if ((*result_str = strdupWA( V_BSTR( &retval ) )))
545 TRACE( "result: %s\n", debugstr_a(*result_str) );
546 *result_len = strlen( *result_str ) + 1;
547 ret = TRUE;
549 VariantClear( &retval );
551 done:
552 SysFreeString( full_script );
553 SysFreeString( func );
554 if (dispatch) IDispatch_Release( dispatch );
555 if (parser) IActiveScriptParse_Release( parser );
556 if (engine) IActiveScript_Release( engine );
557 if (SUCCEEDED( init )) CoUninitialize();
558 return ret;
561 /******************************************************************
562 * InternetGetProxyInfo (jsproxy.@)
564 BOOL WINAPI InternetGetProxyInfo( LPCSTR url, DWORD len_url, LPCSTR hostname, DWORD len_hostname, LPSTR *proxy,
565 LPDWORD len_proxy )
567 WCHAR *urlW = NULL, *hostnameW = NULL;
568 BOOL ret = FALSE;
570 TRACE( "%s, %lu, %s, %lu, %p, %p\n", debugstr_a(url), len_url, hostname, len_hostname, proxy, len_proxy );
572 EnterCriticalSection( &cs_jsproxy );
574 if (!global_script->text)
576 SetLastError( ERROR_CAN_NOT_COMPLETE );
577 goto done;
579 if (!(urlW = strdupAW( url, len_url ))) goto done;
580 if (hostname && !(hostnameW = strdupAW( hostname, len_hostname ))) goto done;
582 TRACE( "%s\n", debugstr_w(global_script->text) );
583 ret = run_script( global_script->text, urlW, hostnameW, proxy, len_proxy );
585 done:
586 free( hostnameW );
587 free( urlW );
588 LeaveCriticalSection( &cs_jsproxy );
589 return ret;