summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Schleifer <js@nil.im>2020-05-17 16:08:15 +0200
committerJonathan Schleifer <js@nil.im>2020-05-17 16:08:15 +0200
commit9e78bd1f491b2887524f93118ae5057379ee23dd (patch)
tree425b27f246b771e3711dc8ccfc13bc1b111f2b77
parent7ff37e327d5a4c5ae4e1adc2e4f1902eece3c997 (diff)
Add support for non-Unicode Windows in all classes
-rw-r--r--src/OFFile.m24
-rw-r--r--src/OFFileManager.m41
-rw-r--r--src/OFFileURLHandler.m210
-rw-r--r--src/OFPlugin.m9
-rw-r--r--src/OFString.m30
-rw-r--r--src/OFSystemInfo.m23
-rw-r--r--src/OFWindowsRegistryKey.m139
-rw-r--r--src/exceptions/OFException.m45
-rw-r--r--src/platform/windows/OFProcess.m116
9 files changed, 463 insertions, 174 deletions
diff --git a/src/OFFile.m b/src/OFFile.m
index 13b71627..85900c33 100644
--- a/src/OFFile.m
+++ b/src/OFFile.m
@@ -32,6 +32,7 @@
#import "OFFile.h"
#import "OFLocale.h"
#import "OFString.h"
+#import "OFSystemInfo.h"
#import "OFURL.h"
#import "OFInitializationFailedException.h"
@@ -220,16 +221,23 @@ parseMode(const char *mode, bool *append)
flags |= O_BINARY | O_CLOEXEC;
-# if defined(OF_WINDOWS)
- if ((handle = _wopen(path.UTF16String, flags,
- _S_IREAD | _S_IWRITE)) == -1)
-# elif defined(HAVE_OPEN64)
- if ((handle = open64([path cStringWithEncoding:
- [OFLocale encoding]], flags, 0666)) == -1)
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ handle = _wopen(path.UTF16String, flags,
+ _S_IREAD | _S_IWRITE);
+ else
+# endif
+# ifdef HAVE_OPEN64
+ handle = open64(
+ [path cStringWithEncoding: [OFLocale encoding]],
+ flags, 0666);
# else
- if ((handle = open([path cStringWithEncoding:
- [OFLocale encoding]], flags, 0666)) == -1)
+ handle = open(
+ [path cStringWithEncoding: [OFLocale encoding]],
+ flags, 0666);
# endif
+
+ if (handle == -1)
@throw [OFOpenItemFailedException
exceptionWithPath: path
mode: mode
diff --git a/src/OFFileManager.m b/src/OFFileManager.m
index 0fbfb9e8..72ec8fb4 100644
--- a/src/OFFileManager.m
+++ b/src/OFFileManager.m
@@ -164,12 +164,24 @@ attributeForKeyOrException(of_file_attributes_t attributes,
{
# if defined(OF_WINDOWS)
OFString *ret;
- wchar_t *buffer = _wgetcwd(NULL, 0);
- @try {
- ret = [OFString stringWithUTF16String: buffer];
- } @finally {
- free(buffer);
+ if ([OFSystemInfo isWindowsNT]) {
+ wchar_t *buffer = _wgetcwd(NULL, 0);
+
+ @try {
+ ret = [OFString stringWithUTF16String: buffer];
+ } @finally {
+ free(buffer);
+ }
+ } else {
+ char *buffer = _getcwd(NULL, 0);
+
+ @try {
+ ret = [OFString stringWithCString: buffer
+ encoding: [OFLocale encoding]];
+ } @finally {
+ free(buffer);
+ }
}
return ret;
@@ -482,12 +494,7 @@ attributeForKeyOrException(of_file_attributes_t attributes,
if (path == nil)
@throw [OFInvalidArgumentException exception];
-# if defined(OF_WINDOWS)
- if (_wchdir(path.UTF16String) != 0)
- @throw [OFChangeCurrentDirectoryPathFailedException
- exceptionWithPath: path
- errNo: errno];
-# elif defined(OF_AMIGAOS)
+# ifdef OF_AMIGAOS
BPTR lock, oldLock;
if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]],
@@ -521,7 +528,17 @@ attributeForKeyOrException(of_file_attributes_t attributes,
dirChanged = true;
# else
- if (chdir([path cStringWithEncoding: [OFLocale encoding]]) != 0)
+ int status;
+
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ status = _wchdir(path.UTF16String);
+ else
+# endif
+ status = chdir(
+ [path cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != 0)
@throw [OFChangeCurrentDirectoryPathFailedException
exceptionWithPath: path
errNo: errno];
diff --git a/src/OFFileURLHandler.m b/src/OFFileURLHandler.m
index ca98fe9e..476ddfb2 100644
--- a/src/OFFileURLHandler.m
+++ b/src/OFFileURLHandler.m
@@ -42,6 +42,7 @@
#import "OFFileManager.h"
#import "OFLocale.h"
#import "OFNumber.h"
+#import "OFSystemInfo.h"
#import "OFURL.h"
#ifdef OF_HAVE_THREADS
@@ -150,9 +151,17 @@ of_stat(OFString *path, of_stat_t *buffer)
{
#if defined(OF_WINDOWS)
WIN32_FILE_ATTRIBUTE_DATA data;
+ bool success;
- if (!GetFileAttributesExW(path.UTF16String, GetFileExInfoStandard,
- &data)) {
+ if ([OFSystemInfo isWindowsNT])
+ success = GetFileAttributesExW(path.UTF16String,
+ GetFileExInfoStandard, &data);
+ else
+ success = GetFileAttributesExA(
+ [path cStringWithEncoding: [OFLocale encoding]],
+ GetFileExInfoStandard, &data);
+
+ if (!success) {
setErrno();
return -1;
}
@@ -163,6 +172,10 @@ of_stat(OFString *path, of_stat_t *buffer)
if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
buffer->st_mode = S_IFDIR;
else if (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ /*
+ * No need to use A functions in this branch: This is only
+ * available on NTFS (and hence Windows NT) anyway.
+ */
WIN32_FIND_DATAW findData;
HANDLE findHandle;
@@ -592,12 +605,17 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS
uint16_t mode = permissions.uInt16Value & 0777;
OFString *path = URL.fileSystemRepresentation;
+ int status;
-# ifndef OF_WINDOWS
- if (chmod([path cStringWithEncoding: [OFLocale encoding]], mode) != 0)
-# else
- if (_wchmod(path.UTF16String, mode) != 0)
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ status = _wchmod(path.UTF16String, mode);
+ else
# endif
+ status = chmod(
+ [path cStringWithEncoding: [OFLocale encoding]], mode);
+
+ if (status != 0)
@throw [OFSetItemAttributesFailedException
exceptionWithURL: URL
attributes: attributes
@@ -780,7 +798,15 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
path = URL.fileSystemRepresentation;
#if defined(OF_WINDOWS)
- if (_wmkdir(path.UTF16String) != 0)
+ int status;
+
+ if ([OFSystemInfo isWindowsNT])
+ status = _wmkdir(path.UTF16String);
+ else
+ status = _mkdir(
+ [path cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != 0)
@throw [OFCreateDirectoryFailedException
exceptionWithURL: URL
errNo: errno];
@@ -846,45 +872,94 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
#if defined(OF_WINDOWS)
HANDLE handle;
- WIN32_FIND_DATAW fd;
path = [path stringByAppendingString: @"\\*"];
- if ((handle = FindFirstFileW(path.UTF16String,
- &fd)) == INVALID_HANDLE_VALUE) {
- int errNo = 0;
+ if ([OFSystemInfo isWindowsNT]) {
+ WIN32_FIND_DATAW fd;
- if (GetLastError() == ERROR_FILE_NOT_FOUND)
- errNo = ENOENT;
+ if ((handle = FindFirstFileW(path.UTF16String,
+ &fd)) == INVALID_HANDLE_VALUE) {
+ int errNo = 0;
- @throw [OFOpenItemFailedException exceptionWithURL: URL
- mode: nil
- errNo: errNo];
- }
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ errNo = ENOENT;
- @try {
- do {
- OFString *file;
+ @throw [OFOpenItemFailedException
+ exceptionWithURL: URL
+ mode: nil
+ errNo: errNo];
+ }
- if (!wcscmp(fd.cFileName, L".") ||
- !wcscmp(fd.cFileName, L".."))
- continue;
+ @try {
+ do {
+ OFString *file;
- file = [[OFString alloc]
- initWithUTF16String: fd.cFileName];
- @try {
- [files addObject: file];
- } @finally {
- [file release];
- }
- } while (FindNextFileW(handle, &fd));
+ if (wcscmp(fd.cFileName, L".") == 0 ||
+ wcscmp(fd.cFileName, L"..") == 0)
+ continue;
- if (GetLastError() != ERROR_NO_MORE_FILES)
- @throw [OFReadFailedException exceptionWithObject: self
- requestedLength: 0
- errNo: EIO];
- } @finally {
- FindClose(handle);
+ file = [[OFString alloc]
+ initWithUTF16String: fd.cFileName];
+ @try {
+ [files addObject: file];
+ } @finally {
+ [file release];
+ }
+ } while (FindNextFileW(handle, &fd));
+
+ if (GetLastError() != ERROR_NO_MORE_FILES)
+ @throw [OFReadFailedException
+ exceptionWithObject: self
+ requestedLength: 0
+ errNo: EIO];
+ } @finally {
+ FindClose(handle);
+ }
+ } else {
+ of_string_encoding_t encoding = [OFLocale encoding];
+ WIN32_FIND_DATA fd;
+
+ if ((handle = FindFirstFileA(
+ [path cStringWithEncoding: encoding], &fd)) ==
+ INVALID_HANDLE_VALUE) {
+ int errNo = 0;
+
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ errNo = ENOENT;
+
+ @throw [OFOpenItemFailedException
+ exceptionWithURL: URL
+ mode: nil
+ errNo: errNo];
+ }
+
+ @try {
+ do {
+ OFString *file;
+
+ if (strcmp(fd.cFileName, ".") == 0 ||
+ strcmp(fd.cFileName, "..") == 0)
+ continue;
+
+ file = [[OFString alloc]
+ initWithCString: fd.cFileName
+ encoding: encoding];
+ @try {
+ [files addObject: file];
+ } @finally {
+ [file release];
+ }
+ } while (FindNextFileA(handle, &fd));
+
+ if (GetLastError() != ERROR_NO_MORE_FILES)
+ @throw [OFReadFailedException
+ exceptionWithObject: self
+ requestedLength: 0
+ errNo: EIO];
+ } @finally {
+ FindClose(handle);
+ }
}
#elif defined(OF_AMIGAOS)
of_string_encoding_t encoding = [OFLocale encoding];
@@ -1094,21 +1169,32 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
}
#ifndef OF_AMIGAOS
-# ifndef OF_WINDOWS
- if (rmdir([path cStringWithEncoding: [OFLocale encoding]]) != 0)
-# else
- if (_wrmdir(path.UTF16String) != 0)
+ int status;
+
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ status = _wrmdir(path.UTF16String);
+ else
# endif
+ status = rmdir(
+ [path cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != 0)
@throw [OFRemoveItemFailedException
exceptionWithURL: URL
errNo: errno];
} else {
-# ifndef OF_WINDOWS
- if (unlink([path cStringWithEncoding:
- [OFLocale encoding]]) != 0)
-# else
- if (_wunlink(path.UTF16String) != 0)
+ int status;
+
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ status = _wunlink(path.UTF16String);
+ else
# endif
+ status = unlink(
+ [path cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != 0)
@throw [OFRemoveItemFailedException
exceptionWithURL: URL
errNo: errno];
@@ -1246,14 +1332,7 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
pool = objc_autoreleasePoolPush();
-#if defined(OF_WINDOWS)
- if (_wrename(source.fileSystemRepresentation.UTF16String,
- destination.fileSystemRepresentation.UTF16String) != 0)
- @throw [OFMoveItemFailedException
- exceptionWithSourceURL: source
- destinationURL: destination
- errNo: errno];
-#elif defined(OF_AMIGAOS)
+#ifdef OF_AMIGAOS
of_string_encoding_t encoding = [OFLocale encoding];
if (!Rename([source.fileSystemRepresentation
@@ -1290,12 +1369,25 @@ setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes,
errNo: errNo];
}
#else
- of_string_encoding_t encoding = [OFLocale encoding];
+ int status;
- if (rename([source.fileSystemRepresentation
- cStringWithEncoding: encoding],
- [destination.fileSystemRepresentation
- cStringWithEncoding: encoding]) != 0)
+# ifdef OF_WINDOWS
+ if ([OFSystemInfo isWindowsNT])
+ status = _wrename(source.fileSystemRepresentation.UTF16String,
+ destination.fileSystemRepresentation.UTF16String);
+ else {
+# endif
+ of_string_encoding_t encoding = [OFLocale encoding];
+
+ status = rename([source.fileSystemRepresentation
+ cStringWithEncoding: encoding],
+ [destination.fileSystemRepresentation
+ cStringWithEncoding: encoding]);
+# ifdef OF_WINDOWS
+ }
+# endif
+
+ if (status != 0)
@throw [OFMoveItemFailedException
exceptionWithSourceURL: source
destinationURL: destination
diff --git a/src/OFPlugin.m b/src/OFPlugin.m
index d94e753d..941f09a5 100644
--- a/src/OFPlugin.m
+++ b/src/OFPlugin.m
@@ -25,8 +25,9 @@
#endif
#import "OFPlugin.h"
-#import "OFString.h"
#import "OFLocale.h"
+#import "OFString.h"
+#import "OFSystemInfo.h"
#import "OFInitializationFailedException.h"
#import "OFLoadPluginFailedException.h"
@@ -42,7 +43,11 @@ of_dlopen(OFString *path, int flags)
if (path == nil)
return GetModuleHandle(NULL);
- return LoadLibraryW(path.UTF16String);
+ if ([OFSystemInfo isWindowsNT])
+ return LoadLibraryW(path.UTF16String);
+ else
+ return LoadLibraryA(
+ [path cStringWithEncoding: [OFLocale encoding]]);
#endif
}
diff --git a/src/OFString.m b/src/OFString.m
index 014adf3c..cc8f9921 100644
--- a/src/OFString.m
+++ b/src/OFString.m
@@ -41,6 +41,7 @@
#endif
#import "OFLocale.h"
#import "OFStream.h"
+#import "OFSystemInfo.h"
#import "OFURL.h"
#import "OFURLHandler.h"
#import "OFUTF8String.h"
@@ -2711,15 +2712,30 @@ decomposedString(OFString *self, const char *const *const *table, size_t size)
#ifdef OF_WINDOWS
- (OFString *)stringByExpandingWindowsEnvironmentStrings
{
- wchar_t buffer[512];
- size_t length;
+ if ([OFSystemInfo isWindowsNT]) {
+ wchar_t buffer[512];
+ size_t length;
- if ((length = ExpandEnvironmentStringsW(self.UTF16String, buffer,
- sizeof(buffer))) == 0)
- return self;
+ if ((length = ExpandEnvironmentStringsW(self.UTF16String,
+ buffer, sizeof(buffer))) == 0)
+ return self;
- return [OFString stringWithUTF16String: buffer
- length: length - 1];
+ return [OFString stringWithUTF16String: buffer
+ length: length - 1];
+ } else {
+ of_string_encoding_t encoding = [OFLocale encoding];
+ char buffer[512];
+ size_t length;
+
+ if ((length = ExpandEnvironmentStringsA(
+ [self cStringWithEncoding: encoding], buffer,
+ sizeof(buffer))) == 0)
+ return self;
+
+ return [OFString stringWithCString: buffer
+ encoding: encoding
+ length: length - 1];
+ }
}
#endif
diff --git a/src/OFSystemInfo.m b/src/OFSystemInfo.m
index 9b13bb2b..6f177b76 100644
--- a/src/OFSystemInfo.m
+++ b/src/OFSystemInfo.m
@@ -165,24 +165,25 @@ initOperatingSystemVersion(void)
void *pool = objc_autoreleasePoolPush();
@try {
- wchar_t systemDir[PATH_MAX];
+ of_string_encoding_t encoding = [OFLocale encoding];
+ char systemDir[PATH_MAX];
UINT systemDirLen;
OFString *systemDirString;
- const of_char16_t *path;
+ const char *path;
void *buffer;
DWORD bufferLen;
- systemDirLen = GetSystemDirectoryW(systemDir, PATH_MAX);
+ systemDirLen = GetSystemDirectoryA(systemDir, PATH_MAX);
if (systemDirLen == 0)
return;
- systemDirString = [OFString
- stringWithUTF16String: systemDir
- length: systemDirLen];
- path = [systemDirString stringByAppendingPathComponent:
- @"kernel32.dll"].UTF16String;
+ systemDirString = [OFString stringWithCString: systemDir
+ encoding: encoding
+ length: systemDirLen];
+ path = [[systemDirString stringByAppendingPathComponent:
+ @"kernel32.dll"] cStringWithEncoding: encoding];
- if ((bufferLen = GetFileVersionInfoSizeW(path, NULL)) == 0)
+ if ((bufferLen = GetFileVersionInfoSizeA(path, NULL)) == 0)
return;
if ((buffer = malloc(bufferLen)) == 0)
return;
@@ -192,10 +193,10 @@ initOperatingSystemVersion(void)
UINT dataLen;
VS_FIXEDFILEINFO *info;
- if (!GetFileVersionInfoW(path, 0, bufferLen, buffer))
+ if (!GetFileVersionInfoA(path, 0, bufferLen, buffer))
return;
- if (!VerQueryValueW(buffer, L"\\", &data, &dataLen) ||
+ if (!VerQueryValueA(buffer, "\\", &data, &dataLen) ||
dataLen < sizeof(info))
return;
diff --git a/src/OFWindowsRegistryKey.m b/src/OFWindowsRegistryKey.m
index abfdc89d..7c18dd23 100644
--- a/src/OFWindowsRegistryKey.m
+++ b/src/OFWindowsRegistryKey.m
@@ -19,6 +19,8 @@
#import "OFWindowsRegistryKey.h"
#import "OFData.h"
+#import "OFLocale.h"
+#import "OFSystemInfo.h"
#include <windows.h>
@@ -108,8 +110,15 @@
LSTATUS status;
HKEY subKey;
- if ((status = RegOpenKeyExW(_hKey, path.UTF16String, options,
- securityAndAccessRights, &subKey)) != ERROR_SUCCESS) {
+ if ([OFSystemInfo isWindowsNT])
+ status = RegOpenKeyExW(_hKey, path.UTF16String, options,
+ securityAndAccessRights, &subKey);
+ else
+ status = RegOpenKeyExA(_hKey,
+ [path cStringWithEncoding: [OFLocale encoding]], options,
+ securityAndAccessRights, &subKey);
+
+ if (status != ERROR_SUCCESS) {
if (status == ERROR_FILE_NOT_FOUND) {
objc_autoreleasePoolPop(pool);
return nil;
@@ -151,9 +160,17 @@
LSTATUS status;
HKEY subKey;
- if ((status = RegCreateKeyExW(_hKey, path.UTF16String, 0,
- NULL, options, securityAndAccessRights, securityAttributes,
- &subKey, NULL)) != ERROR_SUCCESS)
+ if ([OFSystemInfo isWindowsNT])
+ status = RegCreateKeyExW(_hKey, path.UTF16String, 0,
+ NULL, options, securityAndAccessRights, securityAttributes,
+ &subKey, NULL);
+ else
+ status = RegCreateKeyExA(_hKey,
+ [path cStringWithEncoding: [OFLocale encoding]], 0, NULL,
+ options, securityAndAccessRights, securityAttributes,
+ &subKey, NULL);
+
+ if (status != ERROR_SUCCESS)
@throw [OFCreateWindowsRegistryKeyFailedException
exceptionWithRegistryKey: self
path: path
@@ -176,11 +193,17 @@
BYTE stackBuffer[256], *buffer = stackBuffer;
DWORD length = sizeof(stackBuffer);
OFMutableData *ret = nil;
+ bool winNT = [OFSystemInfo isWindowsNT];
LSTATUS status;
for (;;) {
- status = RegQueryValueExW(_hKey, value.UTF16String, NULL, type,
- buffer, &length);
+ if (winNT)
+ status = RegQueryValueExW(_hKey, value.UTF16String,
+ NULL, type, buffer, &length);
+ else
+ status = RegQueryValueExA(_hKey,
+ [value cStringWithEncoding: [OFLocale encoding]],
+ NULL, type, buffer, &length);
switch (status) {
case ERROR_SUCCESS:
@@ -229,8 +252,15 @@
if (length > UINT32_MAX)
@throw [OFOutOfRangeException exception];
- if ((status = RegSetValueExW(_hKey, value.UTF16String, 0, type,
- data.items, (DWORD)length)) != ERROR_SUCCESS)
+ if ([OFSystemInfo isWindowsNT])
+ status = RegSetValueExW(_hKey, value.UTF16String, 0, type,
+ data.items, (DWORD)length);
+ else
+ status = RegSetValueExA(_hKey,
+ [value cStringWithEncoding: [OFLocale encoding]], 0, type,
+ data.items, (DWORD)length);
+
+ if (status != ERROR_SUCCESS)
@throw [OFSetWindowsRegistryValueFailedException
exceptionWithRegistryKey: self
value: value
@@ -252,8 +282,6 @@
DWORD type;
OFData *data = [self dataForValue: value
type: &type];
- const of_char16_t *UTF16String;
- size_t length;
OFString *ret;
if (data == nil)
@@ -262,27 +290,50 @@
if (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_LINK)
@throw [OFInvalidEncodingException exception];
- UTF16String = data.items;
- length = data.count;
-
- if (data.itemSize != 1 || length % 2 == 1)
+ if (data.itemSize != 1)
@throw [OFInvalidFormatException exception];
- length /= 2;
+ if ([OFSystemInfo isWindowsNT]) {
+ const of_char16_t *UTF16String = data.items;
+ size_t length = data.count;
+
+ if (length % 2 == 1)
+ @throw [OFInvalidFormatException exception];
- /*
- * REG_SZ and REG_EXPAND_SZ contain a \0, but can contain data after it
- * that should be ignored.
- */
- for (size_t i = 0; i < length; i++) {
- if (UTF16String[i] == 0) {
- length = i;
- break;
+ length /= 2;
+
+ /*
+ * REG_SZ and REG_EXPAND_SZ contain a \0, but can contain data
+ * after it that should be ignored.
+ */
+ for (size_t i = 0; i < length; i++) {
+ if (UTF16String[i] == 0) {
+ length = i;
+ break;
+ }
}
- }
- ret = [[OFString alloc] initWithUTF16String: UTF16String
- length: length];
+ ret = [[OFString alloc] initWithUTF16String: UTF16String
+ length: length];
+ } else {
+ const char *cString = data.items;
+ size_t length = data.count;
+
+ /*
+ * REG_SZ and REG_EXPAND_SZ contain a \0, but can contain data
+ * after it that should be ignored.
+ */
+ for (size_t i = 0; i < length; i++) {
+ if (cString[i] == 0) {
+ length = i;
+ break;
+ }
+ }
+
+ ret = [[OFString alloc] initWithCString: cString
+ encoding: [OFLocale encoding]
+ length: length];
+ }
if (typeOut != NULL)
*typeOut = type;
@@ -307,9 +358,19 @@
void *pool = objc_autoreleasePoolPush();
OFData *data;
- data = [OFData dataWithItems: string.UTF16String
- itemSize: sizeof(of_char16_t)
- count: string.UTF16StringLength + 1];
+ if ([OFSystemInfo isWindowsNT])
+ data = [OFData dataWithItems: string.UTF16String
+ itemSize: sizeof(of_char16_t)
+ count: string.UTF16StringLength + 1];
+ else {
+ of_string_encoding_t encoding = [OFLocale encoding];
+ const char *cString = [string cStringWithEncoding: encoding];
+ size_t length = [string cStringLengthWithEncoding: encoding];
+
+ data = [OFData dataWithItems: cString
+ count: length + 1];
+ }
+
[self setData: data
forValue: value
type: type];
@@ -322,8 +383,13 @@
void *pool = objc_autoreleasePoolPush();
LSTATUS status;
- if ((status = RegDeleteValueW(_hKey, value.UTF16String)) !=
- ERROR_SUCCESS)
+ if ([OFSystemInfo isWindowsNT])
+ status = RegDeleteValueW(_hKey, value.UTF16String);
+ else
+ status = RegDeleteValueA(_hKey,
+ [value cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != ERROR_SUCCESS)
@throw [OFDeleteWindowsRegistryValueFailedException
exceptionWithRegistryKey: self
value: value
@@ -337,8 +403,13 @@
void *pool = objc_autoreleasePoolPush();
LSTATUS status;
- if ((status = RegDeleteKeyW(_hKey, subkeyPath.UTF16String)) !=
- ERROR_SUCCESS)
+ if ([OFSystemInfo isWindowsNT])
+ status = RegDeleteKeyW(_hKey, subkeyPath.UTF16String);
+ else
+ status = RegDeleteKeyA(_hKey,
+ [subkeyPath cStringWithEncoding: [OFLocale encoding]]);
+
+ if (status != ERROR_SUCCESS)
@throw [OFDeleteWindowsRegistryKeyFailedException
exceptionWithRegistryKey: self
subkeyPath: subkeyPath
diff --git a/src/exceptions/OFException.m b/src/exceptions/OFException.m
index 07efb6dc..0915c30c 100644
--- a/src/exceptions/OFException.m
+++ b/src/exceptions/OFException.m
@@ -27,9 +27,10 @@
#endif
#import "OFException.h"
-#import "OFString.h"
#import "OFArray.h"
#import "OFLocale.h"
+#import "OFString.h"
+#import "OFSystemInfo.h"
#import "OFInitializationFailedException.h"
#import "OFLockFailedException.h"
@@ -211,19 +212,39 @@ of_strerror(int errNo)
OFString *
of_windows_status_to_string(LSTATUS status)
{
+ OFString *string = nil;
void *buffer;
- OFString *string;
-
- if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, status, 0, (LPWSTR)&buffer, 0,
- NULL) != 0) {
- @try {
- string = [OFString stringWithUTF16String: buffer];
- } @finally {
- LocalFree(buffer);
+
+ if ([OFSystemInfo isWindowsNT]) {
+ if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, status, 0,
+ (LPWSTR)&buffer, 0, NULL) != 0) {
+ @try {
+ string = [OFString
+ stringWithUTF16String: buffer];
+ } @finally {
+ LocalFree(buffer);
+ }
}
- } else
+ } else {
+ if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, status, 0,
+ (LPSTR)&buffer, 0, NULL) != 0) {
+ @try {
+ string = [OFString
+ stringWithCString: buffer
+ encoding: [OFLocale encoding]];
+ } @finally {
+ LocalFree(buffer);
+ }
+ }
+ }
+
+ if (string == nil)
string = [OFString stringWithFormat: @"Status code %u", status];
return string;
diff --git a/src/platform/windows/OFProcess.m b/src/platform/windows/OFProcess.m
index 31774a69..b06a84b7 100644
--- a/src/platform/windows/OFProcess.m
+++ b/src/platform/windows/OFProcess.m
@@ -21,10 +21,12 @@
#include <string.h>
#import "OFProcess.h"
-#import "OFString.h"
#import "OFArray.h"
-#import "OFDictionary.h"
#import "OFData.h"
+#import "OFDictionary.h"
+#import "OFLocale.h"
+#import "OFString.h"
+#import "OFSystemInfo.h"
#import "OFInitializationFailedException.h"
#import "OFNotOpenException.h"
@@ -35,7 +37,8 @@
#include <windows.h>
@interface OFProcess ()
-- (of_char16_t *)of_environmentForDictionary: (OFDictionary *)dictionary;
+- (of_char16_t *)of_wideEnvironmentForDictionary: (OFDictionary *)dictionary;
+- (char *)of_environmentForDictionary: (OFDictionary *)environment;
@end
@implementation OFProcess
@@ -113,11 +116,8 @@
@try {
SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION pi;
- STARTUPINFOW si;
void *pool;
OFMutableString *argumentsString;
- of_char16_t *argumentsCopy;
- size_t length;
_process = INVALID_HANDLE_VALUE;
_readPipe[0] = _writePipe[1] = NULL;
@@ -131,8 +131,9 @@
exceptionWithClass: self.class];
if (!SetHandleInformation(_readPipe[0], HANDLE_FLAG_INHERIT, 0))
- @throw [OFInitializationFailedException
- exceptionWithClass: self.class];
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ @throw [OFInitializationFailedException
+ exceptionWithClass: self.class];
if (!CreatePipe(&_writePipe[0], &_writePipe[1], &sa, 0))
@throw [OFInitializationFailedException
@@ -140,17 +141,11 @@
if (!SetHandleInformation(_writePipe[1],
HANDLE_FLAG_INHERIT, 0))
- @throw [OFInitializationFailedException
- exceptionWithClass: self.class];
+ if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
+ @throw [OFInitializationFailedException
+ exceptionWithClass: self.class];
memset(&pi, 0, sizeof(pi));
- memset(&si, 0, sizeof(si));
-
- si.cb = sizeof(si);
- si.hStdInput = _writePipe[0];
- si.hStdOutput = _readPipe[1];
- si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- si.dwFlags |= STARTF_USESTDHANDLES;
pool = objc_autoreleasePoolPush();
@@ -187,21 +182,53 @@
[argumentsString appendString: @"\""];
}
- length = argumentsString.UTF16StringLength;
- argumentsCopy = [self allocMemoryWithSize: sizeof(of_char16_t)
- count: length + 1];
- memcpy(argumentsCopy, argumentsString.UTF16String,
- (argumentsString.UTF16StringLength + 1) * 2);
- @try {
- if (!CreateProcessW(program.UTF16String,
- argumentsCopy, NULL, NULL, TRUE,
- CREATE_UNICODE_ENVIRONMENT,
+ if ([OFSystemInfo isWindowsNT]) {
+ size_t length;
+ of_char16_t *argumentsCopy;
+ STARTUPINFOW si;
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.hStdInput = _writePipe[0];
+ si.hStdOutput = _readPipe[1];
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ length = argumentsString.UTF16StringLength;
+ argumentsCopy = [self
+ allocMemoryWithSize: sizeof(of_char16_t)
+ count: length + 1];
+ memcpy(argumentsCopy, argumentsString.UTF16String,
+ (length + 1) * 2);
+ @try {
+ if (!CreateProcessW(program.UTF16String,
+ argumentsCopy, NULL, NULL, TRUE,
+ CREATE_UNICODE_ENVIRONMENT,
+ [self of_wideEnvironmentForDictionary:
+ environment], NULL, &si, &pi))
+ @throw [OFInitializationFailedException
+ exceptionWithClass: self.class];
+ } @finally {
+ [self freeMemory: argumentsCopy];
+ }
+ } else {
+ of_string_encoding_t encoding = [OFLocale encoding];
+ STARTUPINFO si;
+
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.hStdInput = _writePipe[0];
+ si.hStdOutput = _readPipe[1];
+ si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
+ si.dwFlags |= STARTF_USESTDHANDLES;
+
+ if (!CreateProcessA([program cStringWithEncoding:
+ encoding], (char *)[argumentsString
+ cStringWithEncoding: encoding], NULL, NULL, TRUE, 0,
[self of_environmentForDictionary: environment],
NULL, &si, &pi))
@throw [OFInitializationFailedException
exceptionWithClass: self.class];
- } @finally {
- [self freeMemory: argumentsCopy];
}
objc_autoreleasePoolPop(pool);
@@ -227,7 +254,7 @@
[super dealloc];
}
-- (of_char16_t *)of_environmentForDictionary: (OFDictionary *)environment
+- (of_char16_t *)of_wideEnvironmentForDictionary: (OFDictionary *)environment
{
OFMutableData *env;
OFEnumerator *keyEnumerator, *objectEnumerator;
@@ -259,6 +286,37 @@
return env.mutableItems;
}
+- (char *)of_environmentForDictionary: (OFDictionary *)environment
+{
+ of_string_encoding_t encoding = [OFLocale encoding];
+ OFMutableData *env;
+ OFEnumerator *keyEnumerator, *objectEnumerator;
+ OFString *key, *object;
+
+ if (environment == nil)
+ return NULL;
+
+ env = [OFMutableData data];
+
+ keyEnumerator = [environment keyEnumerator];
+ objectEnumerator = [environment objectEnumerator];
+ while ((key = [keyEnumerator nextObject]) != nil &&
+ (object = [objectEnumerator nextObject]) != nil) {
+ [env addItems: [key cStringWithEncoding: encoding]
+ count: [key cStringLengthWithEncoding: encoding]];
+ [env addItems: "="
+ count: 1];
+ [env addItems: [object cStringWithEncoding: encoding]
+ count: [object cStringLengthWithEncoding: encoding]];
+ [env addItems: ""
+ count: 1];
+ }
+ [env addItems: "\0"
+ count: 2];
+
+ return env.mutableItems;
+}
+
- (bool)lowlevelIsAtEndOfStream
{
if (_readPipe[0] == NULL)