1 // Windows platform specifica
3 #define WIN32_LEAN_AND_MEAN
7 #define _WIN32_WINNT 0x0600
16 #include "platform_windows.h"
20 #ifndef WC_ERR_INVALID_CHARS
21 #define WC_ERR_INVALID_CHARS 0x00000080 // error for invalid chars
26 static string utf8_string(wstring wstr) {
30 int size = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
31 wstr.c_str(), -1, NULL, 0, NULL, NULL);
34 char *buf = new char[size];
35 WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, wstr.c_str(),
36 -1, buf, size, NULL, NULL);
40 throw out_of_range("input wstring is not valid"
41 " while converting UTF-16 to UTF-8.");
47 static wstring utf16_string(string str) {
51 int size = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
52 str.c_str(), -1, NULL, 0);
55 wchar_t * buf = new wchar_t[size];
56 MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str.c_str(), -1,
61 throw out_of_range("input string is not valid"
62 " while converting UTF-8 to UTF-16.");
68 static bool readRegistryString(
69 HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPTSTR lpResult,
70 DWORD dwSize, LPCTSTR lpDefault
77 DWORD bytesCopied = dwSize;
80 result = RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &theKey);
81 if (result != ERROR_SUCCESS) {
83 wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
90 result = RegQueryValueEx(theKey, lpValueName, NULL, &type,
91 (LPBYTE) lpResult, &bytesCopied);
92 if (result != ERROR_SUCCESS || (type != REG_EXPAND_SZ && type != REG_SZ)) {
94 wcsncpy_s(lpResult, dwSize, lpDefault, _TRUNCATE);
108 static const DWORD PATH_BUF_SIZE = 32768;
110 static inline string managementPath(const char *file_path, const char *file_name)
113 static TCHAR tPath[PATH_BUF_SIZE];
115 DWORD length = ExpandEnvironmentStringsW(utf16_string(file_path).c_str(),
116 tPath, PATH_BUF_SIZE);
119 throw bad_alloc(); // BUG: there are other errors possible beside out of memory
121 CreateDirectory(tPath, NULL);
122 DWORD error = GetLastError();
124 path = utf8_string(tPath);
133 void *dlopen(const char *filename, int flag) {
134 static TCHAR path[PATH_BUF_SIZE];
137 assert(flag == RTLD_LAZY); // only lazy binding is implemented
139 bool result = readRegistryString(HKEY_LOCAL_MACHINE,
140 TEXT("SOFTWARE\\GNU\\GnuPG"), TEXT("Install Directory"), path,
141 PATH_BUF_SIZE, NULL);
146 SetDllDirectory(TEXT(""));
147 BOOL _result = SetDllDirectory(path);
148 assert(_result != 0);
152 HMODULE module = LoadLibrary(utf16_string(filename).c_str());
153 SetDllDirectory(NULL);
157 return (void *) module;
160 int dlclose(void *handle) {
161 if (FreeLibrary((HMODULE) handle))
167 void *dlsym(void *handle, const char *symbol) {
168 return (void *) (intptr_t) GetProcAddress((HMODULE) handle, symbol);
171 const char *windoze_local_db(void) {
173 if (path.length() == 0)
174 path = managementPath("%LOCALAPPDATA%\\pEp", "management.db");
178 const char *windoze_system_db(void) {
180 if (path.length() == 0)
181 path = managementPath("%ALLUSERSPROFILE%\\pEp", "system.db");
185 const char *gpg_conf(void)
188 if (path.length() == 0)
189 path = managementPath("%APPDATA%\\gnupg", "gpg.conf");
193 const char *gpg_agent_conf(void)
195 static string agent_path;
196 if (agent_path.length() == 0)
197 agent_path = managementPath("%APPDATA%\\gnupg", "gpg-agent.conf");
198 return agent_path.c_str();
207 assert(sizeof(unsigned int) == sizeof(long)); // this is Windoze
213 return (long) (r & ((1U<<31)-1));
216 char *strndup(const char *s1, size_t n)
218 char *str = (char *) calloc(n + 1, 1);
226 char *stpcpy(char *dst, const char *src)
228 for (;; ++dst, ++src) {
236 size_t strlcpy(char* dst, const char* src, size_t size) {
237 size_t retval = strlen(src);
238 size_t size_to_copy = (retval < size ? retval : size - 1);
240 // strlcpy doc says src and dst not allowed to overlap, as
241 // it's undefined. So this is acceptable:
242 memcpy((void*)dst, (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
243 dst[size_to_copy] = '\0';
246 size_t strlcat(char* dst, const char* src, size_t size) {
247 size_t start_len = strnlen(dst, size);
248 if (start_len == size)
249 return size; // no copy, no null termination in size bytes, according to spec
251 size_t add_len = strlen(src);
252 size_t retval = start_len + add_len;
253 size_t size_to_copy = (retval < size ? add_len : (size - start_len) - 1);
255 // strlcat doc says src and dst not allowed to overlap, as
256 // it's undefined. So this is acceptable:
257 memcpy((void*)(dst + start_len), (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
258 dst[start_len + size_to_copy] = '\0';
262 int mkstemp(char *templ)
264 char *pathname = _mktemp(templ);
267 return _open(pathname, _O_RDWR | _O_CREAT | _O_EXCL, _S_IREAD | _S_IWRITE);
270 void uuid_generate_random(uuid_t out)
272 RPC_STATUS rpc_status = UuidCreate(out);
273 assert(rpc_status == RPC_S_OK);
276 int uuid_parse(char *in, uuid_t uu)
278 unsigned char *_in = (unsigned char *) in;
279 RPC_STATUS rpc_status = UuidFromString(_in, &uu);
280 assert(rpc_status == RPC_S_OK);
281 if (rpc_status == RPC_S_INVALID_STRING_UUID)
286 void uuid_unparse_upper(uuid_t uu, uuid_string_t out)
288 unsigned char *_out = out;
290 RPC_STATUS rpc_status = UuidToString(uu, &str);
291 assert(rpc_status == RPC_S_OK);
292 if (rpc_status == RPC_S_OK) {
293 memcpy(out, str, 36);
297 else { // if (rpc_status == RPC_S_OUT_OF_MEMORY)