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
20 #include <sys/types.h>
33 #include "wine/debug.h"
34 #include "wine/heap.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(jsproxy
);
38 static CRITICAL_SECTION cs_jsproxy
;
39 static CRITICAL_SECTION_DEBUG critsect_debug
=
42 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
43 0, 0, { (DWORD_PTR
)(__FILE__
": cs_jsproxy") }
45 static CRITICAL_SECTION cs_jsproxy
= { &critsect_debug
, -1, 0, 0, 0, 0 };
47 static inline WCHAR
*strdupAW( const char *src
, int len
)
52 int dst_len
= MultiByteToWideChar( CP_ACP
, 0, src
, len
, NULL
, 0 );
53 if ((dst
= heap_alloc( (dst_len
+ 1) * sizeof(WCHAR
) )))
55 len
= MultiByteToWideChar( CP_ACP
, 0, src
, len
, dst
, dst_len
);
62 static inline char *strdupWA( const WCHAR
*src
)
67 int len
= WideCharToMultiByte( CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
68 if ((dst
= heap_alloc( len
))) WideCharToMultiByte( CP_ACP
, 0, src
, -1, dst
, len
, NULL
, NULL
);
73 static struct pac_script
77 static struct pac_script
*global_script
= &pac_script
;
79 /******************************************************************
80 * InternetDeInitializeAutoProxyDll (jsproxy.@)
82 BOOL WINAPI
InternetDeInitializeAutoProxyDll( LPSTR mime
, DWORD reserved
)
84 TRACE( "%s, %u\n", debugstr_a(mime
), reserved
);
86 EnterCriticalSection( &cs_jsproxy
);
88 heap_free( global_script
->text
);
89 global_script
->text
= NULL
;
91 LeaveCriticalSection( &cs_jsproxy
);
95 static WCHAR
*load_script( const char *filename
)
98 DWORD size
, bytes_read
;
101 WCHAR
*script
= NULL
;
103 handle
= CreateFileA( filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
104 if (handle
== INVALID_HANDLE_VALUE
) return NULL
;
106 size
= GetFileSize( handle
, NULL
);
107 if (!(buffer
= heap_alloc( size
))) goto done
;
108 if (!ReadFile( handle
, buffer
, size
, &bytes_read
, NULL
) || bytes_read
!= size
) goto done
;
110 len
= MultiByteToWideChar( CP_ACP
, 0, buffer
, size
, NULL
, 0 );
111 if (!(script
= heap_alloc( (len
+ 1) * sizeof(WCHAR
) ))) goto done
;
112 MultiByteToWideChar( CP_ACP
, 0, buffer
, size
, script
, len
);
116 CloseHandle( handle
);
121 /******************************************************************
122 * InternetInitializeAutoProxyDll (jsproxy.@)
124 BOOL WINAPI
JSPROXY_InternetInitializeAutoProxyDll( DWORD version
, LPSTR tmpfile
, LPSTR mime
,
125 AutoProxyHelperFunctions
*callbacks
,
126 LPAUTO_PROXY_SCRIPT_BUFFER buffer
)
130 TRACE( "%u, %s, %s, %p, %p\n", version
, debugstr_a(tmpfile
), debugstr_a(mime
), callbacks
, buffer
);
132 if (callbacks
) FIXME( "callbacks not supported\n" );
134 EnterCriticalSection( &cs_jsproxy
);
136 if (buffer
&& buffer
->dwStructSize
== sizeof(*buffer
) && buffer
->lpszScriptBuffer
)
138 if (!buffer
->dwScriptBufferSize
)
140 SetLastError( ERROR_INVALID_PARAMETER
);
141 LeaveCriticalSection( &cs_jsproxy
);
144 heap_free( global_script
->text
);
145 if ((global_script
->text
= strdupAW( buffer
->lpszScriptBuffer
,
146 buffer
->dwScriptBufferSize
))) ret
= TRUE
;
150 heap_free( global_script
->text
);
151 if ((global_script
->text
= load_script( tmpfile
))) ret
= TRUE
;
154 LeaveCriticalSection( &cs_jsproxy
);
158 static HRESULT WINAPI
dispex_QueryInterface(
159 IDispatchEx
*iface
, REFIID riid
, void **ppv
)
163 if (IsEqualGUID( riid
, &IID_IUnknown
) ||
164 IsEqualGUID( riid
, &IID_IDispatch
) ||
165 IsEqualGUID( riid
, &IID_IDispatchEx
))
168 return E_NOINTERFACE
;
173 static ULONG WINAPI
dispex_AddRef(
179 static ULONG WINAPI
dispex_Release(
185 static HRESULT WINAPI
dispex_GetTypeInfoCount(
186 IDispatchEx
*iface
, UINT
*info
)
191 static HRESULT WINAPI
dispex_GetTypeInfo(
192 IDispatchEx
*iface
, UINT info
, LCID lcid
, ITypeInfo
**type_info
)
197 static HRESULT WINAPI
dispex_GetIDsOfNames(
198 IDispatchEx
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*id
)
203 static HRESULT WINAPI
dispex_Invoke(
204 IDispatchEx
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
205 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep
, UINT
*err
)
210 static HRESULT WINAPI
dispex_DeleteMemberByName(
211 IDispatchEx
*iface
, BSTR name
, DWORD flags
)
216 static HRESULT WINAPI
dispex_DeleteMemberByDispID(
217 IDispatchEx
*iface
, DISPID id
)
222 static HRESULT WINAPI
dispex_GetMemberProperties(
223 IDispatchEx
*iface
, DISPID id
, DWORD flags_fetch
, DWORD
*flags
)
228 static HRESULT WINAPI
dispex_GetMemberName(
229 IDispatchEx
*iface
, DISPID id
, BSTR
*name
)
234 static HRESULT WINAPI
dispex_GetNextDispID(
235 IDispatchEx
*iface
, DWORD flags
, DISPID id
, DISPID
*next
)
240 static HRESULT WINAPI
dispex_GetNameSpaceParent(
241 IDispatchEx
*iface
, IUnknown
**unk
)
246 #define DISPID_GLOBAL_DNSRESOLVE 0x1000
248 static HRESULT WINAPI
dispex_GetDispID(
249 IDispatchEx
*iface
, BSTR name
, DWORD flags
, DISPID
*id
)
251 if (!lstrcmpW( name
, L
"dns_resolve" ))
253 *id
= DISPID_GLOBAL_DNSRESOLVE
;
256 return DISP_E_UNKNOWNNAME
;
259 static char *get_computer_name( COMPUTER_NAME_FORMAT format
)
264 GetComputerNameExA( format
, NULL
, &size
);
265 if (GetLastError() != ERROR_MORE_DATA
) return NULL
;
266 if (!(ret
= heap_alloc( size
))) return NULL
;
267 if (!GetComputerNameExA( format
, ret
, &size
))
275 static void printf_addr( const WCHAR
*fmt
, WCHAR
*buf
, SIZE_T size
, struct sockaddr_in
*addr
)
277 swprintf( buf
, size
, fmt
,
278 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 24 & 0xff),
279 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 16 & 0xff),
280 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 8 & 0xff),
281 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) & 0xff) );
284 static HRESULT
dns_resolve( const WCHAR
*hostname
, VARIANT
*result
)
287 struct addrinfo
*ai
, *elem
;
292 hostnameA
= strdupWA( hostname
);
294 hostnameA
= get_computer_name( ComputerNamePhysicalDnsFullyQualified
);
296 if (!hostnameA
) return E_OUTOFMEMORY
;
297 res
= getaddrinfo( hostnameA
, NULL
, NULL
, &ai
);
298 heap_free( hostnameA
);
299 if (res
) return S_FALSE
;
302 while (elem
&& elem
->ai_family
!= AF_INET
) elem
= elem
->ai_next
;
308 printf_addr( L
"%u.%u.%u.%u", addr
, ARRAY_SIZE(addr
), (struct sockaddr_in
*)elem
->ai_addr
);
310 V_VT( result
) = VT_BSTR
;
311 V_BSTR( result
) = SysAllocString( addr
);
315 static HRESULT WINAPI
dispex_InvokeEx(
316 IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
317 VARIANT
*result
, EXCEPINFO
*exep
, IServiceProvider
*caller
)
319 if (id
== DISPID_GLOBAL_DNSRESOLVE
)
321 if (params
->cArgs
!= 1) return DISP_E_BADPARAMCOUNT
;
322 if (V_VT(¶ms
->rgvarg
[0]) != VT_BSTR
) return DISP_E_BADVARTYPE
;
323 return dns_resolve( V_BSTR(¶ms
->rgvarg
[0]), result
);
325 return DISP_E_MEMBERNOTFOUND
;
328 static const IDispatchExVtbl dispex_vtbl
=
330 dispex_QueryInterface
,
333 dispex_GetTypeInfoCount
,
335 dispex_GetIDsOfNames
,
339 dispex_DeleteMemberByName
,
340 dispex_DeleteMemberByDispID
,
341 dispex_GetMemberProperties
,
342 dispex_GetMemberName
,
343 dispex_GetNextDispID
,
344 dispex_GetNameSpaceParent
347 static IDispatchEx global_dispex
= { &dispex_vtbl
};
349 static HRESULT WINAPI
site_QueryInterface(
350 IActiveScriptSite
*iface
, REFIID riid
, void **ppv
)
354 if (IsEqualGUID( &IID_IUnknown
, riid
))
356 else if (IsEqualGUID( &IID_IActiveScriptSite
, riid
))
359 return E_NOINTERFACE
;
361 IUnknown_AddRef( (IUnknown
*)*ppv
);
365 static ULONG WINAPI
site_AddRef(
366 IActiveScriptSite
*iface
)
371 static ULONG WINAPI
site_Release(
372 IActiveScriptSite
*iface
)
377 static HRESULT WINAPI
site_GetLCID(
378 IActiveScriptSite
*iface
, LCID
*lcid
)
383 static HRESULT WINAPI
site_GetItemInfo(
384 IActiveScriptSite
*iface
, LPCOLESTR name
, DWORD mask
,
385 IUnknown
**item
, ITypeInfo
**type_info
)
387 if (!lstrcmpW( name
, L
"global_funcs" ) && mask
== SCRIPTINFO_IUNKNOWN
)
389 *item
= (IUnknown
*)&global_dispex
;
395 static HRESULT WINAPI
site_GetDocVersionString(
396 IActiveScriptSite
*iface
, BSTR
*version
)
401 static HRESULT WINAPI
site_OnScriptTerminate(
402 IActiveScriptSite
*iface
, const VARIANT
*result
, const EXCEPINFO
*info
)
407 static HRESULT WINAPI
site_OnStateChange(
408 IActiveScriptSite
*iface
, SCRIPTSTATE state
)
413 static HRESULT WINAPI
site_OnScriptError(
414 IActiveScriptSite
*iface
, IActiveScriptError
*error
)
419 static HRESULT WINAPI
site_OnEnterScript(
420 IActiveScriptSite
*iface
)
425 static HRESULT WINAPI
site_OnLeaveScript(
426 IActiveScriptSite
*iface
)
431 static const IActiveScriptSiteVtbl site_vtbl
=
438 site_GetDocVersionString
,
439 site_OnScriptTerminate
,
446 static IActiveScriptSite script_site
= { &site_vtbl
};
448 static BSTR
include_pac_utils( const WCHAR
*script
)
450 HMODULE hmod
= GetModuleHandleA( "jsproxy.dll" );
457 if (!(rsrc
= FindResourceW( hmod
, L
"pac.js", (LPCWSTR
)40 ))) return NULL
;
458 size
= SizeofResource( hmod
, rsrc
);
459 data
= LoadResource( hmod
, rsrc
);
461 len
= MultiByteToWideChar( CP_ACP
, 0, data
, size
, NULL
, 0 );
462 if (!(ret
= SysAllocStringLen( NULL
, len
+ lstrlenW( script
) + 1 ))) return NULL
;
463 MultiByteToWideChar( CP_ACP
, 0, data
, size
, ret
, len
);
464 lstrcpyW( ret
+ len
, script
);
469 #define IActiveScriptParse_Release IActiveScriptParse64_Release
470 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
471 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
473 #define IActiveScriptParse_Release IActiveScriptParse32_Release
474 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
475 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
478 static BOOL
run_script( const WCHAR
*script
, const WCHAR
*url
, const WCHAR
*hostname
, char **result_str
, DWORD
*result_len
)
480 IActiveScriptParse
*parser
= NULL
;
481 IActiveScript
*engine
= NULL
;
482 IDispatch
*dispatch
= NULL
;
486 BSTR func
= NULL
, full_script
= NULL
;
487 VARIANT args
[2], retval
;
491 init
= CoInitialize( NULL
);
492 hr
= CLSIDFromProgID( L
"JScript", &clsid
);
493 if (hr
!= S_OK
) goto done
;
495 hr
= CoCreateInstance( &clsid
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
496 &IID_IActiveScript
, (void **)&engine
);
497 if (hr
!= S_OK
) goto done
;
499 hr
= IActiveScript_QueryInterface( engine
, &IID_IActiveScriptParse
, (void **)&parser
);
500 if (hr
!= S_OK
) goto done
;
502 hr
= IActiveScriptParse_InitNew( parser
);
503 if (hr
!= S_OK
) goto done
;
505 hr
= IActiveScript_SetScriptSite( engine
, &script_site
);
506 if (hr
!= S_OK
) goto done
;
508 hr
= IActiveScript_AddNamedItem( engine
, L
"global_funcs", SCRIPTITEM_GLOBALMEMBERS
);
509 if (hr
!= S_OK
) goto done
;
511 if (!(full_script
= include_pac_utils( script
))) goto done
;
513 hr
= IActiveScriptParse_ParseScriptText( parser
, full_script
, NULL
, NULL
, NULL
, 0, 0, 0, NULL
, NULL
);
514 if (hr
!= S_OK
) goto done
;
516 hr
= IActiveScript_SetScriptState( engine
, SCRIPTSTATE_STARTED
);
517 if (hr
!= S_OK
) goto done
;
519 hr
= IActiveScript_GetScriptDispatch( engine
, NULL
, &dispatch
);
520 if (hr
!= S_OK
) goto done
;
522 if (!(func
= SysAllocString( L
"FindProxyForURL" ))) goto done
;
523 hr
= IDispatch_GetIDsOfNames( dispatch
, &IID_NULL
, &func
, 1, LOCALE_SYSTEM_DEFAULT
, &dispid
);
524 if (hr
!= S_OK
) goto done
;
526 V_VT( &args
[0] ) = VT_BSTR
;
527 V_BSTR( &args
[0] ) = SysAllocString( hostname
);
528 V_VT( &args
[1] ) = VT_BSTR
;
529 V_BSTR( &args
[1] ) = SysAllocString( url
);
531 params
.rgvarg
= args
;
532 params
.rgdispidNamedArgs
= NULL
;
534 params
.cNamedArgs
= 0;
535 hr
= IDispatch_Invoke( dispatch
, dispid
, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
,
536 ¶ms
, &retval
, NULL
, NULL
);
537 VariantClear( &args
[0] );
538 VariantClear( &args
[1] );
541 WARN("script failed 0x%08x\n", hr
);
544 if ((*result_str
= strdupWA( V_BSTR( &retval
) )))
546 TRACE( "result: %s\n", debugstr_a(*result_str
) );
547 *result_len
= strlen( *result_str
) + 1;
550 VariantClear( &retval
);
553 SysFreeString( full_script
);
554 SysFreeString( func
);
555 if (dispatch
) IDispatch_Release( dispatch
);
556 if (parser
) IActiveScriptParse_Release( parser
);
557 if (engine
) IActiveScript_Release( engine
);
558 if (SUCCEEDED( init
)) CoUninitialize();
562 /******************************************************************
563 * InternetGetProxyInfo (jsproxy.@)
565 BOOL WINAPI
InternetGetProxyInfo( LPCSTR url
, DWORD len_url
, LPCSTR hostname
, DWORD len_hostname
, LPSTR
*proxy
,
568 WCHAR
*urlW
= NULL
, *hostnameW
= NULL
;
571 TRACE( "%s, %u, %s, %u, %p, %p\n", debugstr_a(url
), len_url
, hostname
, len_hostname
, proxy
, len_proxy
);
573 EnterCriticalSection( &cs_jsproxy
);
575 if (!global_script
->text
)
577 SetLastError( ERROR_CAN_NOT_COMPLETE
);
580 if (hostname
&& len_hostname
< strlen( hostname
))
582 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
585 if (!(urlW
= strdupAW( url
, -1 ))) goto done
;
586 if (hostname
&& !(hostnameW
= strdupAW( hostname
, -1 ))) goto done
;
588 TRACE( "%s\n", debugstr_w(global_script
->text
) );
589 ret
= run_script( global_script
->text
, urlW
, hostnameW
, proxy
, len_proxy
);
592 heap_free( hostnameW
);
594 LeaveCriticalSection( &cs_jsproxy
);