| /******************************************************************************* |
| * Copyright (c) 2008 compeople AG and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * compeople AG (Stefan Liebig) - initial API and implementation |
| *******************************************************************************/ |
| |
| |
| #if _MSC_VER > 1000 |
| #pragma once |
| #endif // _MSC_VER > 1000 |
| |
| |
| #define WIN32_LEAN_AND_MEAN |
| |
| #include <stdio.h> |
| #include <iostream> |
| #include <windows.h> |
| #include <winhttp.h> |
| #include <objbase.h> |
| |
| #include "jWinHttp.h" |
| |
| using namespace std; |
| |
| // Remember the GetLastError() after a failed WinHttp... call. |
| static int lastError; |
| |
| BOOL APIENTRY DllMain( HANDLE hModule, |
| DWORD ul_reason_for_call, |
| LPVOID lpReserved |
| ) { |
| switch (ul_reason_for_call) { |
| case DLL_PROCESS_ATTACH: |
| #ifdef _DEBUG |
| cout << "DLL_PROCESS_ATTACH - jWinHttp" << endl; |
| #endif |
| break; |
| case DLL_THREAD_ATTACH: |
| #ifdef _DEBUG |
| cout << "DLL_THREAD_ATTACH - jWinHttp" << endl; |
| #endif |
| break; |
| case DLL_THREAD_DETACH: |
| #ifdef _DEBUG |
| cout << "DLL_THREAD_DETACH - jWinHttp" << endl; |
| #endif |
| break; |
| case DLL_PROCESS_DETACH: |
| #ifdef _DEBUG |
| cout << "DLL_PROCESS_DETACH - jWinHttp" << endl; |
| #endif |
| break; |
| } |
| return TRUE; |
| } |
| |
| |
| /* |
| * Helper for some ugly things! |
| * ............................ |
| */ |
| |
| const jchar * getStringChars( JNIEnv * env, jstring jString ) { |
| if ( jString != NULL ) { |
| return env->GetStringChars( jString, NULL ); |
| } else { |
| return NULL; |
| } |
| } |
| |
| void releaseStringChars( JNIEnv * env, jstring jString, const jchar * jCharString ) { |
| if ( jString != NULL ) { |
| env->ReleaseStringChars( jString, jCharString ); |
| } |
| } |
| |
| jobject newString( JNIEnv * env, LPWSTR string ) { |
| return env->NewString( (const jchar *)string, lstrlenW( string ) ); |
| } |
| |
| void setStringField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, LPWSTR value ) { |
| if ( value != NULL ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "Ljava/lang/String;" ); |
| env->SetObjectField( jObject, jFieldId, newString( env, value ) ); |
| GlobalFree( value ); |
| } |
| } |
| |
| jstring getStringField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "Ljava/lang/String;" ); |
| return (jstring)env->GetObjectField( jObject, jFieldId ); |
| } |
| |
| void setBooleanField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, BOOL value ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "Z" ); |
| env->SetBooleanField( jObject, jFieldId, value ); |
| } |
| |
| jboolean getBooleanField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "Z" ); |
| return env->GetBooleanField( jObject, jFieldId ); |
| } |
| |
| void setIntField( JNIEnv * env, jclass jClass, jobject jObject, const char * field, jint value ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "I" ); |
| env->SetIntField( jObject, jFieldId, value ); |
| } |
| |
| jint getIntField( JNIEnv * env, jclass jClass, jobject jObject, const char * field ) { |
| jfieldID jFieldId = env->GetFieldID( jClass, field, "I" ); |
| return env->GetIntField( jObject, jFieldId ); |
| } |
| |
| #ifdef _DEBUG |
| LPCWSTR null( const LPCWSTR string ) { |
| if ( string == NULL ) { |
| return (LPCWSTR) L"null"; |
| } else { |
| return string; |
| } |
| } |
| |
| LPWSTR null( const LPWSTR string ) { |
| if ( string == NULL ) { |
| return (LPWSTR) L"null"; |
| } else { |
| return string; |
| } |
| } |
| #endif |
| |
| /* |
| * The real ugly work goes on here! |
| * ................................ |
| */ |
| |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: open |
| * Signature: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;I)I |
| */ |
| JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_open |
| (JNIEnv * env, jclass jClass, jstring jUserAgent, jint jAccessType, jstring jProxyName, jstring jProxyBypass, jint jFlags ) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_open - entered" << endl; |
| #endif |
| |
| const jchar * userAgent = (const jchar *) L"jWinHttp Java Wrapper"; |
| const jchar * proxyName = NULL; |
| const jchar * proxyBypass = NULL; |
| |
| userAgent = getStringChars( env, jUserAgent ); |
| proxyName = getStringChars( env, jProxyName ); |
| proxyBypass = getStringChars( env, jProxyBypass ); |
| |
| CoInitialize( NULL ); // --> http://support.microsoft.com/?kbid=834742 |
| |
| int hInternet = (int) WinHttpOpen( (LPCWSTR)userAgent, jAccessType, (LPCWSTR)proxyName, (LPCWSTR)proxyBypass, jFlags ); |
| |
| if ( hInternet == NULL ) { |
| lastError = GetLastError(); |
| #ifdef _DEBUG |
| cout << "WinHttpOpen() failed with " << lastError << endl; |
| #endif |
| } else { |
| lastError = 0; |
| } |
| |
| |
| #ifdef _DEBUG |
| cout << "WinHttpOpen() returned: " << hInternet << endl; |
| #endif |
| |
| |
| releaseStringChars( env, jUserAgent, userAgent ); |
| releaseStringChars( env, jProxyName, proxyName ); |
| releaseStringChars( env, jProxyBypass, proxyBypass ); |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_open - exit" << endl; |
| #endif |
| |
| return hInternet; |
| } |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: closeHandle |
| * Signature: (I)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_closeHandle |
| (JNIEnv * env, jclass jClass, jint jInternet) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_closeHandle - entered" << endl; |
| #endif |
| |
| BOOL ok = WinHttpCloseHandle( (void *) jInternet ); |
| |
| if ( ! ok ) { |
| lastError = GetLastError(); |
| #ifdef _DEBUG |
| cout << "WinHttpClose() failed with " << lastError << endl; |
| #endif |
| } else { |
| lastError = 0; |
| } |
| |
| CoUninitialize(); |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_closeHandle - exit" << endl; |
| #endif |
| |
| return ok; |
| } |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: getIEProxyConfigForCurrentUser |
| * Signature: (Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpCurrentUserIEProxyConfig;)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getIEProxyConfigForCurrentUser |
| (JNIEnv * env, jclass jClass, jobject jWinHttpCurrentUserIEProxyConfig) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getIEProxyConfigForCurrentUser - entered" << endl; |
| #endif |
| |
| WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig; |
| ZeroMemory( &proxyConfig, sizeof( proxyConfig ) ); |
| |
| BOOL ok = WinHttpGetIEProxyConfigForCurrentUser( &proxyConfig ); |
| |
| if ( ! ok ) { |
| lastError = GetLastError(); |
| #ifdef _DEBUG |
| cout << "HttpGetIEProxyConfigForCurrentUser() failed with " << lastError << endl; |
| #endif |
| } |
| |
| if ( ok ) { |
| |
| #ifdef _DEBUG |
| cout << "proxyConfig.fAutoDetect: " << proxyConfig.fAutoDetect << endl; |
| wcout << L"proxyConfig.lpszProxy: " << null( proxyConfig.lpszProxy ) << endl; |
| wcout << L"proxyConfig.lpszProxyBypass: " << null( proxyConfig.lpszProxyBypass ) << endl; |
| #endif |
| |
| lastError = 0; |
| jclass jWinHttpCurrentUserIEProxyConfigClass = env->GetObjectClass( jWinHttpCurrentUserIEProxyConfig ); |
| setBooleanField( env,jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "isAutoDetect", proxyConfig.fAutoDetect ); |
| setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "autoConfigUrl", proxyConfig.lpszAutoConfigUrl ); |
| setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "proxy", proxyConfig.lpszProxy ); |
| setStringField( env, jWinHttpCurrentUserIEProxyConfigClass, jWinHttpCurrentUserIEProxyConfig, "proxyBypass", proxyConfig.lpszProxyBypass ); |
| } |
| |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getIEProxyConfigForCurrentUser - exit" << endl; |
| #endif |
| |
| return ok; |
| } |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: getProxyForUrl |
| * Signature: (ILjava/lang/String;Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpAutoProxyOptions;Lorg/eclipse/core/internal/net/proxy/win32/winhttp/WinHttpProxyInfo;)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getProxyForUrl |
| (JNIEnv * env, jclass jClass, jint jInternet, jstring jUrl, jobject jWinHttpAutoProxyOptions, jobject jWinHttpProxyInfo ) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getProxyForUrl - entered" << endl; |
| #endif |
| |
| WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions; |
| ZeroMemory( &autoProxyOptions, sizeof( autoProxyOptions ) ); |
| |
| jclass jWinHttpAutoProxyOptionsClass = env->GetObjectClass( jWinHttpAutoProxyOptions ); |
| |
| autoProxyOptions.dwFlags = getIntField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "flags" ); |
| autoProxyOptions.dwAutoDetectFlags = getIntField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoDetectFlags" ); |
| jstring jAutoConfigUrl = getStringField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoConfigUrl" ); |
| autoProxyOptions.lpszAutoConfigUrl = (LPCWSTR)getStringChars( env, jAutoConfigUrl ); |
| |
| // The ´reserved´ fields will not be transfered! |
| // - String reservedPointer |
| // - int reservedInt |
| |
| autoProxyOptions.fAutoLogonIfChallenged = getBooleanField( env, jWinHttpAutoProxyOptionsClass, jWinHttpAutoProxyOptions, "autoLogonIfChallenged" ); |
| |
| #ifdef _DEBUG |
| cout << "autoProxyOptions.dwFlags: " << autoProxyOptions.dwFlags << endl; |
| cout << "autoProxyOptions.dwAutoDetectFlags: " << autoProxyOptions.dwAutoDetectFlags << endl; |
| wcout << L"autoProxyOptions.lpszAutoConfigUrl: " << null( autoProxyOptions.lpszAutoConfigUrl ) << endl; |
| cout << "autoProxyOptions.fAutoLogonIfChallenged: " << autoProxyOptions.fAutoLogonIfChallenged << endl; |
| #endif |
| |
| WINHTTP_PROXY_INFO proxyInfo; |
| ZeroMemory( &proxyInfo, sizeof( proxyInfo ) ); |
| |
| const jchar * url = getStringChars( env, jUrl ); |
| |
| BOOL ok = WinHttpGetProxyForUrl( (void *)jInternet, (LPCWSTR)url, &autoProxyOptions, &proxyInfo ); |
| |
| if ( ! ok ) { |
| lastError = GetLastError(); |
| #ifdef _DEBUG |
| cout << "WinHttpGetProxyForUrl() failed with " << lastError << endl; |
| #endif |
| } |
| |
| releaseStringChars( env, jUrl, url ); |
| releaseStringChars( env, jAutoConfigUrl, (const jchar *)autoProxyOptions.lpszAutoConfigUrl ); |
| |
| if ( ok ) { |
| lastError = 0; |
| jclass jWinHttpProxyInfoClass = env->GetObjectClass( jWinHttpProxyInfo ); |
| |
| #ifdef _DEBUG |
| cout << "proxyInfo.dwAccessType: " << proxyInfo.dwAccessType << endl; |
| wcout << L"proxyInfo.lpszProxy: " << null( proxyInfo.lpszProxy ) << endl; |
| wcout << L"proxyInfo.lpszProxyBypass: " << null( proxyInfo.lpszProxyBypass ) << endl; |
| #endif |
| |
| setIntField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "accessType", proxyInfo.dwAccessType ); |
| setStringField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "proxy", proxyInfo.lpszProxy ); |
| setStringField( env, jWinHttpProxyInfoClass, jWinHttpProxyInfo, "proxyBypass", proxyInfo.lpszProxyBypass ); |
| } |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getProxyForUrl - exit" << endl; |
| #endif |
| |
| return ok; |
| } |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: detectAutoProxyConfigUrl |
| * Signature: (Lorg/eclipse/core/internal/net/proxy/win32/winhttp/AutoProxyHolder;)Z |
| */ |
| JNIEXPORT jboolean JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_detectAutoProxyConfigUrl |
| (JNIEnv * env, jclass jClass, jobject jAutoProxyHolder) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_detectAutoProxyConfigUrl - entered" << endl; |
| #endif |
| |
| jclass jAutoProxyHolderClass = env->GetObjectClass( jAutoProxyHolder ); |
| DWORD dwAutoDetectFlags = getIntField( env, jAutoProxyHolderClass, jAutoProxyHolder, "autoDetectFlags" ); |
| |
| #ifdef _DEBUG |
| cout << "autoProxyHolder.autoDetectFlags: " << dwAutoDetectFlags << endl; |
| #endif |
| |
| LPWSTR pwszAutoConfigUrl; |
| |
| BOOL ok = WinHttpDetectAutoProxyConfigUrl( dwAutoDetectFlags, &pwszAutoConfigUrl ); |
| |
| if ( ! ok ) { |
| lastError = GetLastError(); |
| #ifdef _DEBUG |
| cout << "WinHttpDetectAutoProxyConfigUrl() failed with " << lastError << endl; |
| #endif |
| } |
| |
| if ( ok ) { |
| lastError = 0; |
| |
| #ifdef _DEBUG |
| wcout << L"autoConfigUrl: " << null( pwszAutoConfigUrl ) << endl; |
| #endif |
| |
| setStringField( env, jAutoProxyHolderClass, jAutoProxyHolder, "autoConfigUrl", pwszAutoConfigUrl ); |
| } |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_detectAutoProxyConfigUrl - exit" << endl; |
| #endif |
| |
| return ok; |
| } |
| |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: getLastError |
| * Signature: ()I |
| */ |
| JNIEXPORT jint JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getLastError |
| (JNIEnv * env, jclass jClass) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getLastError - entered" << endl; |
| #endif |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getLastError - exit" << endl; |
| #endif |
| |
| return lastError; |
| } |
| |
| /* |
| * Class: org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp |
| * Method: getLastErrorMessage |
| * Signature: ()Ljava/lang/String; |
| */ |
| JNIEXPORT jstring JNICALL Java_org_eclipse_core_internal_net_proxy_win32_winhttp_WinHttp_getLastErrorMessage |
| (JNIEnv * env, jclass jClass) { |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getLastErrorMessage - entered" << endl; |
| #endif |
| |
| LPVOID lpMsgBuf = NULL; |
| DWORD result = 0; |
| |
| if ( lastError >= WINHTTP_ERROR_BASE && lastError <= WINHTTP_ERROR_LAST ) { |
| HMODULE hModule = GetModuleHandle( "winhttp.dll" ); |
| |
| if ( hModule == NULL ) { |
| lpMsgBuf = "Could not retrieve error message, because ´GetModuleHandle( \"winhttp.dll\" )´ failed."; |
| } else { |
| result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| FORMAT_MESSAGE_FROM_HMODULE | |
| FORMAT_MESSAGE_IGNORE_INSERTS, |
| hModule, |
| lastError, |
| MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language |
| (LPTSTR) &lpMsgBuf, |
| 0, |
| NULL ); |
| } |
| |
| } else { |
| result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| FORMAT_MESSAGE_FROM_SYSTEM | |
| FORMAT_MESSAGE_IGNORE_INSERTS, |
| NULL, |
| lastError, |
| MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // Default language |
| (LPTSTR) &lpMsgBuf, |
| 0, |
| NULL ); |
| } |
| |
| if ( lpMsgBuf == NULL ) { |
| #ifdef _DEBUG |
| cout << "WinHttp_getLastErrorMessage() failed with " << GetLastError() << " for error code " << lastError << endl; |
| #endif |
| |
| lpMsgBuf = "Could not retrieve error message."; |
| } |
| |
| jstring string = env->NewStringUTF( (char *) lpMsgBuf ); |
| |
| if ( result > 0 ) { |
| // Free dynamically allocated buffer |
| LocalFree( lpMsgBuf ); |
| } |
| |
| #ifdef _DEBUG |
| cout << "WinHttp_getLastErrorMessage - exit" << endl; |
| #endif |
| |
| return string; |
| } |
| |