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 <wine/config.h>
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
35 #include <wine/debug.h>
36 #include <wine/unicode.h>
38 #ifdef HAVE_SYS_SOCKET_H
39 # include <sys/socket.h>
41 #ifdef HAVE_NETINET_IN_H
42 # include <netinet/in.h>
47 #if defined(__MINGW32__) || defined (_MSC_VER)
48 # include <ws2tcpip.h>
50 # define closesocket close
51 # define ioctlsocket ioctl
58 static HINSTANCE instance
;
60 WINE_DEFAULT_DEBUG_CHANNEL(jsproxy
);
62 static CRITICAL_SECTION cs_jsproxy
;
63 static CRITICAL_SECTION_DEBUG critsect_debug
=
66 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
67 0, 0, { (DWORD_PTR
)(__FILE__
": cs_jsproxy") }
69 static CRITICAL_SECTION cs_jsproxy
= { &critsect_debug
, -1, 0, 0, 0, 0 };
71 static const WCHAR global_funcsW
[] = {'g','l','o','b','a','l','_','f','u','n','c','s',0};
72 static const WCHAR dns_resolveW
[] = {'d','n','s','_','r','e','s','o','l','v','e',0};
74 /******************************************************************
77 BOOL WINAPI
DllMain( HINSTANCE hinst
, DWORD reason
, LPVOID reserved
)
81 case DLL_PROCESS_ATTACH
:
83 DisableThreadLibraryCalls( hinst
);
86 case DLL_PROCESS_DETACH
:
92 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(size_t size
)
94 return HeapAlloc(GetProcessHeap(), 0, size
);
97 static inline BOOL
heap_free(void *mem
)
99 return HeapFree(GetProcessHeap(), 0, mem
);
102 static inline WCHAR
*strdupAW( const char *src
, int len
)
107 int dst_len
= MultiByteToWideChar( CP_ACP
, 0, src
, len
, NULL
, 0 );
108 if ((dst
= heap_alloc( (dst_len
+ 1) * sizeof(WCHAR
) )))
110 len
= MultiByteToWideChar( CP_ACP
, 0, src
, len
, dst
, dst_len
);
117 static inline char *strdupWA( const WCHAR
*src
)
122 int len
= WideCharToMultiByte( CP_ACP
, 0, src
, -1, NULL
, 0, NULL
, NULL
);
123 if ((dst
= heap_alloc( len
))) WideCharToMultiByte( CP_ACP
, 0, src
, -1, dst
, len
, NULL
, NULL
);
128 static struct pac_script
132 static struct pac_script
*global_script
= &pac_script
;
134 /******************************************************************
135 * InternetDeInitializeAutoProxyDll (jsproxy.@)
137 BOOL WINAPI
InternetDeInitializeAutoProxyDll( LPSTR mime
, DWORD reserved
)
139 TRACE( "%s, %u\n", debugstr_a(mime
), reserved
);
141 EnterCriticalSection( &cs_jsproxy
);
143 heap_free( global_script
->text
);
144 global_script
->text
= NULL
;
146 LeaveCriticalSection( &cs_jsproxy
);
150 static WCHAR
*load_script( const char *filename
)
153 DWORD size
, bytes_read
;
156 WCHAR
*script
= NULL
;
158 handle
= CreateFileA( filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
159 if (handle
== INVALID_HANDLE_VALUE
) return NULL
;
161 size
= GetFileSize( handle
, NULL
);
162 if (!(buffer
= heap_alloc( size
))) goto done
;
163 if (!ReadFile( handle
, buffer
, size
, &bytes_read
, NULL
) || bytes_read
!= size
) goto done
;
165 len
= MultiByteToWideChar( CP_ACP
, 0, buffer
, size
, NULL
, 0 );
166 if (!(script
= heap_alloc( (len
+ 1) * sizeof(WCHAR
) ))) goto done
;
167 MultiByteToWideChar( CP_ACP
, 0, buffer
, size
, script
, len
);
171 CloseHandle( handle
);
176 /******************************************************************
177 * InternetInitializeAutoProxyDll (jsproxy.@)
179 BOOL WINAPI
JSPROXY_InternetInitializeAutoProxyDll( DWORD version
, LPSTR tmpfile
, LPSTR mime
,
180 AutoProxyHelperFunctions
*callbacks
,
181 LPAUTO_PROXY_SCRIPT_BUFFER buffer
)
185 TRACE( "%u, %s, %s, %p, %p\n", version
, debugstr_a(tmpfile
), debugstr_a(mime
), callbacks
, buffer
);
187 if (callbacks
) FIXME( "callbacks not supported\n" );
189 EnterCriticalSection( &cs_jsproxy
);
191 if (buffer
&& buffer
->dwStructSize
== sizeof(*buffer
) && buffer
->lpszScriptBuffer
)
194 for (i
= 0; i
< buffer
->dwScriptBufferSize
; i
++)
196 if (!buffer
->lpszScriptBuffer
[i
]) break;
199 if (len
== buffer
->dwScriptBufferSize
)
201 SetLastError( ERROR_INVALID_PARAMETER
);
202 LeaveCriticalSection( &cs_jsproxy
);
205 heap_free( global_script
->text
);
206 if ((global_script
->text
= strdupAW( buffer
->lpszScriptBuffer
, len
))) ret
= TRUE
;
210 heap_free( global_script
->text
);
211 if ((global_script
->text
= load_script( tmpfile
))) ret
= TRUE
;
214 LeaveCriticalSection( &cs_jsproxy
);
218 static HRESULT WINAPI
dispex_QueryInterface(
219 IDispatchEx
*iface
, REFIID riid
, void **ppv
)
223 if (IsEqualGUID( riid
, &IID_IUnknown
) ||
224 IsEqualGUID( riid
, &IID_IDispatch
) ||
225 IsEqualGUID( riid
, &IID_IDispatchEx
))
228 return E_NOINTERFACE
;
233 static ULONG WINAPI
dispex_AddRef(
239 static ULONG WINAPI
dispex_Release(
245 static HRESULT WINAPI
dispex_GetTypeInfoCount(
246 IDispatchEx
*iface
, UINT
*info
)
251 static HRESULT WINAPI
dispex_GetTypeInfo(
252 IDispatchEx
*iface
, UINT info
, LCID lcid
, ITypeInfo
**type_info
)
257 static HRESULT WINAPI
dispex_GetIDsOfNames(
258 IDispatchEx
*iface
, REFIID riid
, LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*id
)
263 static HRESULT WINAPI
dispex_Invoke(
264 IDispatchEx
*iface
, DISPID member
, REFIID riid
, LCID lcid
, WORD flags
,
265 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excep
, UINT
*err
)
270 static HRESULT WINAPI
dispex_DeleteMemberByName(
271 IDispatchEx
*iface
, BSTR name
, DWORD flags
)
276 static HRESULT WINAPI
dispex_DeleteMemberByDispID(
277 IDispatchEx
*iface
, DISPID id
)
282 static HRESULT WINAPI
dispex_GetMemberProperties(
283 IDispatchEx
*iface
, DISPID id
, DWORD flags_fetch
, DWORD
*flags
)
288 static HRESULT WINAPI
dispex_GetMemberName(
289 IDispatchEx
*iface
, DISPID id
, BSTR
*name
)
294 static HRESULT WINAPI
dispex_GetNextDispID(
295 IDispatchEx
*iface
, DWORD flags
, DISPID id
, DISPID
*next
)
300 static HRESULT WINAPI
dispex_GetNameSpaceParent(
301 IDispatchEx
*iface
, IUnknown
**unk
)
306 #define DISPID_GLOBAL_DNSRESOLVE 0x1000
308 static HRESULT WINAPI
dispex_GetDispID(
309 IDispatchEx
*iface
, BSTR name
, DWORD flags
, DISPID
*id
)
311 if (!strcmpW( name
, dns_resolveW
))
313 *id
= DISPID_GLOBAL_DNSRESOLVE
;
316 return DISP_E_UNKNOWNNAME
;
319 static char *get_computer_name( COMPUTER_NAME_FORMAT format
)
324 GetComputerNameExA( format
, NULL
, &size
);
325 if (GetLastError() != ERROR_MORE_DATA
) return NULL
;
326 if (!(ret
= heap_alloc( size
))) return NULL
;
327 if (!GetComputerNameExA( format
, ret
, &size
))
335 static void printf_addr( const WCHAR
*fmt
, WCHAR
*buf
, struct sockaddr_in
*addr
)
338 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 24 & 0xff),
339 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 16 & 0xff),
340 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) >> 8 & 0xff),
341 (unsigned int)(ntohl( addr
->sin_addr
.s_addr
) & 0xff) );
344 static HRESULT
dns_resolve( const WCHAR
*hostname
, VARIANT
*result
)
346 #ifdef HAVE_GETADDRINFO
347 static const WCHAR fmtW
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
349 struct addrinfo
*ai
, *elem
;
354 hostnameA
= strdupWA( hostname
);
356 hostnameA
= get_computer_name( ComputerNamePhysicalDnsFullyQualified
);
358 if (!hostnameA
) return E_OUTOFMEMORY
;
359 res
= getaddrinfo( hostnameA
, NULL
, NULL
, &ai
);
360 heap_free( hostnameA
);
361 if (res
) return S_FALSE
;
364 while (elem
&& elem
->ai_family
!= AF_INET
) elem
= elem
->ai_next
;
370 printf_addr( fmtW
, addr
, (struct sockaddr_in
*)elem
->ai_addr
);
372 V_VT( result
) = VT_BSTR
;
373 V_BSTR( result
) = SysAllocString( addr
);
376 FIXME("getaddrinfo not found at build time\n");
381 static HRESULT WINAPI
dispex_InvokeEx(
382 IDispatchEx
*iface
, DISPID id
, LCID lcid
, WORD flags
, DISPPARAMS
*params
,
383 VARIANT
*result
, EXCEPINFO
*exep
, IServiceProvider
*caller
)
385 if (id
== DISPID_GLOBAL_DNSRESOLVE
)
387 if (params
->cArgs
!= 1) return DISP_E_BADPARAMCOUNT
;
388 if (V_VT(¶ms
->rgvarg
[0]) != VT_BSTR
) return DISP_E_BADVARTYPE
;
389 return dns_resolve( V_BSTR(¶ms
->rgvarg
[0]), result
);
391 return DISP_E_MEMBERNOTFOUND
;
394 static const IDispatchExVtbl dispex_vtbl
=
396 dispex_QueryInterface
,
399 dispex_GetTypeInfoCount
,
401 dispex_GetIDsOfNames
,
405 dispex_DeleteMemberByName
,
406 dispex_DeleteMemberByDispID
,
407 dispex_GetMemberProperties
,
408 dispex_GetMemberName
,
409 dispex_GetNextDispID
,
410 dispex_GetNameSpaceParent
413 static IDispatchEx global_dispex
= { &dispex_vtbl
};
415 static HRESULT WINAPI
site_QueryInterface(
416 IActiveScriptSite
*iface
, REFIID riid
, void **ppv
)
420 if (IsEqualGUID( &IID_IUnknown
, riid
))
422 else if (IsEqualGUID( &IID_IActiveScriptSite
, riid
))
425 return E_NOINTERFACE
;
427 IUnknown_AddRef( (IUnknown
*)*ppv
);
431 static ULONG WINAPI
site_AddRef(
432 IActiveScriptSite
*iface
)
437 static ULONG WINAPI
site_Release(
438 IActiveScriptSite
*iface
)
443 static HRESULT WINAPI
site_GetLCID(
444 IActiveScriptSite
*iface
, LCID
*lcid
)
449 static HRESULT WINAPI
site_GetItemInfo(
450 IActiveScriptSite
*iface
, LPCOLESTR name
, DWORD mask
,
451 IUnknown
**item
, ITypeInfo
**type_info
)
453 if (!strcmpW( name
, global_funcsW
) && mask
== SCRIPTINFO_IUNKNOWN
)
455 *item
= (IUnknown
*)&global_dispex
;
461 static HRESULT WINAPI
site_GetDocVersionString(
462 IActiveScriptSite
*iface
, BSTR
*version
)
467 static HRESULT WINAPI
site_OnScriptTerminate(
468 IActiveScriptSite
*iface
, const VARIANT
*result
, const EXCEPINFO
*info
)
473 static HRESULT WINAPI
site_OnStateChange(
474 IActiveScriptSite
*iface
, SCRIPTSTATE state
)
479 static HRESULT WINAPI
site_OnScriptError(
480 IActiveScriptSite
*iface
, IActiveScriptError
*error
)
485 static HRESULT WINAPI
site_OnEnterScript(
486 IActiveScriptSite
*iface
)
491 static HRESULT WINAPI
site_OnLeaveScript(
492 IActiveScriptSite
*iface
)
497 static const IActiveScriptSiteVtbl site_vtbl
=
504 site_GetDocVersionString
,
505 site_OnScriptTerminate
,
512 static IActiveScriptSite script_site
= { &site_vtbl
};
514 static BSTR
include_pac_utils( const WCHAR
*script
)
516 static const WCHAR pacjsW
[] = {'p','a','c','.','j','s',0};
517 HMODULE hmod
= GetModuleHandleA( "jsproxy.dll" );
524 if (!(rsrc
= FindResourceW( hmod
, pacjsW
, (LPCWSTR
)40 ))) return NULL
;
525 size
= SizeofResource( hmod
, rsrc
);
526 data
= LoadResource( hmod
, rsrc
);
528 len
= MultiByteToWideChar( CP_ACP
, 0, data
, size
, NULL
, 0 );
529 if (!(ret
= SysAllocStringLen( NULL
, len
+ strlenW( script
) + 1 ))) return NULL
;
530 MultiByteToWideChar( CP_ACP
, 0, data
, size
, ret
, len
);
531 strcpyW( ret
+ len
, script
);
536 #define IActiveScriptParse_Release IActiveScriptParse64_Release
537 #define IActiveScriptParse_InitNew IActiveScriptParse64_InitNew
538 #define IActiveScriptParse_ParseScriptText IActiveScriptParse64_ParseScriptText
540 #define IActiveScriptParse_Release IActiveScriptParse32_Release
541 #define IActiveScriptParse_InitNew IActiveScriptParse32_InitNew
542 #define IActiveScriptParse_ParseScriptText IActiveScriptParse32_ParseScriptText
545 static BOOL
run_script( const WCHAR
*script
, const WCHAR
*url
, const WCHAR
*hostname
, char **result_str
, DWORD
*result_len
)
547 static const WCHAR jscriptW
[] = {'J','S','c','r','i','p','t',0};
548 static const WCHAR findproxyW
[] = {'F','i','n','d','P','r','o','x','y','F','o','r','U','R','L',0};
549 IActiveScriptParse
*parser
= NULL
;
550 IActiveScript
*engine
= NULL
;
551 IDispatch
*dispatch
= NULL
;
555 BSTR func
= NULL
, full_script
= NULL
;
556 VARIANT args
[2], retval
;
560 init
= CoInitialize( NULL
);
561 hr
= CLSIDFromProgID( jscriptW
, &clsid
);
562 if (hr
!= S_OK
) goto done
;
564 hr
= CoCreateInstance( &clsid
, NULL
, CLSCTX_INPROC_SERVER
|CLSCTX_INPROC_HANDLER
,
565 &IID_IActiveScript
, (void **)&engine
);
566 if (hr
!= S_OK
) goto done
;
568 hr
= IActiveScript_QueryInterface( engine
, &IID_IActiveScriptParse
, (void **)&parser
);
569 if (hr
!= S_OK
) goto done
;
571 hr
= IActiveScriptParse_InitNew( parser
);
572 if (hr
!= S_OK
) goto done
;
574 hr
= IActiveScript_SetScriptSite( engine
, &script_site
);
575 if (hr
!= S_OK
) goto done
;
577 hr
= IActiveScript_AddNamedItem( engine
, global_funcsW
, SCRIPTITEM_GLOBALMEMBERS
);
578 if (hr
!= S_OK
) goto done
;
580 if (!(full_script
= include_pac_utils( script
))) goto done
;
582 hr
= IActiveScriptParse_ParseScriptText( parser
, full_script
, NULL
, NULL
, NULL
, 0, 0, 0, NULL
, NULL
);
583 if (hr
!= S_OK
) goto done
;
585 hr
= IActiveScript_SetScriptState( engine
, SCRIPTSTATE_STARTED
);
586 if (hr
!= S_OK
) goto done
;
588 hr
= IActiveScript_GetScriptDispatch( engine
, NULL
, &dispatch
);
589 if (hr
!= S_OK
) goto done
;
591 if (!(func
= SysAllocString( findproxyW
))) goto done
;
592 hr
= IDispatch_GetIDsOfNames( dispatch
, &IID_NULL
, &func
, 1, LOCALE_SYSTEM_DEFAULT
, &dispid
);
593 if (hr
!= S_OK
) goto done
;
595 V_VT( &args
[0] ) = VT_BSTR
;
596 V_BSTR( &args
[0] ) = SysAllocString( hostname
);
597 V_VT( &args
[1] ) = VT_BSTR
;
598 V_BSTR( &args
[1] ) = SysAllocString( url
);
600 params
.rgvarg
= args
;
601 params
.rgdispidNamedArgs
= NULL
;
603 params
.cNamedArgs
= 0;
604 hr
= IDispatch_Invoke( dispatch
, dispid
, &IID_NULL
, LOCALE_SYSTEM_DEFAULT
, DISPATCH_METHOD
,
605 ¶ms
, &retval
, NULL
, NULL
);
606 VariantClear( &args
[0] );
607 VariantClear( &args
[1] );
610 WARN("script failed 0x%08x\n", hr
);
613 if ((*result_str
= strdupWA( V_BSTR( &retval
) )))
615 TRACE( "result: %s\n", debugstr_a(*result_str
) );
616 *result_len
= strlen( *result_str
) + 1;
619 VariantClear( &retval
);
622 SysFreeString( full_script
);
623 SysFreeString( func
);
624 if (dispatch
) IDispatch_Release( dispatch
);
625 if (parser
) IActiveScriptParse_Release( parser
);
626 if (engine
) IActiveScript_Release( engine
);
627 if (SUCCEEDED( init
)) CoUninitialize();
631 /******************************************************************
632 * InternetGetProxyInfo (jsproxy.@)
634 BOOL WINAPI
InternetGetProxyInfo( LPCSTR url
, DWORD len_url
, LPCSTR hostname
, DWORD len_hostname
, LPSTR
*proxy
,
637 WCHAR
*urlW
= NULL
, *hostnameW
= NULL
;
640 TRACE( "%s, %u, %s, %u, %p, %p\n", debugstr_a(url
), len_url
, hostname
, len_hostname
, proxy
, len_proxy
);
642 EnterCriticalSection( &cs_jsproxy
);
644 if (!global_script
->text
)
646 SetLastError( ERROR_CAN_NOT_COMPLETE
);
649 if (hostname
&& len_hostname
< strlen( hostname
))
651 SetLastError( ERROR_INSUFFICIENT_BUFFER
);
654 if (!(urlW
= strdupAW( url
, -1 ))) goto done
;
655 if (hostname
&& !(hostnameW
= strdupAW( hostname
, -1 ))) goto done
;
657 TRACE( "%s\n", debugstr_w(global_script
->text
) );
658 ret
= run_script( global_script
->text
, urlW
, hostnameW
, proxy
, len_proxy
);
661 heap_free( hostnameW
);
663 LeaveCriticalSection( &cs_jsproxy
);