src/platform_windows.cpp
author vb
Wed, 25 Jun 2014 18:44:58 +0200
changeset 0 16f27efbef98
child 8 26cc9f0228f4
permissions -rw-r--r--
initial commit
vb@0
     1
// Windows platform specifica
vb@0
     2
vb@0
     3
#define WIN32_LEAN_AND_MEAN
vb@0
     4
#ifndef UNICODE
vb@0
     5
#define UNICODE
vb@0
     6
#endif
vb@0
     7
#define _WIN32_WINNT 0x0600
vb@0
     8
vb@0
     9
#include <windows.h>
vb@0
    10
#include <assert.h>
vb@0
    11
#include <string>
vb@0
    12
#include <stdexcept>
vb@0
    13
#include "platform_windows.h"
vb@0
    14
vb@0
    15
#ifndef WC_ERR_INVALID_CHARS
vb@0
    16
#define WC_ERR_INVALID_CHARS      0x00000080  // error for invalid chars
vb@0
    17
#endif
vb@0
    18
vb@0
    19
using namespace std;
vb@0
    20
vb@0
    21
static string utf8_string(wstring wstr) {
vb@0
    22
    string result;
vb@0
    23
vb@0
    24
    if (wstr.length()) {
vb@0
    25
        int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
vb@0
    26
                wstr.c_str(), -1, NULL, 0, NULL, NULL);
vb@0
    27
        assert(size);
vb@0
    28
        if (size) {
vb@0
    29
            char *buf = new char[size];
vb@0
    30
            WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wstr.c_str(),
vb@0
    31
                    -1, buf, size, NULL, NULL);
vb@0
    32
            result = buf;
vb@0
    33
            delete[] buf;
vb@0
    34
        } else
vb@0
    35
            throw out_of_range("input wstring is not valid"
vb@0
    36
                    " while converting UTF-16 to UTF-8.");
vb@0
    37
    }
vb@0
    38
vb@0
    39
    return result;
vb@0
    40
}
vb@0
    41
vb@0
    42
static wstring utf16_string(string str) {
vb@0
    43
    wstring result;
vb@0
    44
vb@0
    45
    if (str.length()) {
vb@0
    46
        int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
vb@0
    47
                str.c_str(), -1, NULL, 0);
vb@0
    48
        assert(size);
vb@0
    49
        if (size) {
vb@0
    50
            wchar_t * buf = new wchar_t[size];
vb@0
    51
            MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), -1,
vb@0
    52
                    buf, size);
vb@0
    53
            result = buf;
vb@0
    54
            delete[] buf;
vb@0
    55
        } else
vb@0
    56
            throw out_of_range("input string is not valid"
vb@0
    57
                    " while converting UTF-8 to UTF-16.");
vb@0
    58
    }
vb@0
    59
vb@0
    60
    return result;
vb@0
    61
}
vb@0
    62
vb@0
    63
static bool readRegistryString(
vb@0
    64
        HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPTSTR lpResult,
vb@0
    65
        DWORD dwSize, LPCTSTR lpDefault
vb@0
    66
    )
vb@0
    67
{
vb@0
    68
    assert(lpResult);
vb@0
    69
vb@0
    70
	HKEY theKey;
vb@0
    71
	DWORD type;
vb@0
    72
	DWORD bytesCopied = dwSize;
vb@0
    73
	HRESULT result;
vb@0
    74
vb@0
    75
	result = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &theKey);
vb@0
    76
	if (result != ERROR_SUCCESS) {
vb@0
    77
		if (lpDefault) {
vb@0
    78
			wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
vb@0
    79
			return true;
vb@0
    80
		}
vb@0
    81
		else
vb@0
    82
			return false;
vb@0
    83
	}
vb@0
    84
vb@0
    85
	result = RegQueryValueEx(theKey, lpValueName, NULL, &type,
vb@0
    86
            (LPBYTE) lpResult, &bytesCopied);
vb@0
    87
    if (result != ERROR_SUCCESS || (type != REG_EXPAND_SZ && type != REG_SZ)) {
vb@0
    88
		if (lpDefault) {
vb@0
    89
			wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
vb@0
    90
			RegCloseKey(theKey);
vb@0
    91
			return true;
vb@0
    92
		}
vb@0
    93
		else {
vb@0
    94
			RegCloseKey(theKey);
vb@0
    95
			return false;
vb@0
    96
		}
vb@0
    97
	}
vb@0
    98
vb@0
    99
	RegCloseKey(theKey);
vb@0
   100
	return true;
vb@0
   101
}
vb@0
   102
vb@0
   103
static const DWORD PATH_BUF_SIZE = 32768;
vb@0
   104
vb@0
   105
static inline string managementPath(const char *file_path, const char *file_name)
vb@0
   106
{
vb@0
   107
    string path;
vb@0
   108
	static TCHAR tPath[PATH_BUF_SIZE];
vb@0
   109
vb@0
   110
    DWORD length = ExpandEnvironmentStringsW(utf16_string(file_path).c_str(),
vb@0
   111
            tPath, PATH_BUF_SIZE);
vb@0
   112
	assert(length);
vb@0
   113
    if (length == 0)
vb@0
   114
        throw bad_alloc();
vb@0
   115
vb@0
   116
	CreateDirectory(tPath, NULL);
vb@0
   117
	DWORD error = GetLastError();
vb@0
   118
	assert(error == 0 || error == ERROR_ALREADY_EXISTS);
vb@0
   119
vb@0
   120
	path = utf8_string(tPath);
vb@0
   121
	path += "\\";
vb@0
   122
	path += file_name;
vb@0
   123
vb@0
   124
	return path;
vb@0
   125
}
vb@0
   126
vb@0
   127
extern "C" {
vb@0
   128
vb@0
   129
void *dlopen(const char *filename, int flag) {
vb@0
   130
	static TCHAR path[PATH_BUF_SIZE];
vb@0
   131
vb@0
   132
    assert(filename);
vb@0
   133
	assert(flag == RTLD_LAZY); // only lazy binding is implemented
vb@0
   134
vb@0
   135
    bool result = readRegistryString(HKEY_LOCAL_MACHINE,
vb@0
   136
            TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
vb@0
   137
            PATH_BUF_SIZE, NULL);
vb@0
   138
	assert(result);
vb@0
   139
	if (!result)
vb@0
   140
		return NULL;
vb@0
   141
vb@0
   142
    SetDllDirectory(TEXT(""));
vb@0
   143
    BOOL _result = SetDllDirectory(path);
vb@0
   144
    assert(_result != 0);
vb@0
   145
    if (_result == 0)
vb@0
   146
        return NULL;
vb@0
   147
vb@0
   148
	HMODULE module = LoadLibrary(utf16_string(filename).c_str());
vb@0
   149
    SetDllDirectory(NULL);
vb@0
   150
	if (module == NULL)
vb@0
   151
		return NULL;
vb@0
   152
	else
vb@0
   153
		return (void *) module;
vb@0
   154
}
vb@0
   155
vb@0
   156
int dlclose(void *handle) {
vb@0
   157
	if (FreeLibrary((HMODULE) handle))
vb@0
   158
		return 0;
vb@0
   159
	else
vb@0
   160
		return 1;
vb@0
   161
}
vb@0
   162
vb@0
   163
void *dlsym(void *handle, const char *symbol) {
vb@0
   164
	return (void *) (intptr_t) GetProcAddress((HMODULE) handle, symbol);
vb@0
   165
}
vb@0
   166
vb@0
   167
const char *windoze_local_db() {
vb@0
   168
	static string path;
vb@0
   169
	if (path.length() == 0)
vb@0
   170
        path = managementPath("%LOCALAPPDATA%\\pEp", "management.db");
vb@0
   171
    return path.c_str();
vb@0
   172
}
vb@0
   173
vb@0
   174
const char *windoze_system_db() {
vb@0
   175
	static string path;
vb@0
   176
	if (path.length() == 0)
vb@0
   177
		path = managementPath("%ALLUSERSPROFILE%\\pEp", "system.db");
vb@0
   178
    return path.c_str();
vb@0
   179
}
vb@0
   180
vb@0
   181
const char *gpg_conf()
vb@0
   182
{
vb@0
   183
    static string path;
vb@0
   184
    if (path.length() == 0)
vb@0
   185
        path = managementPath("%APPDATA%\\gnupg", "gpg.conf");
vb@0
   186
    return path.c_str();
vb@0
   187
}
vb@0
   188
vb@0
   189
} // "C"