summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordarin%meer.net <devnull@localhost>2006-03-10 05:38:31 +0000
committerdarin%meer.net <devnull@localhost>2006-03-10 05:38:31 +0000
commit1beb411c0945c04e35adab953345c9ab49b6f68e (patch)
treec955addd037a6ee608c2e85397846e02e5884dbb
parent388734830e1a0934ecffec96230cf6466b8c2a01 (diff)
downloadnspr-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.h3
-rw-r--r--pr/include/prlink.h13
-rw-r--r--pr/include/prtypes.h7
-rw-r--r--pr/src/linking/prlink.c224
-rw-r--r--pr/src/md/windows/w95io.c25
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)
{