Author: mturk Date: Mon Jan 11 15:20:50 2010 New Revision: 897899 URL: http://svn.apache.org/viewvc?rev=897899&view=rev Log: Add unicode registry helpers
Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h?rev=897899&r1=897898&r2=897899&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h Mon Jan 11 15:20:50 2010 @@ -297,6 +297,38 @@ #define ACR_IOH_FLAGS(H) acr_ioh_tab[(H) & acr_ioh_mask].flags #define ACR_IOH_FDATA(H) acr_ioh_tab[(H) & acr_ioh_mask].h +static ACR_INLINE void FS2BSW(wchar_t *s) +{ + for (; *s; s++) { + if (*s == L'/') + *s = L'\\'; + } +} + +static ACR_INLINE void BS2FSW(wchar_t *s) +{ + for (; *s; s++) { + if (*s == L'\\') + *s = L'/'; + } +} + +static ACR_INLINE void FS2BSA(char *s) +{ + for (; *s; s++) { + if (*s == '/') + *s = '\\'; + } +} + +static ACR_INLINE void BS2FSA(char *s) +{ + for (; *s; s++) { + if (*s == '\\') + *s = '/'; + } +} + static ACR_INLINE void FileTimeToUsecTime(acr_time_t *result, LPFILETIME input) { /* Convert FILETIME one 64 bit number so we can work with it. */ Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c?rev=897899&r1=897898&r2=897899&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c Mon Jan 11 15:20:50 2010 @@ -45,6 +45,22 @@ return NULL; } +static HKEY wcs_rootnamed(const wchar_t *name) +{ + if (!wcsnicmp(name, L"HKLM", 4)) + return HKEY_LOCAL_MACHINE; + else if (!wcsnicmp(name, L"HKCU", 4)) + return HKEY_CURRENT_USER; + else if (!wcsnicmp(name, L"HKCR", 4)) + return HKEY_CLASSES_ROOT; + else if (!wcsnicmp(name, L"HKCC", 4)) + return HKEY_CURRENT_CONFIG; + else if (!wcsnicmp(name, L"HKU", 3)) + return HKEY_USERS; + else + return NULL; +} + static REGSAM reg_flags(const char *s) { REGSAM sam = KEY_QUERY_VALUE; @@ -57,7 +73,24 @@ sam |= KEY_WRITE; if (strchr(s, '3')) sam |= KEY_WOW64_32KEY; - else if (strchr(s, '6')) + else if (strstr(s, "64")) + sam |= KEY_WOW64_64KEY; + return sam; +} + +static REGSAM wcs_flags(const wchar_t *s) +{ + REGSAM sam = KEY_QUERY_VALUE; + + if (wcschr(s, L'x')) + sam |= KEY_ALL_ACCESS; + if (wcschr(s, L'r')) + sam |= KEY_READ; + if (wcschr(s, L'w')) + sam |= KEY_WRITE; + if (wcschr(s, L'3')) + sam |= KEY_WOW64_32KEY; + else if (wcsstr(s, L"64")) sam |= KEY_WOW64_64KEY; return sam; } @@ -94,6 +127,38 @@ return k; } +ACR_DECLARE(x_registry_t *) RegistryOpenW(const wchar_t *name, const wchar_t *sam) +{ + int i; + HKEY r; + wchar_t *p; + x_registry_t *k; + + if (!(r = wcs_rootnamed(name))) { + ACR_SET_OS_ERROR(ACR_EINVAL); + return NULL; + } + + k = x_malloc(sizeof(x_registry_t)); + if (!(p = wcschr(name, L'\\'))) { + x_free(k); + ACR_SET_OS_ERROR(ACR_EINVAL); + return NULL; + } + k->name = x_wcsdup(p + 1); + k->sam = wcs_flags(sam); + + if ((i = RegOpenKeyExW(r, k->name, 0, + k->sam, &k->key)) != ERROR_SUCCESS) { + x_free(k->name); + x_free(k); + ACR_SET_OS_ERROR(i); + return NULL; + } + + return k; +} + ACR_DECLARE(void) RegistryClose(x_registry_t *key) { if (key) { @@ -151,6 +216,51 @@ return i; } +ACR_DECLARE(int) RegistryDeleteW(const wchar_t *name, const wchar_t *sam, int all, + const wchar_t *value) +{ + int i = ERROR_SUCCESS; + HKEY r; + wchar_t *p; + x_registry_t k; + wchar_t *s = NULL; + + if (!(r = wcs_rootnamed(name))) { + return ACR_EINVAL; + } + + if (!(p = wcschr(name, L'\\'))) { + return ACR_EINVAL; + } + k.name = x_wcsdup(p + 1); + k.sam = wcs_flags(sam); + + if ((s = wcschr(k.name, L'\\'))) { + *(s++) = L'\0'; + } + else { + x_free(k.name); + return ACR_EINVAL; + } + if ((i = RegOpenKeyExW(r, k.name, 0, + k.sam, &k.key)) != ERROR_SUCCESS) { + x_free(k.name); + return i; + } + if (value) { + i = SHDeleteValueW(k.key, s, value); + } + else { + if (all) + i = SHDeleteKeyW(k.key, s); + else + i = SHDeleteEmptyKeyW(k.key, s); + } + SAFE_CLOSE_KEY(k.key); + x_free(k.name); + return i; +} + ACR_DECLARE(x_registry_t *) RegistryCreateA(const char *name, const char *sam) { DWORD c; @@ -184,6 +294,39 @@ return k; } +ACR_DECLARE(x_registry_t *) RegistryCreateW(const wchar_t *name, const wchar_t *sam) +{ + DWORD c; + int i; + HKEY r; + wchar_t *p; + x_registry_t *k; + + if (!(r = wcs_rootnamed(name))) { + ACR_SET_OS_ERROR(ACR_EINVAL); + return NULL; + } + + k = x_malloc(sizeof(x_registry_t)); + if (!(p = wcschr(name, '\\'))) { + x_free(k); + ACR_SET_OS_ERROR(ACR_EINVAL); + return NULL; + } + k->name = x_wcsdup(p + 1); + k->sam = wcs_flags(sam); + + if ((i = RegCreateKeyExW(r, k->name, 0, NULL, 0, + k->sam, NULL, &k->key, &c)) != ERROR_SUCCESS) { + x_free(k->name); + x_free(k); + ACR_SET_OS_ERROR(i); + return NULL; + } + + return k; +} + ACR_DECLARE(char *) RegistryGetA(x_registry_t *k, const char *name, int sc) { int rc = 0; @@ -278,6 +421,96 @@ return value; } +ACR_DECLARE(wchar_t *) RegistryGetW(x_registry_t *k, const wchar_t *name, int sc) +{ + int rc = 0; + DWORD rt; + DWORD rl, dw; + INT64 qw; + wchar_t *wn = NULL; + wchar_t tb[128]; + unsigned char *bb = NULL; + wchar_t *value = NULL; + wchar_t *wp; + wchar_t *wb; + wchar_t *cp; + + if (k && IS_INVALID_HANDLE(k->key)) { + ACR_SET_OS_ERROR(ACR_EINVAL); + return NULL; + } + if ((rc = (LONG)RegQueryValueExW(k->key, name, NULL, + &rt, NULL, &rl)) != ERROR_SUCCESS) { + goto cleanup; + } + bb = x_malloc((size_t)rl); + if ((rc = (int)RegQueryValueExW(k->key, name, NULL, + &rt, bb, &rl)) != ERROR_SUCCESS) { + goto cleanup; + } + wb = (wchar_t *)bb; + switch (rt) { + case REG_SZ: + value = wb; + bb = NULL; + break; + case REG_MULTI_SZ: + for (wp = wb; *wp; wp++) { + while (*wp) + wp++; + if (*(wp + 1) != L'\0') + *wp = sc; + } + value = wb; + bb = NULL; + break; + case REG_EXPAND_SZ: + { + wchar_t *sb; + DWORD sz; + sz = ExpandEnvironmentStringsW(wb, NULL, 0); + if (sz) { + sb = s_malloc(wchar_t, sz); + if (sb == NULL) + break; + sz = ExpandEnvironmentStringsW(wb, sb, sz); + if (!sz) { + /* Shouldn't ever happen */ + int rc = GetLastError(); + x_free(sb); + goto cleanup; + } + value = sb; + } + } + break; + case REG_DWORD: + memcpy(&rt, bb, 4); + value = x_wcsdup(_itow(rt, tb, 10)); + break; + case REG_QWORD: + memcpy(&qw, bb, 8); + value = x_wcsdup(_i64tow(qw, tb, 10)); + break; + case REG_BINARY: + value = s_malloc(wchar_t, rl * 4 + 1); + for (dw = 0, cp = value; dw < (rl - 1); dw++) { + _snwprintf(cp, 4, L"%02x, ", bb[dw]); + cp += 4; + } + _snwprintf(cp, 4, L"%02x", bb[dw]); + break; + default: + rc = ACR_EBADF; + break; + } + +cleanup: + x_free(bb); + ACR_SET_OS_ERROR(rc); + return value; +} + ACR_DECLARE(int) RegistrySetA(x_registry_t *k, const char *name, int type, const char *value, int sc) { @@ -355,6 +588,7 @@ pp++; } rc = RegSetValueExW(k->key, wn, 0, st, bb, i); + x_free(bb); } break; default: @@ -367,6 +601,89 @@ return rc; } +ACR_DECLARE(int) RegistrySetW(x_registry_t *k, const wchar_t *name, + int type, const wchar_t *value, int sc) +{ + int rc = 0; + DWORD rt, st = type; + DWORD rl, dw; + INT64 qw; + wchar_t *wp, *p; + + if (k && IS_INVALID_HANDLE(k->key)) { + return ACR_EINVAL; + } + if ((rc = (int)RegQueryValueExW(k->key, name, NULL, + &rt, NULL, &rl)) == ERROR_SUCCESS) { + if (st != REG_NONE && st != rt) { + rc = ACR_EINVAL; + goto cleanup; + } + st = rt; + } + if (st == REG_NONE) + st = REG_SZ; + + switch (st) { + case REG_SZ: + case REG_EXPAND_SZ: + rc = RegSetValueExW(k->key, name, 0, st, + (const unsigned char *)value, + (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); + break; + case REG_MULTI_SZ: + wp = x_wcsdup(value); + rl = (DWORD)wcslen(wp); + for (p = wp; *p; p++) { + if (*p == sc) + *p = L'\0'; + } + rc = RegSetValueExW(k->key, name, 0, st, + (const unsigned char *)wp, + (DWORD)((rl + 2) * sizeof(wchar_t))); + x_free(wp); + break; + case REG_DWORD: + dw = (DWORD)_wtoi(value); + rc = RegSetValueExW(k->key, name, 0, st, + (const unsigned char *)&dw, 4); + break; + case REG_QWORD: + qw = _wtoi64(value); + rc = RegSetValueExW(k->key, name, 0, st, + (const unsigned char *)&qw, 8); + break; + case REG_BINARY: + { + DWORD i = 0; + const wchar_t *pp; + unsigned char *bb = x_malloc(wcslen(value) / 2); + if (!bb) { + rc = ACR_ENOMEM; + break; + } + for (pp = value; *pp; ) { + wchar_t *ep; + unsigned long v = wcstoul(pp, &ep, 16); + + bb[i++] = (unsigned char)v; + pp = ep; + while (*pp && !iswxdigit(*pp)) + pp++; + } + rc = RegSetValueExW(k->key, name, 0, st, bb, i); + x_free(bb); + } + break; + default: + rc = ACR_EBADF; + break; + } + +cleanup: + return rc; +} + ACR_DECLARE(int) RegistryHasA(const char *name) { int i; @@ -399,6 +716,38 @@ return i; } +ACR_DECLARE(int) RegistryHasW(const wchar_t *name) +{ + int i; + HKEY r; + wchar_t *p; + x_registry_t k; + wchar_t *s = NULL; + + if (!(r = wcs_rootnamed(name))) { + return ACR_EINVAL; + } + + if (!(p = wcschr(name, '\\'))) { + return ACR_EINVAL; + } + k.name = x_wcsdup(p + 1); + k.sam = KEY_READ; + k.key = 0; + if ((s = wcsrchr(k.name, L'\\'))) { + *(s++) = L'\0'; + } + else { + x_free(k.name); + return ACR_EINVAL; + } + i = RegOpenKeyExW(r, k.name, 0, k.sam, &k.key); + + SAFE_CLOSE_KEY(k.key); + x_free(k.name); + return i; +} + static REGSAM _regsam_translate(int nsam) { REGSAM rsam = 0; @@ -429,14 +778,6 @@ return rsam; } -static __inline void FS2BS(wchar_t *s) -{ - for (; *s; s++) { - if (*s == L'/') - *s = L'\\'; - } -} - ACR_JNI_PLATFORM_DECLARE(jint, RegistryKey, close0)(ACR_JNISTDARGS, jlong key) { @@ -474,7 +815,7 @@ REGSAM rsam = _regsam_translate(sam); WITH_WSTR(name) { - FS2BS(J2W(name)); + FS2BSW(J2W(name)); rc = RegOpenKeyExW(hkey, J2W(name), 0, @@ -500,7 +841,7 @@ REGSAM rsam = _regsam_translate(sam); WITH_WSTR(name) { - FS2BS(J2W(name)); + FS2BSW(J2W(name)); rc = RegCreateKeyExW(hkey, J2W(name), 0, Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c?rev=897899&r1=897898&r2=897899&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c Mon Jan 11 15:20:50 2010 @@ -234,10 +234,7 @@ * On Win32 for utf8 paths we always use the forwrd slashes. * They are converted to backward on translatio from utf8 */ - for (; *retstr; retstr++) { - if (*retstr == '\\') - *retstr = '/'; - } + BS2FSA(retstr); return 0; } @@ -273,14 +270,11 @@ * On Win32 for utf8 paths we always use the forward slashes. * They are converted to backward on translation from acr. */ - for (; *retstr; retstr++) { - if (*retstr == '\\') - *retstr = '/'; - } + BS2FSW(retstr); return 0; } -int acr_to_unicode_path(wchar_t* retstr, size_t retlen, +int acr_to_unicode_path(wchar_t *retstr, size_t retlen, const wchar_t* srcstr) { /* TODO: The computations could preconvert the string to determine