Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2008 compeople AG and others. |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
8 |
* Contributors: |
9 |
* compeople AG (Stefan Liebig) - initial API and implementation |
10 |
*******************************************************************************/ |
11 |
|
12 |
|
13 |
#if _MSC_VER > 1000 |
14 |
#pragma once |
15 |
#endif // _MSC_VER > 1000 |
16 |
|
17 |
|
18 |
#define WIN32_LEAN_AND_MEAN |
19 |
|
20 |
#include <stdio.h> |
21 |
#include <iostream> |
22 |
#include <windows.h> |
23 |
#include <winhttp.h> |
24 |
#include <objbase.h> |
25 |
|
26 |
#include <org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp.h> |
27 |
|
28 |
using namespace std; |
29 |
|
30 |
// Remember the GetLastError() after a failed WinHttp... call. |
31 |
static int lastError; |
32 |
|
33 |
BOOL APIENTRY DllMain( HANDLE hModule, |
34 |
DWORD ul_reason_for_call, |
35 |
LPVOID lpReserved |
36 |
) { |
37 |
switch (ul_reason_for_call) { |
38 |
case DLL_PROCESS_ATTACH: |
39 |
#ifdef _DEBUG |
40 |
cout << "DLL_PROCESS_ATTACH - jWinHttp" << endl; |
41 |
#endif |
42 |
break; |
43 |
case DLL_THREAD_ATTACH: |
44 |
#ifdef _DEBUG |
45 |
cout << "DLL_THREAD_ATTACH - jWinHttp" << endl; |
46 |
#endif |
47 |
break; |
48 |
case DLL_THREAD_DETACH: |
49 |
#ifdef _DEBUG |
50 |
cout << "DLL_THREAD_DETACH - jWinHttp" << endl; |
51 |
#endif |
52 |
break; |
53 |
case DLL_PROCESS_DETACH: |
54 |
#ifdef _DEBUG |
55 |
cout << "DLL_PROCESS_DETACH - jWinHttp" << endl; |
56 |
#endif |
57 |
break; |
58 |
} |
59 |
return TRUE; |
60 |
} |
61 |
|
62 |
|
63 |
/* |
64 |
* Helper for some ugly things! |
65 |
* ............................ |
66 |
*/ |
67 |
|
68 |
const jchar * getStringChars( JNIEnv * env, jstring jString ) { |
69 |
if ( jString != NULL ) { |
70 |
return env->GetStringChars( jString, NULL ); |
71 |
} else { |
72 |
return NULL; |
73 |
} |
74 |
} |
75 |
|
76 |
void releaseStringChars( JNIEnv * env, jstring jString, const jchar * jCharString ) { |
77 |
if ( jString != NULL ) { |
78 |
env->ReleaseStringChars( jString, jCharString ); |
79 |
} |
80 |
} |
81 |
|
82 |
jobject newString( JNIEnv * env, LPWSTR string ) { |
83 |
return env->NewString( (const jchar *)string, lstrlenW( string ) ); |
84 |
} |
85 |
|
86 |
void setStringField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, LPWSTR value ) { |
87 |
if ( value != NULL ) { |
88 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "Ljava/lang/String;" ); |
89 |
env->SetObjectField( jObject, jFieldId, newString( env, value ) ); |
90 |
GlobalFree( value ); |
91 |
} |
92 |
} |
93 |
|
94 |
jstring getStringField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
95 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "Ljava/lang/String;" ); |
96 |
return (jstring)env->GetObjectField( jObject, jFieldId ); |
97 |
} |
98 |
|
99 |
void setBooleanField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, BOOL value ) { |
100 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "Z" ); |
101 |
env->SetBooleanField( jObject, jFieldId, value ); |
102 |
} |
103 |
|
104 |
jboolean getBooleanField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
105 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "Z" ); |
106 |
return env->GetBooleanField( jObject, jFieldId ); |
107 |
} |
108 |
|
109 |
void setIntField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, jint value ) { |
110 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "I" ); |
111 |
env->SetIntField( jObject, jFieldId, value ); |
112 |
} |
113 |
|
114 |
jint getIntField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
115 |
jfieldID jFieldId = env->GetFieldID( jClass, field, "I" ); |
116 |
return env->GetIntField( jObject, jFieldId ); |
117 |
} |
118 |
|
119 |
#ifdef _DEBUG |
120 |
LPCWSTR null( const LPCWSTR string ) { |
121 |
if ( string == NULL ) { |
122 |
return (LPCWSTR) L"null"; |
123 |
} else { |
124 |
return string; |
125 |
} |
126 |
} |
127 |
|
128 |
LPWSTR null( const LPWSTR string ) { |
129 |
if ( string == NULL ) { |
130 |
return (LPWSTR) L"null"; |
131 |
} else { |
132 |
return string; |
133 |
} |
134 |
} |
135 |
#endif |
136 |
|
137 |
/* |
138 |
* The real ugly work goes on here! |
139 |
* ................................ |
140 |
*/ |
141 |
|
142 |
|
143 |
/* |
144 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
145 |
* Method: open |
146 |
* Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;I)I |
147 |
*/ |
148 |
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_open |
149 |
(JNIEnv * env, jclass jClass, jstring jUserAgent, jint jAccessType, jstring jProxyName, jstring jProxyBypass, jint jFlags ) { |
150 |
|
151 |
#ifdef _DEBUG |
152 |
cout << "WinHttp_open - entered" << endl; |
153 |
#endif |
154 |
|
155 |
const jchar * userAgent = (const jchar *) L"jWinHttp Java Wrapper"; |
156 |
const jchar * proxyName = NULL; |
157 |
const jchar * proxyBypass = NULL; |
158 |
|
159 |
userAgent = getStringChars( env, jUserAgent ); |
160 |
proxyName = getStringChars( env, jProxyName ); |
161 |
proxyBypass = getStringChars( env, jProxyBypass ); |
162 |
|
163 |
CoInitialize( NULL ); // --> http://support.microsoft.com/?kbid=834742 |
164 |
|
165 |
int hInternet = (int) WinHttpOpen( (LPCWSTR)userAgent, jAccessType, (LPCWSTR)proxyName, (LPCWSTR)proxyBypass, jFlags ); |
166 |
|
167 |
if ( hInternet == NULL ) { |
168 |
lastError = GetLastError(); |
169 |
#ifdef _DEBUG |
170 |
cout << "WinHttpOpen() failed with " << lastError << endl; |
171 |
#endif |
172 |
} else { |
173 |
lastError = 0; |
174 |
} |
175 |
|
176 |
|
177 |
#ifdef _DEBUG |
178 |
cout << "WinHttpOpen() returned: " << hInternet << endl; |
179 |
#endif |
180 |
|
181 |
|
182 |
releaseStringChars( env, jUserAgent, userAgent ); |
183 |
releaseStringChars( env, jProxyName, proxyName ); |
184 |
releaseStringChars( env, jProxyBypass, proxyBypass ); |
185 |
|
186 |
#ifdef _DEBUG |
187 |
cout << "WinHttp_open - exit" << endl; |
188 |
#endif |
189 |
|
190 |
return hInternet; |
191 |
} |
192 |
|
193 |
/* |
194 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
195 |
* Method: closeHandle |
196 |
* Signature: (I)Z |
197 |
*/ |
198 |
JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_closeHandle |
199 |
(JNIEnv * env, jclass jClass, jint jInternet) { |
200 |
|
201 |
#ifdef _DEBUG |
202 |
cout << "WinHttp_closeHandle - entered" << endl; |
203 |
#endif |
204 |
|
205 |
BOOL ok = WinHttpCloseHandle( (void *) jInternet ); |
206 |
|
207 |
if ( ! ok ) { |
208 |
lastError = GetLastError(); |
209 |
#ifdef _DEBUG |
210 |
cout << "WinHttpClose() failed with " << lastError << endl; |
211 |
#endif |
212 |
} else { |
213 |
lastError = 0; |
214 |
} |
215 |
|
216 |
CoUninitialize(); |
217 |
|
218 |
#ifdef _DEBUG |
219 |
cout << "WinHttp_closeHandle - exit" << endl; |
220 |
#endif |
221 |
|
222 |
return ok; |
223 |
} |
224 |
|
225 |
/* |
226 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
227 |
* Method: getIEProxyConfigForCurrentUser |
228 |
* Signature: (Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpCurrentUserIEProxyConfig;)Z |
229 |
*/ |
230 |
JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getIEProxyConfigForCurrentUser |
231 |
(JNIEnv * env, jclass jClass, jobject jWinHttpCurrentUserIEProxyConfig) { |
232 |
|
233 |
#ifdef _DEBUG |
234 |
cout << "WinHttp_getIEProxyConfigForCurrentUser - entered" << endl; |
235 |
#endif |
236 |
|
237 |
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig; |
238 |
ZeroMemory( &proxyConfig, sizeof( proxyConfig ) ); |
239 |
|
240 |
BOOL ok = WinHttpGetIEProxyConfigForCurrentUser( &proxyConfig ); |
241 |
|
242 |
if ( ! ok ) { |
243 |
lastError = GetLastError(); |
244 |
#ifdef _DEBUG |
245 |
cout << "HttpGetIEProxyConfigForCurrentUser() failed with " << lastError << endl; |
246 |
#endif |
247 |
} |
248 |
|
249 |
if ( ok ) { |
250 |
|
251 |
#ifdef _DEBUG |
252 |
cout << "proxyConfig.fAutoDetect: " << proxyConfig.fAutoDetect << endl; |
253 |
wcout << L"proxyConfig.lpszProxy: " << null( proxyConfig.lpszProxy ) << endl; |
254 |
wcout << L"proxyConfig.lpszProxyBypass: " << null( proxyConfig.lpszProxyBypass ) << endl; |
255 |
#endif |
256 |
|
257 |
lastError = 0; |
258 |
jclass jWinHttpCurrentUserIEProxyConfigClass = env->GetObjectClass( jWinHttpCurrentUserIEProxyConfig ); |
259 |
setBooleanField( env,jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "isAutoDetect", proxyConfig.fAutoDetect ); |
260 |
setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "autoConfigUrl", proxyConfig.lpszAutoConfigUrl ); |
261 |
setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "proxy", proxyConfig.lpszProxy ); |
262 |
setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "proxyBypass", proxyConfig.lpszProxyBypass ); |
263 |
} |
264 |
|
265 |
|
266 |
#ifdef _DEBUG |
267 |
cout << "WinHttp_getIEProxyConfigForCurrentUser - exit" << endl; |
268 |
#endif |
269 |
|
270 |
return ok; |
271 |
} |
272 |
|
273 |
/* |
274 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
275 |
* Method: getProxyForUrl |
276 |
* Signature: (ILjava/lang/String;Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpAutoProxyOptions;Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpProxyInfo;)Z |
277 |
*/ |
278 |
JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getProxyForUrl |
279 |
(JNIEnv * env, jclass jClass, jint jInternet, jstring jUrl, jobject jWinHttpAutoProxyOptions, jobject jWinHttpProxyInfo ) { |
280 |
|
281 |
#ifdef _DEBUG |
282 |
cout << "WinHttp_getProxyForUrl - entered" << endl; |
283 |
#endif |
284 |
|
285 |
WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions; |
286 |
ZeroMemory( &autoProxyOptions, sizeof( autoProxyOptions ) ); |
287 |
|
288 |
jclass jWinHttpAutoProxyOptionsClass = env->GetObjectClass( jWinHttpAutoProxyOptions ); |
289 |
|
290 |
autoProxyOptions.dwFlags = getIntField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "flags" ); |
291 |
autoProxyOptions.dwAutoDetectFlags = getIntField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoDetectFlags" ); |
292 |
jstring jAutoConfigUrl = getStringField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoConfigUrl" ); |
293 |
autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)getStringChars( env, jAutoConfigUrl ); |
294 |
|
295 |
// The ´reserved´ fields will not be transfered! |
296 |
// - String reservedPointer |
297 |
// - int reservedInt |
298 |
|
299 |
autoProxyOptions.fAutoLogonIfChallenged = getBooleanField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoLogonIfChallenged" ); |
300 |
|
301 |
#ifdef _DEBUG |
302 |
cout << "autoProxyOptions.dwFlags: " << autoProxyOptions.dwFlags << endl; |
303 |
cout << "autoProxyOptions.dwAutoDetectFlags: " << autoProxyOptions.dwAutoDetectFlags << endl; |
304 |
wcout << L"autoProxyOptions.lpszAutoConfigUrl: " << null( autoProxyOptions.lpszAutoConfigUrl ) << endl; |
305 |
cout << "autoProxyOptions.fAutoLogonIfChallenged: " << autoProxyOptions.fAutoLogonIfChallenged << endl; |
306 |
#endif |
307 |
|
308 |
WINHTTP_PROXY_INFO proxyInfo; |
309 |
ZeroMemory( &proxyInfo, sizeof( proxyInfo ) ); |
310 |
|
311 |
const jchar * url = getStringChars( env, jUrl ); |
312 |
|
313 |
BOOL ok = WinHttpGetProxyForUrl( (void *)jInternet, (LPCWSTR)url, &autoProxyOptions, &proxyInfo ); |
314 |
|
315 |
if ( ! ok ) { |
316 |
lastError = GetLastError(); |
317 |
#ifdef _DEBUG |
318 |
cout << "WinHttpGetProxyForUrl() failed with " << lastError << endl; |
319 |
#endif |
320 |
} |
321 |
|
322 |
releaseStringChars( env, jUrl, url ); |
323 |
releaseStringChars( env, jAutoConfigUrl, (const jchar *)autoProxyOptions.lpszAutoConfigUrl ); |
324 |
|
325 |
if ( ok ) { |
326 |
lastError = 0; |
327 |
jclass jWinHttpProxyInfoClass = env->GetObjectClass( jWinHttpProxyInfo ); |
328 |
|
329 |
#ifdef _DEBUG |
330 |
cout << "proxyInfo.dwAccessType: " << proxyInfo.dwAccessType << endl; |
331 |
wcout << L"proxyInfo.lpszProxy: " << null( proxyInfo.lpszProxy ) << endl; |
332 |
wcout << L"proxyInfo.lpszProxyBypass: " << null( proxyInfo.lpszProxyBypass ) << endl; |
333 |
#endif |
334 |
|
335 |
setIntField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "accessType", proxyInfo.dwAccessType ); |
336 |
setStringField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "proxy", proxyInfo.lpszProxy ); |
337 |
setStringField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "proxyBypass", proxyInfo.lpszProxyBypass ); |
338 |
} |
339 |
|
340 |
#ifdef _DEBUG |
341 |
cout << "WinHttp_getProxyForUrl - exit" << endl; |
342 |
#endif |
343 |
|
344 |
return ok; |
345 |
} |
346 |
|
347 |
/* |
348 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
349 |
* Method: detectAutoProxyConfigUrl |
350 |
* Signature: (Lorg/eclipse/core/internal/net/proxy/win32/winhttp/AutoProxyHolder;)Z |
351 |
*/ |
352 |
JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_detectAutoProxyConfigUrl |
353 |
(JNIEnv * env, jclass jClass, jobject jAutoProxyHolder) { |
354 |
|
355 |
#ifdef _DEBUG |
356 |
cout << "WinHttp_detectAutoProxyConfigUrl - entered" << endl; |
357 |
#endif |
358 |
|
359 |
jclass jAutoProxyHolderClass = env->GetObjectClass( jAutoProxyHolder ); |
360 |
DWORD dwAutoDetectFlags = getIntField( env, jAutoProxyHolderClass, jAutoProxyHolder, "autoDetectFlags" ); |
361 |
|
362 |
#ifdef _DEBUG |
363 |
cout << "autoProxyHolder.autoDetectFlags: " << dwAutoDetectFlags << endl; |
364 |
#endif |
365 |
|
366 |
LPWSTR pwszAutoConfigUrl; |
367 |
|
368 |
BOOL ok = WinHttpDetectAutoProxyConfigUrl( dwAutoDetectFlags, &pwszAutoConfigUrl ); |
369 |
|
370 |
if ( ! ok ) { |
371 |
lastError = GetLastError(); |
372 |
#ifdef _DEBUG |
373 |
cout << "WinHttpDetectAutoProxyConfigUrl() failed with " << lastError << endl; |
374 |
#endif |
375 |
} |
376 |
|
377 |
if ( ok ) { |
378 |
lastError = 0; |
379 |
|
380 |
#ifdef _DEBUG |
381 |
wcout << L"autoConfigUrl: " << null( pwszAutoConfigUrl ) << endl; |
382 |
#endif |
383 |
|
384 |
setStringField( env, jAutoProxyHolderClass, jAutoProxyHolder, "autoConfigUrl", pwszAutoConfigUrl ); |
385 |
} |
386 |
|
387 |
#ifdef _DEBUG |
388 |
cout << "WinHttp_detectAutoProxyConfigUrl - exit" << endl; |
389 |
#endif |
390 |
|
391 |
return ok; |
392 |
} |
393 |
|
394 |
|
395 |
/* |
396 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
397 |
* Method: getLastError |
398 |
* Signature: ()I |
399 |
*/ |
400 |
JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getLastError |
401 |
(JNIEnv * env, jclass jClass) { |
402 |
|
403 |
#ifdef _DEBUG |
404 |
cout << "WinHttp_getLastError - entered" << endl; |
405 |
#endif |
406 |
|
407 |
#ifdef _DEBUG |
408 |
cout << "WinHttp_getLastError - exit" << endl; |
409 |
#endif |
410 |
|
411 |
return lastError; |
412 |
} |
413 |
|
414 |
/* |
415 |
* Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
416 |
* Method: getLastErrorMessage |
417 |
* Signature: ()Ljava/lang/String; |
418 |
*/ |
419 |
JNIEXPORT jstring JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getLastErrorMessage |
420 |
(JNIEnv * env, jclass jClass) { |
421 |
|
422 |
#ifdef _DEBUG |
423 |
cout << "WinHttp_getLastErrorMessage - entered" << endl; |
424 |
#endif |
425 |
|
426 |
LPVOID lpMsgBuf = NULL; |
427 |
DWORD result = 0; |
428 |
|
429 |
if ( lastError >= WINHTTP_ERROR_BASE && lastError <= WINHTTP_ERROR_LAST ) { |
430 |
HMODULE hModule = GetModuleHandle( "winhttp.dll" ); |
431 |
|
432 |
if ( hModule == NULL ) { |
433 |
lpMsgBuf = "Could not retrieve error message, because ´GetModuleHandle( \"winhttp.dll\" )´ failed."; |
434 |
} else { |
435 |
result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
436 |
FORMAT_MESSAGE_FROM_HMODULE | |
437 |
FORMAT_MESSAGE_IGNORE_INSERTS, |
438 |
hModule, |
439 |
lastError, |
440 |
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language |
441 |
(LPTSTR) &lpMsgBuf, |
442 |
0, |
443 |
NULL ); |
444 |
} |
445 |
|
446 |
} else { |
447 |
result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
448 |
FORMAT_MESSAGE_FROM_SYSTEM | |
449 |
FORMAT_MESSAGE_IGNORE_INSERTS, |
450 |
NULL, |
451 |
lastError, |
452 |
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language |
453 |
(LPTSTR) &lpMsgBuf, |
454 |
0, |
455 |
NULL ); |
456 |
} |
457 |
|
458 |
if ( lpMsgBuf == NULL ) { |
459 |
#ifdef _DEBUG |
460 |
cout << "WinHttp_getLastErrorMessage() failed with " << GetLastError() << " for error code " << lastError << endl; |
461 |
#endif |
462 |
|
463 |
lpMsgBuf = "Could not retrieve error message."; |
464 |
} |
465 |
|
466 |
jstring string = env->NewStringUTF( (char *) lpMsgBuf ); |
467 |
|
468 |
if ( result > 0 ) { |
469 |
// Free dynamically allocated buffer |
470 |
LocalFree( lpMsgBuf ); |
471 |
} |
472 |
|
473 |
#ifdef _DEBUG |
474 |
cout << "WinHttp_getLastErrorMessage - exit" << endl; |
475 |
#endif |
476 |
|
477 |
return string; |
478 |
} |
479 |
|