diff options
author | darin%meer.net <devnull@localhost> | 2006-03-10 05:38:31 +0000 |
---|---|---|
committer | darin%meer.net <devnull@localhost> | 2006-03-10 05:38:31 +0000 |
commit | 1beb411c0945c04e35adab953345c9ab49b6f68e (patch) | |
tree | c955addd037a6ee608c2e85397846e02e5884dbb | |
parent | 388734830e1a0934ecffec96230cf6466b8c2a01 (diff) | |
download | nspr-hg-LIGHTNING_0_1_RELEASE.tar.gz |
fixes bug 326168 "Add a UTF-16 API to load a library" patch by jshin1987@gmail.com r=wtc,darinLIGHTNING_0_1_RELEASE
-rw-r--r-- | pr/include/md/_win95.h | 3 | ||||
-rw-r--r-- | pr/include/prlink.h | 13 | ||||
-rw-r--r-- | pr/include/prtypes.h | 7 | ||||
-rw-r--r-- | pr/src/linking/prlink.c | 224 | ||||
-rw-r--r-- | pr/src/md/windows/w95io.c | 25 |
5 files changed, 257 insertions, 15 deletions
diff --git a/pr/include/md/_win95.h b/pr/include/md/_win95.h index 083d0200..a36b5b8e 100644 --- a/pr/include/md/_win95.h +++ b/pr/include/md/_win95.h @@ -273,8 +273,9 @@ extern PRInt32 _MD_CloseFile(PROsfd osfd); #define _MD_TLOCKFILE _PR_MD_TLOCKFILE #define _MD_UNLOCKFILE _PR_MD_UNLOCKFILE -#ifdef MOZ_UNICODE /* --- UTF16 IO stuff --- */ +extern PRBool _pr_useUnicode; +#ifdef MOZ_UNICODE #define _MD_OPEN_FILE_UTF16 _PR_MD_OPEN_FILE_UTF16 #define _MD_OPEN_DIR_UTF16 _PR_MD_OPEN_DIR_UTF16 #define _MD_READ_DIR_UTF16 _PR_MD_READ_DIR_UTF16 diff --git a/pr/include/prlink.h b/pr/include/prlink.h index b2eb5141..0ef3d7ff 100644 --- a/pr/include/prlink.h +++ b/pr/include/prlink.h @@ -118,15 +118,16 @@ NSPR_API(PRLibrary*) PR_LoadLibrary(const char *name); ** in a library, if code fragments are supported by the OS. ** A code fragment can be specified by name or by an integer index. ** -** Right now PRLibSpec supports three types of library specification: -** a pathname, a Mac code fragment by name, and a Mac code fragment -** by index. +** Right now PRLibSpec supports four types of library specification: +** a pathname in the native charset, a Mac code fragment by name, +** a Mac code fragment by index, and a UTF-16 pathname. */ typedef enum PRLibSpecType { PR_LibSpec_Pathname, PR_LibSpec_MacNamedFragment, /* obsolete (for Mac OS Classic) */ - PR_LibSpec_MacIndexedFragment /* obsolete (for Mac OS Classic) */ + PR_LibSpec_MacIndexedFragment, /* obsolete (for Mac OS Classic) */ + PR_LibSpec_PathnameU /* supported only on Win32 */ } PRLibSpecType; struct FSSpec; /* Mac OS FSSpec */ @@ -148,6 +149,9 @@ typedef struct PRLibSpec { const struct FSSpec *fsspec; PRUint32 index; } mac_indexed_fragment; /* obsolete (for Mac OS Classic) */ + + /* if type is PR_LibSpec_PathnameU */ + const PRUnichar *pathname_u; /* supported only on Win32 */ } value; } PRLibSpec; @@ -161,6 +165,7 @@ typedef struct PRLibSpec { #define PR_LD_NOW 0x2 /* equivalent to RTLD_NOW on Unix */ #define PR_LD_GLOBAL 0x4 /* equivalent to RTLD_GLOBAL on Unix */ #define PR_LD_LOCAL 0x8 /* equivalent to RTLD_LOCAL on Unix */ +/* 0x400 reserved for NSPR internal use */ /* ** Load the specified library, in the manner specified by 'flags'. diff --git a/pr/include/prtypes.h b/pr/include/prtypes.h index 157da93a..c7369a06 100644 --- a/pr/include/prtypes.h +++ b/pr/include/prtypes.h @@ -474,19 +474,14 @@ typedef PRUint8 PRPackedBool; */ typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus; -#ifdef MOZ_UNICODE -/* - * EXPERIMENTAL: This type may be removed in a future release. - */ #ifndef __PRUNICHAR__ #define __PRUNICHAR__ -#if defined(WIN32) || defined(XP_MAC) +#if (defined(__MWERKS__) || defined(_MSC_VER)) && defined(WIN32) typedef wchar_t PRUnichar; #else typedef PRUint16 PRUnichar; #endif #endif -#endif /* MOZ_UNICODE */ /* ** WARNING: The undocumented data types PRWord and PRUword are diff --git a/pr/src/linking/prlink.c b/pr/src/linking/prlink.c index e6e7d64c..a23bc599 100644 --- a/pr/src/linking/prlink.c +++ b/pr/src/linking/prlink.c @@ -157,6 +157,10 @@ struct _imcb *IAC$GL_IMAGE_LIST = NULL; #define NEED_LEADING_UNDERSCORE #endif +#ifdef WIN32 +#define PR_LD_PATHW 0x400 /* for PR_LibSpec_PathnameU */ +#endif + /************************************************************************/ struct PRLibrary { @@ -204,6 +208,16 @@ static char* _pr_currentLibPath = NULL; static PRLibrary *pr_LoadLibraryByPathname(const char *name, PRIntn flags); +#ifdef WIN95 +typedef HMODULE (WINAPI *LoadLibraryWFn)(LPCWSTR); +static HMODULE WINAPI EmulateLoadLibraryW(LPCWSTR); +static LoadLibraryWFn loadLibraryW = LoadLibraryW; +#endif + +#ifdef WIN32 +static int pr_ConvertUTF16toUTF8(LPCWSTR wname, LPSTR name, int len); +#endif + /************************************************************************/ #if !defined(USE_DLFCN) && !defined(HAVE_STRERROR) @@ -244,6 +258,12 @@ void _PR_InitLinker(void) void *h; #endif +#ifdef WIN95 + if (!_pr_useUnicode) { + loadLibraryW = EmulateLoadLibraryW; + } +#endif + if (!pr_linker_lock) { pr_linker_lock = PR_NewNamedMonitor("linker-lock"); } @@ -556,6 +576,16 @@ PR_LoadLibraryWithFlags(PRLibSpec libSpec, PRIntn flags) switch (libSpec.type) { case PR_LibSpec_Pathname: return pr_LoadLibraryByPathname(libSpec.value.pathname, flags); +#ifdef WIN32 + case PR_LibSpec_PathnameU: + /* + * cast to |char *| and set PR_LD_PATHW flag so that + * it can be cast back to PRUnichar* in the callee. + */ + return pr_LoadLibraryByPathname((const char*) + libSpec.value.pathname_u, + flags | PR_LD_PATHW); +#endif default: PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); return NULL; @@ -752,6 +782,25 @@ pr_LoadViaDyld(const char *name, PRLibrary *lm) #endif /* XP_MACOSX */ +#ifdef WIN95 +static HMODULE WINAPI +EmulateLoadLibraryW(LPCWSTR lpLibFileName) +{ + HMODULE h; + char nameA[MAX_PATH]; + + if (!WideCharToMultiByte(CP_ACP, 0, lpLibFileName, -1, + nameA, sizeof nameA, NULL, NULL)) { + return NULL; + } + /* Perhaps it's better to add a check for characters + * not representable in CP_ACP. + */ + h = LoadLibraryA(nameA); + return h; +} +#endif /* WIN95 */ + /* ** Dynamically load a library. Only load libraries once, so scan the load ** map first. @@ -762,13 +811,48 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) PRLibrary *lm; PRLibrary* result; PRInt32 oserr; +#ifdef WIN32 + char utf8name_stack[MAX_PATH]; + PRUnichar wname_stack[MAX_PATH]; + char *utf8name = utf8name_stack; + PRUnichar *wname = wname_stack; + int len; +#endif if (!_pr_initialized) _PR_ImplicitInitialization(); /* See if library is already loaded */ PR_EnterMonitor(pr_linker_lock); +#ifdef WIN32 + if (flags & PR_LD_PATHW) { + /* cast back what's cast to |char *| for the argument passing. */ + wname = (LPWSTR) name; + } else { + int wlen = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0); + if (wlen > MAX_PATH) + wname = PR_Malloc(wlen); + if (wname == NULL || + !MultiByteToWideChar(CP_ACP, 0, name, -1, wname, wlen)) { + oserr = _MD_ERRNO(); + goto unlock; + } + } + len = pr_ConvertUTF16toUTF8(wname, NULL, 0); + if (len > MAX_PATH) + utf8name = PR_Malloc(len); + if (utf8name == NULL || + !pr_ConvertUTF16toUTF8(wname, utf8name, len)) { + oserr = _MD_ERRNO(); + goto unlock; + } + /* the list of loaded library names are always kept in UTF-8 + * on Win32 platforms */ + result = pr_UnlockedFindLibrary(utf8name); +#else result = pr_UnlockedFindLibrary(name); +#endif + if (result != NULL) goto unlock; lm = PR_NEWZAP(PRLibrary); @@ -801,13 +885,31 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) { HINSTANCE h; +#ifdef WIN32 +#ifdef WIN95 + if (flags & PR_LD_PATHW) + h = loadLibraryW(wname); + else + h = LoadLibraryA(name); +#else + if (flags & PR_LD_PATHW) + h = LoadLibraryW(wname); + else + h = LoadLibraryA(name); +#endif /* WIN95 */ +#else h = LoadLibrary(name); +#endif if (h < (HINSTANCE)HINSTANCE_ERROR) { oserr = _MD_ERRNO(); PR_DELETE(lm); goto unlock; } +#ifdef WIN32 + lm->name = strdup(utf8name); +#else lm->name = strdup(name); +#endif lm->dlh = h; lm->next = pr_loadmap; pr_loadmap = lm; @@ -1008,10 +1110,132 @@ pr_LoadLibraryByPathname(const char *name, PRIntn flags) PR_SetError(PR_LOAD_LIBRARY_ERROR, oserr); DLLErrorInternal(oserr); /* sets error text */ } +#ifdef WIN32 + if (utf8name && utf8name != utf8name_stack) + PR_Free(utf8name); + if (!(flags & PR_LD_PATHW) && wname && wname != wname_stack) + PR_Free(wname); +#endif PR_ExitMonitor(pr_linker_lock); return result; } +#ifdef WIN32 +#ifdef WIN95 +/* + * CP_UTF8 is not supported by WideCharToMultiByte on Windows 95 so that + * we have to emulate it + */ +static PRStatus +pr_ConvertSingleCharToUTF8(PRUint32 usv, PRUint16 offset, int bufLen, + int *utf8Len, char * *buf) +{ + /* XXX No error checking. Add it for debug build */ + char* p = *buf; + /*if (!bufLen || !*buf) { */ + if (!bufLen) { + *utf8Len += offset; + return PR_SUCCESS; + } + + if (*utf8Len + offset >= bufLen) + return PR_FAILURE; + + *utf8Len += offset; + if (offset == 1) { + *p++ = (char) usv; + } else if (offset == 2) { + *p++ = (char)0xc0 | (usv >> 6); + *p++ = (char)0x80 | (usv & 0x003f); + } else if (offset == 3) { + *p++ = (char)0xe0 | (usv >> 12); + *p++ = (char)0x80 | ((usv >> 6) & 0x003f); + *p++ = (char)0x80 | (usv & 0x003f); + } else { /* offset = 4 */ + *p++ = (char)0xf0 | (usv >> 18); + *p++ = (char)0x80 | ((usv >> 12) & 0x003f); + *p++ = (char)0x80 | ((usv >> 6) & 0x003f); + *p++ = (char)0x80 | (usv & 0x003f); + } + + *buf = p; + return PR_SUCCESS; +} + +static int pr_ConvertUTF16toUTF8(LPCWSTR wname, LPSTR name, int len) +{ + LPCWSTR pw = wname; + LPSTR p = name; + int utf8Len = 0; + PRBool highSurrogate = PR_FALSE; + + /* Windows NT4/2k/XP supports CP_UTF8. So do Win 98/ME, but + * we don't bother to optimize for them. */ + if (_pr_useUnicode) + return WideCharToMultiByte(CP_UTF8, 0, wname, -1, name, len, + NULL, NULL); + + if (!wname || len < 0 || (len > 0 && !name)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + while (*pw) { + PRStatus status = PR_SUCCESS; + if (highSurrogate) { + if (*pw >= (PRUnichar) 0xDC00 && *pw < (PRUnichar) 0xE000) { + /* found a matching low surrogate */ + /* convert a surrogate pair to UCS4 */ + PRUint32 usv = ((*(pw-1) - (PRUnichar)0xD800) << 10) + + (*pw - (PRUnichar)0xDC00) + (PRUint32)0x10000; + if (pr_ConvertSingleCharToUTF8(usv, 4, len, &utf8Len, &p) == + PR_FAILURE) + return 0; + highSurrogate = PR_FALSE; + ++pw; + continue; + } else { + /* + * silently ignore a lone high surrogate + * as is done by WideCharToMultiByte by default + */ + highSurrogate = PR_FALSE; + } + } + if (*pw <= 0x7f) + status = pr_ConvertSingleCharToUTF8(*pw, 1, len, &utf8Len, &p); + else if (*pw <= 0x07ff) + status = pr_ConvertSingleCharToUTF8(*pw, 2, len, &utf8Len, &p); + else if (*pw < (PRUnichar) 0xD800 || *pw >= (PRUnichar) 0xE000) + status = pr_ConvertSingleCharToUTF8(*pw, 3, len, &utf8Len, &p); + else if (*pw < (PRUnichar) 0xDC00) + highSurrogate = PR_TRUE; + /* else */ + /* silently ignore a lone low surrogate as is done by + * WideCharToMultiByte by default */ + + if (status == PR_FAILURE) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + ++pw; + } + + /* if we're concerned with a lone high surrogate, + * we have to take care of it here, but we just drop it + */ + if (len > 0) + *p = '\0'; + return utf8Len + 1; +} +#else +static int pr_ConvertUTF16toUTF8(LPCWSTR wname, LPSTR name, int len) +{ + return WideCharToMultiByte(CP_UTF8, 0, wname, -1, name, len, NULL, NULL); +} +#endif /* WIN95 */ +#endif /* WIN32 */ + /* ** Unload a shared library which was loaded via PR_LoadLibrary */ diff --git a/pr/src/md/windows/w95io.c b/pr/src/md/windows/w95io.c index 81be67b1..84641cca 100644 --- a/pr/src/md/windows/w95io.c +++ b/pr/src/md/windows/w95io.c @@ -81,9 +81,7 @@ static const PRTime _pr_filetime_offset = 116444736000000000LL; static const PRTime _pr_filetime_offset = 116444736000000000i64; #endif -#ifdef MOZ_UNICODE static void InitUnicodeSupport(void); -#endif static PRBool IsPrevCharSlash(const char *str, const char *current); @@ -124,9 +122,7 @@ _PR_MD_INIT_IO() _PR_NT_InitSids(); -#ifdef MOZ_UNICODE InitUnicodeSupport(); -#endif } PRStatus @@ -1130,6 +1126,10 @@ static GetFullPathNameWFn getFullPathNameW = GetFullPathNameW; typedef UINT (WINAPI *GetDriveTypeWFn) (LPCWSTR); static GetDriveTypeWFn getDriveTypeW = GetDriveTypeW; +#endif /* MOZ_UNICODE */ + +PRBool _pr_useUnicode = PR_FALSE; + static void InitUnicodeSupport(void) { /* @@ -1137,8 +1137,25 @@ static void InitUnicodeSupport(void) * ERROR_CALL_NOT_IMPLEMENTED error. We plan to emulate the * MSLU W functions on Win9x in the future. */ + + /* Find out if we are running on a Unicode enabled version of Windows */ + OSVERSIONINFOA osvi = {0}; + + osvi.dwOSVersionInfoSize = sizeof(osvi); + if (GetVersionExA(&osvi)) { + _pr_useUnicode = (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT); + } else { + _pr_useUnicode = PR_FALSE; + } +#ifdef DEBUG + /* In debug builds, allow explicit use of ANSI methods for testing. */ + if (getenv("WINAPI_USE_ANSI")) + _pr_useUnicode = PR_FALSE; +#endif } +#ifdef MOZ_UNICODE + /* ================ UTF16 Interfaces ================================ */ void FlipSlashesW(PRUnichar *cp, size_t len) { |