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"
35 WINE_DEFAULT_DEBUG_CHANNEL(jsproxy
);
37 static CRITICAL_SECTION cs_jsproxy
;
38 static CRITICAL_SECTION_DEBUG critsect_debug
=
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
)
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
);
61 static inline char *strdupWA( const WCHAR
*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
);
72 static struct 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
);
94 static WCHAR
*load_script( const char *filename
)
97 DWORD size
, bytes_read
;
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
);
115 CloseHandle( handle
);
120 /******************************************************************
121 * InternetInitializeAutoProxyDll (jsproxy.@)
123 BOOL WINAPI
JSPROXY_InternetInitializeAutoProxyDll( DWORD version
, LPSTR tmpfile
, LPSTR mime
,
124 AutoProxyHelperFunctions
*callbacks
,
125 LPAUTO_PROXY_SCRIPT_BUFFER buffer
)
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
);
143 free( global_script
->text
);
144 if ((global_script
->text
= strdupAW( buffer
->lpszScriptBuffer
,
145 buffer
->dwScriptBufferSize
))) ret
= TRUE
;
149 free( global_script
->text
);
150 if ((global_script
->text
= load_script( tmpfile
))) ret
= TRUE
;
153 LeaveCriticalSection( &cs_jsproxy
);
157 static HRESULT WINAPI
dispex_QueryInterface(
158 IDispatchEx
*iface
, REFIID riid
, void **ppv
)
162 if (IsEqualGUID( riid
, &IID_IUnknown
) ||
163 IsEqualGUID( riid
, &IID_IDispatch
) ||
164 IsEqualGUID( riid
, &IID_IDispatchEx
))
167 return E_NOINTERFACE
;
172 static ULONG WINAPI
dispex_AddRef(
178 static ULONG WINAPI
dispex_Release(
184 static HRESULT WINAPI
dispex_GetTypeInfoCount(
185 IDispatchEx
*iface
, UINT
*info
)
190 static HRESULT WINAPI
dispex_GetTypeInfo(
191 IDispatchEx
*iface
, UINT info
, LCID lcid
, ITypeInfo
**type_info
)
196 static HRESULT WINAPI
dispex_GetIDsOfNames(
197 IDispatchEx
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*id
)
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
)
209 static HRESULT WINAPI
dispex_DeleteMemberByName(
210 IDispatchEx
*iface
, BSTR name
, DWORD flags
)
215 static HRESULT WINAPI
dispex_DeleteMemberByDispID(
216 IDispatchEx
*iface
, DISPID id
)
221 static HRESULT WINAPI
dispex_GetMemberProperties(
222 IDispatchEx
*iface
, DISPID id
, DWORD flags_fetch
, DWORD
*flags
)
227 static HRESULT WINAPI
dispex_GetMemberName(
228 IDispatchEx
*iface
, DISPID id
, BSTR
*name
)
233 static HRESULT WINAPI
dispex_GetNextDispID(
234 IDispatchEx
*iface
, DWORD flags
, DISPID id
, DISPID
*next
)
239 static HRESULT WINAPI
dispex_GetNameSpaceParent(
240 IDispatchEx
*iface
, IUnknown
**unk
)
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
;
255 return DISP_E_UNKNOWNNAME
;
258 static char *get_computer_name( COMPUTER_NAME_FORMAT format
)
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
))
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
)
286 struct addrinfo
*ai
, *elem
;
291 hostnameA
= strdupWA( hostname
);
293 hostnameA
= get_computer_name( ComputerNamePhysicalDnsFullyQualified
);
295 if (!hostnameA
) return E_OUTOFMEMORY
;
296 res
= getaddrinfo( hostnameA
, NULL
, NULL
, &ai
);
298 if (res
) return S_FALSE
;
301 while (elem
&& elem
->ai_family
!= AF_INET
) elem
= elem
->ai_next
;
307 printf_addr( L
"%u.%u.%u.%u", addr
, ARRAY_SIZE(addr
), (struct sockaddr_in
*)elem
->ai_addr
);
309 V_VT( result
) = VT_BSTR
;
310 V_BSTR( result
) = SysAllocString( addr
);
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(¶ms
->rgvarg
[0]) != VT_BSTR
) return DISP_E_BADVARTYPE
;
322 return dns_resolve( V_BSTR(¶ms
->rgvarg
[0]), result
);
324 return DISP_E_MEMBERNOTFOUND
;
327 static const IDispatchExVtbl dispex_vtbl
=
329 dispex_QueryInterface
,
332 dispex_GetTypeInfoCount
,
334 dispex_GetIDsOfNames
,
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
)
353 if (IsEqualGUID( &IID_IUnknown
, riid
))
355 else if (IsEqualGUID( &IID_IActiveScriptSite
, riid
))
358 return E_NOINTERFACE
;
360 IUnknown_AddRef( (IUnknown
*)*ppv
);
364 static ULONG WINAPI
site_AddRef(
365 IActiveScriptSite
*iface
)
370 static ULONG WINAPI
site_Release(
371 IActiveScriptSite
*iface
)
376 static HRESULT WINAPI
site_GetLCID(
377 IActiveScriptSite
*iface
, LCID
*lcid
)
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
;
394 static HRESULT WINAPI
site_GetDocVersionString(
395 IActiveScriptSite
*iface
, BSTR
*version
)
400 static HRESULT WINAPI
site_OnScriptTerminate(
401 IActiveScriptSite
*iface
, const VARIANT
*result
, const EXCEPINFO
*info
)
406 static HRESULT WINAPI
site_OnStateChange(
407 IActiveScriptSite
*iface
, SCRIPTSTATE state
)
412 static HRESULT WINAPI
site_OnScriptError(
413 IActiveScriptSite
*iface
, IActiveScriptError
*error
)
418 static HRESULT WINAPI
site_OnEnterScript(
419 IActiveScriptSite
*iface
)
424 static HRESULT WINAPI
site_OnLeaveScript(
425 IActiveScriptSite
*iface
)
430 static const IActiveScriptSiteVtbl site_vtbl
=
437 site_GetDocVersionString
,
438 site_OnScriptTerminate
,
445 static IActiveScriptSite script_site
= { &site_vtbl
};
447 static BSTR
include_pac_utils( const WCHAR
*script
)
449 HMODULE hmod
= GetModuleHandleA( "jsproxy.dll" );
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
);
468 #define IActiveScriptParse_Release IActiveScriptParse64_Release
469 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
470 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
472 #define IActiveScriptParse_Release IActiveScriptParse32_Release
473 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
474 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
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
;
485 BSTR func
= NULL
, full_script
= NULL
;
486 VARIANT args
[2], retval
;
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
;
533 params
.cNamedArgs
= 0;
534 hr
= IDispatch_Invoke( dispatch
, dispid
, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
,
535 ¶ms
, &retval
, NULL
, NULL
);
536 VariantClear( &args
[0] );
537 VariantClear( &args
[1] );
540 WARN("script failed 0x%08lx\n", hr
);
543 if ((*result_str
= strdupWA( V_BSTR( &retval
) )))
545 TRACE( "result: %s\n", debugstr_a(*result_str
) );
546 *result_len
= strlen( *result_str
) + 1;
549 VariantClear( &retval
);
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();
561 /******************************************************************
562 * InternetGetProxyInfo (jsproxy.@)
564 BOOL WINAPI
InternetGetProxyInfo( LPCSTR url
, DWORD len_url
, LPCSTR hostname
, DWORD len_hostname
, LPSTR
*proxy
,
567 WCHAR
*urlW
= NULL
, *hostnameW
= NULL
;
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
);
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
);
588 LeaveCriticalSection( &cs_jsproxy
);