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