2012年10月8日 星期一

Use Macro to dynamically load wininet.dll


#ifndef WININETMANAGER_H
#define WININETMANAGER_H

#include <WinInet.h>


#define DECLARE_FUNCTION(functionName, resultType, callingConvention, parameterDeclarations) \
    static resultType functionName parameterDeclarations ;

#define DEFINE_FUNCTION(functionName, resultType, callingConvention, parameterDeclarations, parameterNames) \
    resultType WinInetManager::##functionName parameterDeclarations \
    {\
    resultType (callingConvention*softLink##functionName) parameterDeclarations; \
    softLink##functionName = reinterpret_cast<resultType (callingConvention*) parameterDeclarations>(GetProcAddress(WinInetManager::instance().getDllHandle(), L#functionName)); \
    return softLink##functionName parameterNames; \
    }

namespace WebCore
{

class String;

class WinInetManager
{
public:  

    static WinInetManager& instance();  

    HRESULT freeLibrary();

    const HMODULE& getDllHandle();

    HRESULT setCookieCacheFolder(const String& location);

    HRESULT setCookieCacheFullPath(const String& path);

    HRESULT cacheReserveSize(DWORD *size);

    HRESULT setCacheReserveSize(DWORD size);

    ~WinInetManager();  

    DECLARE_FUNCTION(InternetOpenUrlW,HINTERNET ,WINAPI, (HINTERNET hInternet,LPCWSTR lpszUrl,LPCWSTR lpszHeaders,DWORD dwHeadersLength,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(InternetCloseHandle, BOOL, WINAPI, (HINTERNET hInternet))
    DECLARE_FUNCTION(DeleteUrlCacheEntryW,BOOL,WINAPI, (LPCWSTR lpszUrlName))
    DECLARE_FUNCTION(InternetSetStatusCallbackW, INTERNET_STATUS_CALLBACK, WINAPI, (HINTERNET hInternet,INTERNET_STATUS_CALLBACK lpfnInternetCallback))
    DECLARE_FUNCTION(InternetGetLastResponseInfoW, BOOL, WINAPI, (LPDWORD lpdwError,LPWSTR lpszBuffer,LPDWORD lpdwBufferLength))
    DECLARE_FUNCTION(InternetErrorDlg, DWORD, WINAPI, (HWND hWnd,HINTERNET hRequest,DWORD dwError,DWORD dwFlags,LPVOID * lppvData))
    DECLARE_FUNCTION(InternetReadFileExA, BOOL, WINAPI, (HINTERNET hFile,LPINTERNET_BUFFERSA lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(InternetWriteFile, BOOL, WINAPI, (HINTERNET hFile,LPCVOID lpBuffer,DWORD dwNumberOfBytesToWrite,LPDWORD lpdwNumberOfBytesWritten))
    DECLARE_FUNCTION(InternetConnectW, HINTERNET, WINAPI, (HINTERNET hInternet,LPCWSTR lpszServerName,INTERNET_PORT nServerPort,LPCWSTR lpszUserName,LPCWSTR lpszPassword,DWORD dwService,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(HttpOpenRequestW, HINTERNET, WINAPI, (HINTERNET hConnect,LPCWSTR lpszVerb,LPCWSTR lpszObjectName,LPCWSTR lpszVersion,LPCWSTR lpszReferrer,LPCWSTR FAR * lplpszAcceptTypes,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(HttpSendRequestExW, BOOL, WINAPI, (HINTERNET hRequest,LPINTERNET_BUFFERSW lpBuffersIn,LPINTERNET_BUFFERSW lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(HttpEndRequestW, BOOL, WINAPI, (HINTERNET hRequest,LPINTERNET_BUFFERSW lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext))
    DECLARE_FUNCTION(ResumeSuspendedDownload, BOOL, WINAPI, (HINTERNET hRequest,DWORD dwResultCode))
    DECLARE_FUNCTION(HttpQueryInfoW, BOOL, WINAPI, (HINTERNET hRequest,DWORD dwInfoLevel,LPVOID lpBuffer,LPDWORD lpdwBufferLength,LPDWORD lpdwIndex))
    DECLARE_FUNCTION(InternetOpenW, HINTERNET, WINAPI, (LPCWSTR lpszAgent,DWORD dwAccessType,LPCWSTR lpszProxy,LPCWSTR lpszProxyBypass,DWORD dwFlags))
    DECLARE_FUNCTION(InternetQueryOptionW, BOOL, WINAPI, (HINTERNET hInternet,DWORD dwOption,LPVOID lpBuffer,LPDWORD lpdwBufferLength))
    DECLARE_FUNCTION(InternetSetOptionW, BOOL, WINAPI, (HINTERNET hInternet,DWORD dwOption,LPVOID lpBuffer,DWORD dwBufferLength))
    DECLARE_FUNCTION(InternetSetCookieW,BOOL,WINAPI, (LPCWSTR lpszUrl,LPCWSTR lpszCookieName,LPCWSTR lpszCookieData))
    DECLARE_FUNCTION(InternetGetCookieW,BOOL,WINAPI, (LPCWSTR lpszUrl,LPCWSTR lpszCookieName,LPCWSTR lpszCookieData,LPDWORD lpdwSize))
    DECLARE_FUNCTION(FindFirstUrlCacheEntryW,HINTERNET,WINAPI, (LPCWSTR lpszUrlSearchPattern,LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,LPDWORD lpcbCacheEntryInfo))
    DECLARE_FUNCTION(FindNextUrlCacheEntryW,BOOL,WINAPI, (HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,LPDWORD lpcbCacheEntryInfo))
    DECLARE_FUNCTION(GetUrlCacheEntryInfoW,BOOL,WINAPI, (LPCWSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpcbCacheEntryInfo))

private:
    HRESULT setUserName(const String& name);
    HRESULT setCookieDirectory(HKEY key, const String& dir);
    HRESULT setCacheDirectory(HKEY key, const String& dir);
    HRESULT setHistoryDirectory(HKEY key, const String& dir);

    WinInetManager();

private:      
    HMODULE m_module;  
};

}

#endif //WININETMANAGER_H


#include "config.h"
#include "WinInetManager.h"

#include "FileSystem.h"
#include "WTFString.h"

namespace WebCore
{

static const WCHAR* const WININET_DLL_NAME = L"wininet.dll";
static const WCHAR* const REGISTRY_SHELL_FOLDERS = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
static const WCHAR* const BASE_DIRECTORY = L"\\Windows\\Profiles\\";
static const WCHAR* const TEMP_FILE_DIRECTORY = L"\\Temporary Internet Files";
static const WCHAR* const COOKIE_DIRECTORY = L"\\Cookies";
static const WCHAR* const HISTORY_DIRECTORY = L"\\History";
static const WCHAR* const KEY_USER_NAME = L"Username";
static const WCHAR* const KEY_CACHE = L"Cache";
static const WCHAR* const KEY_COOKIE = L"Cookies";
static const WCHAR* const KEY_HISTORY = L"History";
static const WCHAR* const KEY_IDENT = L"Ident";
static const WCHAR* const REGISTRY_CACHE_CONTENT = L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\5.0\\Cache\\Content";
static const WCHAR* const KEY_CACHE_LIMIT = L"CacheLimit";
static const WCHAR* const PATH_SEPARATOR = L"\\";


DEFINE_FUNCTION(InternetOpenUrlW,HINTERNET ,WINAPI, (HINTERNET hInternet,LPCWSTR lpszUrl,LPCWSTR lpszHeaders,DWORD dwHeadersLength,DWORD dwFlags,DWORD_PTR dwContext), (hInternet,lpszUrl,lpszHeaders,dwHeadersLength,dwFlags,dwContext))
DEFINE_FUNCTION(InternetCloseHandle, BOOL, WINAPI, (HINTERNET hInternet), (hInternet))
DEFINE_FUNCTION(InternetSetStatusCallbackW, INTERNET_STATUS_CALLBACK, WINAPI, (HINTERNET hInternet,INTERNET_STATUS_CALLBACK lpfnInternetCallback),(hInternet,lpfnInternetCallback))
DEFINE_FUNCTION(InternetGetLastResponseInfoW, BOOL, WINAPI, (LPDWORD lpdwError,LPWSTR lpszBuffer,LPDWORD lpdwBufferLength), (lpdwError,lpszBuffer,lpdwBufferLength))
DEFINE_FUNCTION(InternetErrorDlg, DWORD, WINAPI, (HWND hWnd,HINTERNET hRequest,DWORD dwError,DWORD dwFlags,LPVOID * lppvData), (hWnd,hRequest,dwError,dwFlags,lppvData))
DEFINE_FUNCTION(InternetReadFileExA, BOOL, WINAPI, (HINTERNET hFile,LPINTERNET_BUFFERSA lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext), (hFile,lpBuffersOut,dwFlags,dwContext))
DEFINE_FUNCTION(InternetWriteFile, BOOL, WINAPI, (HINTERNET hFile,LPCVOID lpBuffer,DWORD dwNumberOfBytesToWrite,LPDWORD lpdwNumberOfBytesWritten), (hFile,lpBuffer,dwNumberOfBytesToWrite,lpdwNumberOfBytesWritten))
DEFINE_FUNCTION(InternetConnectW, HINTERNET, WINAPI, (HINTERNET hInternet,LPCWSTR lpszServerName,INTERNET_PORT nServerPort,LPCWSTR lpszUserName,LPCWSTR lpszPassword,DWORD dwService,DWORD dwFlags,DWORD_PTR dwContext), (hInternet,lpszServerName,nServerPort,lpszUserName,lpszPassword,dwService,dwFlags,dwContext))
DEFINE_FUNCTION(HttpOpenRequestW, HINTERNET, WINAPI, (HINTERNET hConnect,LPCWSTR lpszVerb,LPCWSTR lpszObjectName,LPCWSTR lpszVersion,LPCWSTR lpszReferrer,LPCWSTR FAR * lplpszAcceptTypes,DWORD dwFlags,DWORD_PTR dwContext), (hConnect,lpszVerb,lpszObjectName,lpszVersion,lpszReferrer,lplpszAcceptTypes,dwFlags,dwContext))
DEFINE_FUNCTION(HttpSendRequestExW, BOOL, WINAPI, (HINTERNET hRequest,LPINTERNET_BUFFERSW lpBuffersIn,LPINTERNET_BUFFERSW lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext), (hRequest,lpBuffersIn,lpBuffersOut,dwFlags,dwContext))
DEFINE_FUNCTION(HttpEndRequestW, BOOL, WINAPI, (HINTERNET hRequest,LPINTERNET_BUFFERSW lpBuffersOut,DWORD dwFlags,DWORD_PTR dwContext), (hRequest,lpBuffersOut,dwFlags,dwContext))
DEFINE_FUNCTION(ResumeSuspendedDownload, BOOL, WINAPI, (HINTERNET hRequest,DWORD dwResultCode),(hRequest,dwResultCode))
DEFINE_FUNCTION(HttpQueryInfoW, BOOL, WINAPI, (HINTERNET hRequest,DWORD dwInfoLevel,LPVOID lpBuffer,LPDWORD lpdwBufferLength,LPDWORD lpdwIndex),(hRequest,dwInfoLevel,lpBuffer,lpdwBufferLength,lpdwIndex))
DEFINE_FUNCTION(InternetOpenW, HINTERNET, WINAPI, (LPCWSTR lpszAgent,DWORD dwAccessType,LPCWSTR lpszProxy,LPCWSTR lpszProxyBypass,DWORD dwFlags),(lpszAgent,dwAccessType,lpszProxy,lpszProxyBypass,dwFlags))
DEFINE_FUNCTION(InternetQueryOptionW, BOOL, WINAPI, (HINTERNET hInternet,DWORD dwOption,LPVOID lpBuffer,LPDWORD lpdwBufferLength),(hInternet,dwOption,lpBuffer,lpdwBufferLength))
DEFINE_FUNCTION(InternetSetOptionW, BOOL, WINAPI, (HINTERNET hInternet,DWORD dwOption,LPVOID lpBuffer,DWORD dwBufferLength),(hInternet,dwOption,lpBuffer,dwBufferLength))
DEFINE_FUNCTION(InternetSetCookieW,BOOL,WINAPI, (LPCWSTR lpszUrl,LPCWSTR lpszCookieName,LPCWSTR lpszCookieData), (lpszUrl,lpszCookieName,lpszCookieData))
DEFINE_FUNCTION(InternetGetCookieW,BOOL,WINAPI, (LPCWSTR lpszUrl,LPCWSTR lpszCookieName,LPCWSTR lpszCookieData,LPDWORD lpdwSize), (lpszUrl,lpszCookieName,lpszCookieData,lpdwSize))
DEFINE_FUNCTION(DeleteUrlCacheEntryW,BOOL,WINAPI, (LPCWSTR lpszUrlName), (lpszUrlName))
DEFINE_FUNCTION(FindFirstUrlCacheEntryW,HINTERNET,WINAPI,  (LPCWSTR lpszUrlSearchPattern,LPINTERNET_CACHE_ENTRY_INFOW lpFirstCacheEntryInfo,LPDWORD lpcbCacheEntryInfo), (lpszUrlSearchPattern,lpFirstCacheEntryInfo,lpcbCacheEntryInfo))
DEFINE_FUNCTION(FindNextUrlCacheEntryW,BOOL,WINAPI, (HANDLE hEnumHandle,LPINTERNET_CACHE_ENTRY_INFOW lpNextCacheEntryInfo,LPDWORD lpcbCacheEntryInfo), (hEnumHandle,lpNextCacheEntryInfo,lpcbCacheEntryInfo))
DEFINE_FUNCTION(GetUrlCacheEntryInfoW,BOOL,WINAPI, (LPCWSTR lpszUrlName,LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,LPDWORD lpcbCacheEntryInfo), (lpszUrlName,lpCacheEntryInfo,lpcbCacheEntryInfo))

WinInetManager::WinInetManager()
:m_module(NULL)
{
}

WinInetManager::~WinInetManager()
{
}


WinInetManager& WinInetManager::instance()
{
    static WinInetManager manager;
    return manager;
}

HRESULT WinInetManager::freeLibrary()
{  
    HMODULE hModule = ::GetModuleHandle(WININET_DLL_NAME);
   
    ///Strange! I just called the LoadLibrary("wininet.dll") one time.
    ///But I cann't really free the library until call the FreeLibrary three times.
    int leftTimes = 20;
    while (hModule != NULL && leftTimes > 0)
    {
        ::FreeLibrary(hModule);
        hModule = ::GetModuleHandle(WININET_DLL_NAME);
        -- leftTimes;
    }  

    HRESULT res = S_OK;
    if (hModule != NULL)
    {
        DEBUGMSG(0, (L"WinInetManager::freeLibrary  Failed \n"));
        res = S_FALSE;
    }
    m_module = NULL;
    return res;  
}


const HMODULE& WinInetManager::getDllHandle()
{  
    if(NULL == m_module)
    {
        m_module = ::LoadLibraryW(WININET_DLL_NAME);
    }
    return m_module;
}

static bool makeDirectory(const String& location)
{
    String path(BASE_DIRECTORY);
    path.append(location);    
    return makeAllDirectories(path);
}

static HRESULT setStringValue(HKEY hKey, const String& key, const String& value)
{
    String tempKey = key;
    String tempValue = value;

    int valueSize = value.length() * sizeof(TCHAR);
    const BYTE* valueStr =  (const BYTE*)tempValue.charactersWithNullTermination();
   

    HRESULT result = RegSetValueEx(hKey, tempKey.charactersWithNullTermination(), 0, REG_SZ, valueStr, valueSize);

    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager setStringValue error \n"));
    }
    return result;
}

static HRESULT setIntegerValue(HKEY hKey, const String& key, const DWORD& value)
{
    String tempKey = key;

    HRESULT result = HRESULT_FROM_WIN32(RegSetValueEx(hKey, tempKey.charactersWithNullTermination(), 0, REG_DWORD, (BYTE*)(&value), sizeof(value)));
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager setIntegerValue error \n"));
    }
    return result;
}

static HRESULT integerValueForKey(HKEY hKey, const String& key, DWORD* value)
{
    String tempKey = key;
    DWORD dwData = 0;
    DWORD dwSize = sizeof(DWORD);

    HRESULT result = E_FAIL;
    if(ERROR_SUCCESS == RegQueryValueEx(hKey, tempKey.charactersWithNullTermination(), NULL, NULL, (BYTE*)(&dwData), &dwSize))
    {
        *value = dwData;
        result = S_OK;
    }
    else
        DEBUGMSG(result, (L"WinInetManager integerValueForKey error \n"));

    return result;
}

HRESULT WinInetManager::setCookieCacheFolder(const String& location)
{
    if (!makeDirectory(location))
    {
        DEBUGMSG(0, (L"WinInetManager::setCookieCacheFolder  makeDirectory error \n"));
        return E_INVALIDARG;
    }

    LONG result = setUserName(location);
    if(FAILED(result))
    {
        DEBUGMSG(0, (L"WinInetManager::setCookieCacheFolder  setUserName error \n"));
        return result;
    }

    HKEY hKey = NULL;
    result = RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_SHELL_FOLDERS, 0, KEY_WRITE, &hKey);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCookieCacheFolder   RegOpenKeyEx error \n"));
        return result;
    }

    result = setCacheDirectory(hKey, location);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCookieCacheFolder  setCacheDirectory error \n"));      
        return result;
    }
   
    result = setCookieDirectory(hKey, location);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCookieCacheFolder setCookieDirectory error \n"));      
        return result;
    }

    result = setHistoryDirectory(hKey, location);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCookieCacheFolder setHistoryDirectory error \n"));      
        return result;
    }  

    return RegCloseKey(hKey);
}

static HRESULT setDirectoryValue(HKEY hKey, const String& key, const String& basePath, const String& subPath)
{
   if(basePath.endsWith(PATH_SEPARATOR))
   {
        return S_FALSE;
   }
 
   return setStringValue(hKey, key, basePath + subPath);
}

HRESULT WinInetManager::setCookieCacheFullPath(const String& path)
{
    if (!makeAllDirectories(path))
    {
        DEBUGMSG(1, (L"WinInetManager::setCookieCacheFullPath  makeAllDirectories error \n"));
        return E_FAIL;
    }

    HKEY hKey = NULL;
    LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_SHELL_FOLDERS, 0, KEY_WRITE, &hKey);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCookieCacheFullPath   RegOpenKeyEx error \n"));
        return result;
    }  

    result = setDirectoryValue(hKey, KEY_CACHE, path, TEMP_FILE_DIRECTORY);
    if(FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setDirectoryValue TEMP_FILE_DIRECTORY error \n"));      
        goto FAIL;
    }

    result = setDirectoryValue(hKey, KEY_COOKIE, path, COOKIE_DIRECTORY);
    if(FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setDirectoryValue COOKIE_DIRECTORY error \n"));      
        goto FAIL;
    }

    result = setDirectoryValue(hKey, KEY_HISTORY, path, HISTORY_DIRECTORY);
    if(FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setDirectoryValue HISTORY_DIRECTORY error \n"));      
        goto FAIL;
    }

FAIL:
    RegCloseKey(hKey);
    return result;
}

HRESULT WinInetManager::setUserName(const String& name)
{
    HKEY hKey;
    HRESULT result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_IDENT, 0, KEY_WRITE, &hKey);
    if(FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setUserName  RegOpenKeyEx error \n"));
        return result;
    }

    String key(KEY_USER_NAME);      
    if (FAILED(setStringValue(hKey, key, name)))
    {
        DEBUGMSG(result, (L"WinInetManager::setUserName  setStringValue error \n"));
        return result;
    }

    return RegCloseKey(hKey);
}

HRESULT WinInetManager::setCacheDirectory(HKEY hKey, const String& location)
{
    // change Cache directory  
    String value(BASE_DIRECTORY);
    value = value + location +  TEMP_FILE_DIRECTORY;
    return setStringValue(hKey, KEY_CACHE, value);      
}

HRESULT WinInetManager::setCookieDirectory(HKEY hKey, const String& location)
{
    // change cookies directory  
    String value(BASE_DIRECTORY);
    value = value + location + COOKIE_DIRECTORY;
    return setStringValue(hKey, KEY_COOKIE, value);  
}

HRESULT WinInetManager::setHistoryDirectory(HKEY hKey, const String& location)
{
    // change history directory
    String value(BASE_DIRECTORY);
    value = value + location + HISTORY_DIRECTORY;
    return setStringValue(hKey, KEY_HISTORY, value);
}

HRESULT WinInetManager::cacheReserveSize(DWORD *size)
{
    HKEY hKey = NULL;
    HRESULT result =  E_FAIL;
    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_CACHE_CONTENT, 0, KEY_READ, &hKey))
    {
        DEBUGMSG(result, (L"WinInetManager::cacheReserveSize   RegOpenKeyEx error \n"));
        return result;
    }

    String key(KEY_CACHE_LIMIT);
    DWORD regSize = 0;
    result = integerValueForKey(hKey, key, &regSize);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::cacheReserveSize  integerValueForKey error \n"));
        *size = 0;
    }
    else
        *size = regSize * 1024;

    RegCloseKey(hKey);
    return S_OK;
}

HRESULT WinInetManager::setCacheReserveSize(DWORD size)
{
    HKEY hKey = NULL;
    HRESULT result = E_FAIL;
    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_CURRENT_USER, REGISTRY_CACHE_CONTENT, 0, KEY_WRITE, &hKey))
    {
        DEBUGMSG(result, (L"WinInetManager::setCacheReserveSize   RegOpenKeyEx error \n"));
        return result;
    }

    String key(KEY_CACHE_LIMIT);
    result = setIntegerValue(hKey, key, size/1024);
    if (FAILED(result))
    {
        DEBUGMSG(result, (L"WinInetManager::setCacheReserveSize  setIntegerValue error \n"));
    }
   
    RegCloseKey(hKey);
    return result;
}

}


沒有留言:

張貼留言