src/platform_windows.cpp
author Volker Birk <vb@pep-project.org>
Thu, 26 Mar 2015 15:30:21 +0100
changeset 130 507895068f83
parent 107 fbef1c59da96
child 140 7abc23dbfdfe
permissions -rw-r--r--
modifications for Windoze
     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 #define _CRT_RAND_S
    11 #include <stdlib.h>
    12 #include <assert.h>
    13 #include <string.h>
    14 #include <string>
    15 #include <stdexcept>
    16 #include "platform_windows.h"
    17 #include <fcntl.h>
    18 #include <sys\stat.h>
    19 
    20 #ifndef WC_ERR_INVALID_CHARS
    21 #define WC_ERR_INVALID_CHARS      0x00000080  // error for invalid chars
    22 #endif
    23 
    24 using namespace std;
    25 
    26 static string utf8_string(wstring wstr) {
    27     string result;
    28 
    29     if (wstr.length()) {
    30         int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
    31                 wstr.c_str(), -1, NULL, 0, NULL, NULL);
    32         assert(size);
    33         if (size) {
    34             char *buf = new char[size];
    35             WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wstr.c_str(),
    36                     -1, buf, size, NULL, NULL);
    37             result = buf;
    38             delete[] buf;
    39         } else
    40             throw out_of_range("input wstring is not valid"
    41                     " while converting UTF-16 to UTF-8.");
    42     }
    43 
    44     return result;
    45 }
    46 
    47 static wstring utf16_string(string str) {
    48     wstring result;
    49 
    50     if (str.length()) {
    51         int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
    52                 str.c_str(), -1, NULL, 0);
    53         assert(size);
    54         if (size) {
    55             wchar_t * buf = new wchar_t[size];
    56             MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), -1,
    57                     buf, size);
    58             result = buf;
    59             delete[] buf;
    60         } else
    61             throw out_of_range("input string is not valid"
    62                     " while converting UTF-8 to UTF-16.");
    63     }
    64 
    65     return result;
    66 }
    67 
    68 static bool readRegistryString(
    69         HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPTSTR lpResult,
    70         DWORD dwSize, LPCTSTR lpDefault
    71     )
    72 {
    73     assert(lpResult);
    74 
    75 	HKEY theKey;
    76 	DWORD type;
    77 	DWORD bytesCopied = dwSize;
    78 	HRESULT result;
    79 
    80 	result = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &theKey);
    81 	if (result != ERROR_SUCCESS) {
    82 		if (lpDefault) {
    83 			wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
    84 			return true;
    85 		}
    86 		else
    87 			return false;
    88 	}
    89 
    90 	result = RegQueryValueEx(theKey, lpValueName, NULL, &type,
    91             (LPBYTE) lpResult, &bytesCopied);
    92     if (result != ERROR_SUCCESS || (type != REG_EXPAND_SZ && type != REG_SZ)) {
    93 		if (lpDefault) {
    94 			wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
    95 			RegCloseKey(theKey);
    96 			return true;
    97 		}
    98 		else {
    99 			RegCloseKey(theKey);
   100 			return false;
   101 		}
   102 	}
   103 
   104 	RegCloseKey(theKey);
   105 	return true;
   106 }
   107 
   108 static const DWORD PATH_BUF_SIZE = 32768;
   109 
   110 static inline string managementPath(const char *file_path, const char *file_name)
   111 {
   112     string path;
   113 	static TCHAR tPath[PATH_BUF_SIZE];
   114 
   115     DWORD length = ExpandEnvironmentStringsW(utf16_string(file_path).c_str(),
   116             tPath, PATH_BUF_SIZE);
   117 	assert(length);
   118     if (length == 0)
   119         throw bad_alloc(); // BUG: there are other errors possible beside out of memory
   120 
   121 	CreateDirectory(tPath, NULL);
   122 	DWORD error = GetLastError();
   123 	assert(error == 0 || error == ERROR_ALREADY_EXISTS);
   124 
   125 	path = utf8_string(tPath);
   126 	path += "\\";
   127 	path += file_name;
   128 
   129 	return path;
   130 }
   131 
   132 extern "C" {
   133 
   134 void *dlopen(const char *filename, int flag) {
   135 	static TCHAR path[PATH_BUF_SIZE];
   136 
   137     assert(filename);
   138 	assert(flag == RTLD_LAZY); // only lazy binding is implemented
   139 
   140     bool result = readRegistryString(HKEY_LOCAL_MACHINE,
   141             TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
   142             PATH_BUF_SIZE, NULL);
   143 	assert(result);
   144 	if (!result)
   145 		return NULL;
   146 
   147     SetDllDirectory(TEXT(""));
   148     BOOL _result = SetDllDirectory(path);
   149     assert(_result != 0);
   150     if (_result == 0)
   151         return NULL;
   152 
   153 	HMODULE module = LoadLibrary(utf16_string(filename).c_str());
   154     SetDllDirectory(NULL);
   155 	if (module == NULL)
   156 		return NULL;
   157 	else
   158 		return (void *) module;
   159 }
   160 
   161 int dlclose(void *handle) {
   162 	if (FreeLibrary((HMODULE) handle))
   163 		return 0;
   164 	else
   165 		return 1;
   166 }
   167 
   168 void *dlsym(void *handle, const char *symbol) {
   169 	return (void *) (intptr_t) GetProcAddress((HMODULE) handle, symbol);
   170 }
   171 
   172 const char *windoze_local_db(void) {
   173 	static string path;
   174 	if (path.length() == 0)
   175         path = managementPath("%LOCALAPPDATA%\\pEp", "management.db");
   176     return path.c_str();
   177 }
   178 
   179 const char *windoze_system_db(void) {
   180 	static string path;
   181 	if (path.length() == 0)
   182 		path = managementPath("%ALLUSERSPROFILE%\\pEp", "system.db");
   183     return path.c_str();
   184 }
   185 
   186 const char *gpg_conf(void)
   187 {
   188     static string path;
   189     if (path.length() == 0)
   190         path = managementPath("%APPDATA%\\gnupg", "gpg.conf");
   191     return path.c_str();
   192 }
   193 
   194 long random(void)
   195 {
   196     unsigned int r;
   197     errno_t e;
   198 
   199     assert(sizeof(unsigned int) == sizeof(long)); // this is Windoze
   200 
   201     do {
   202         e = rand_s(&r);
   203     } while (e);
   204 
   205     return (long) (r & ((1U<<31)-1));
   206 }
   207 
   208 char *strndup(const char *s1, size_t n)
   209 {
   210     char *str = (char *) calloc(n + 1, 1);
   211     if (str == NULL)
   212         return NULL;
   213 
   214     strncpy(str, s1, n);
   215     return str;
   216 }
   217 
   218 int mkstemp(char *templ)
   219 {
   220     char *pathname = _mktemp(templ);
   221     if (errno)
   222         return -1;
   223     return _open(pathname, _O_RDWR | _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE);
   224 }
   225 
   226 } // "C"