Bug 455381 - WinCE XPCOM Explicit Unicode API Calls, Wide Char CheckVersion Function r=bsmedberg
authorBrad Lassey <blassey@mozilla.com>
Wed, 03 Dec 2008 08:41:12 -0500
changeset 22235 0f1b8ab7cd8e9568d6dbf71c425102a0f559823d
parent 22234 5d12d7b9ddb6af8ac807bbcdec5ea8e69d78c6cb
child 22236 ce8fbd7d222e0a07dc0d9d9585dfe532732830c3
push id3878
push userblassey@mozilla.com
push dateWed, 03 Dec 2008 13:43:58 +0000
treeherdermozilla-central@20a011760de7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs455381
milestone1.9.2a1pre
Bug 455381 - WinCE XPCOM Explicit Unicode API Calls, Wide Char CheckVersion Function r=bsmedberg
xpcom/base/nsDebugImpl.cpp
xpcom/base/nsStackWalk.cpp
xpcom/build/nsXPCOMPrivate.h
xpcom/glue/nsGREGlue.cpp
xpcom/glue/nsVersionComparator.cpp
xpcom/glue/nsVersionComparator.h
xpcom/glue/standalone/nsGlueLinkingWin.cpp
xpcom/glue/standalone/nsXPCOMGlue.cpp
xpcom/io/SpecialSystemDirectory.cpp
xpcom/io/nsLocalFileWin.cpp
xpcom/windbgdlg/Makefile.in
xpcom/windbgdlg/windbgdlg.cpp
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -61,16 +61,21 @@
 
 #include "nsTraceRefcntImpl.h"
 #include "nsISupportsUtils.h"
 
 #if defined(XP_UNIX)
 #include <signal.h>
 #endif
 
+#if defined(XP_WIN)
+#include <tchar.h>
+#include "nsString.h"
+#endif
+
 static void
 Abort(const char *aMsg);
 
 static void
 Break(const char *aMsg);
 
 #if defined(XP_OS2)
 #  define INCL_WINDIALOGS  // need for WinMessageBox
@@ -92,17 +97,17 @@ Break(const char *aMsg);
 #if defined (_WIN32)
 
 typedef WINBASEAPI BOOL (WINAPI* LPFNISDEBUGGERPRESENT)();
 PRBool InDebugger()
 {
 #ifndef WINCE
    PRBool fReturn = PR_FALSE;
    LPFNISDEBUGGERPRESENT lpfnIsDebuggerPresent = NULL;
-   HINSTANCE hKernel = LoadLibrary("Kernel32.dll");
+   HINSTANCE hKernel = LoadLibraryW(L"Kernel32.dll");
 
    if(hKernel)
       {
       lpfnIsDebuggerPresent = 
          (LPFNISDEBUGGERPRESENT)GetProcAddress(hKernel, "IsDebuggerPresent");
       if(lpfnIsDebuggerPresent)
          {
          fReturn = (*lpfnIsDebuggerPresent)();
@@ -397,34 +402,36 @@ Break(const char *aMsg)
     DWORD code = IDRETRY;
 
     /* Create the debug dialog out of process to avoid the crashes caused by 
      * Windows events leaking into our event loop from an in process dialog.
      * We do this by launching windbgdlg.exe (built in xpcom/windbgdlg).
      * See http://bugzilla.mozilla.org/show_bug.cgi?id=54792
      */
     PROCESS_INFORMATION pi;
-    STARTUPINFO si;
-    char executable[MAX_PATH];
-    char* pName;
+    STARTUPINFOW si;
+    PRUnichar executable[MAX_PATH];
+    PRUnichar* pName;
 
     memset(&pi, 0, sizeof(pi));
 
     memset(&si, 0, sizeof(si));
     si.cb          = sizeof(si);
     si.wShowWindow = SW_SHOW;
 
     // 2nd arg of CreateProcess is in/out
-    char *msgCopy = (char*) _alloca(strlen(aMsg) + 1); 
-    strcpy(msgCopy, aMsg);
+    PRUnichar *msgCopy = (PRUnichar*) _alloca((strlen(aMsg) + 1)*sizeof(PRUnichar));
+    wcscpy(msgCopy  , (PRUnichar*)NS_ConvertUTF8toUTF16(aMsg).get());
 
-    if(GetModuleFileName(GetModuleHandle("xpcom.dll"), executable, MAX_PATH) &&
-       NULL != (pName = strrchr(executable, '\\')) &&
-       NULL != strcpy(pName+1, "windbgdlg.exe") &&
-       CreateProcess(executable, msgCopy, NULL, NULL, PR_FALSE,
+    if(GetModuleFileNameW(GetModuleHandleW(L"xpcom.dll"), (LPWCH)executable, MAX_PATH) &&
+       NULL != (pName = wcsrchr(executable, '\\')) &&
+       NULL != 
+       wcscpy((WCHAR*)
+       pName+1, L"windbgdlg.exe") &&
+       CreateProcessW((LPCWSTR)executable, (LPWSTR)msgCopy, NULL, NULL, PR_FALSE,
                      DETACHED_PROCESS | NORMAL_PRIORITY_CLASS,
                      NULL, NULL, &si, &pi)) {
       WaitForSingleObject(pi.hProcess, INFINITE);
       GetExitCodeProcess(pi.hProcess, &code);
       CloseHandle(pi.hProcess);
       CloseHandle(pi.hThread);
     }
 
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -323,19 +323,19 @@ EnsureImageHlpInitialized()
     ::CloseHandle(hStackWalkThread);
 
     // Wait for the thread's event loop to start before posting events to it.
     ::WaitForSingleObject(readyEvent, INFINITE);
     ::CloseHandle(readyEvent);
 
     ::InitializeCriticalSection(&gDbgHelpCS);
 
-    HMODULE module = ::LoadLibrary("DBGHELP.DLL");
+    HMODULE module = ::LoadLibraryW(L"DBGHELP.DLL");
     if (!module) {
-        module = ::LoadLibrary("IMAGEHLP.DLL");
+        module = ::LoadLibraryW(L"IMAGEHLP.DLL");
         if (!module) return PR_FALSE;
     }
 
     _SymSetOptions = (SYMSETOPTIONSPROC) ::GetProcAddress(module, "SymSetOptions");
     if (!_SymSetOptions) return PR_FALSE;
 
     _SymInitialize = (SYMINITIALIZEPROC) ::GetProcAddress(module, "SymInitialize");
     if (!_SymInitialize) return PR_FALSE;
--- a/xpcom/build/nsXPCOMPrivate.h
+++ b/xpcom/build/nsXPCOMPrivate.h
@@ -212,19 +212,21 @@ NS_GetFrozenFunctions(XPCOMFunctions *en
  *                          modified to include additional search paths.
  * GRE_CONF_NAME          - Name of the GRE Configuration file
  */
 
 #if defined(XP_WIN32) || defined(XP_OS2) || defined(WINCE)
 
 #define XPCOM_SEARCH_KEY  "PATH"
 #define GRE_CONF_NAME     "gre.config"
-#define GRE_WIN_REG_LOC   "Software\\mozilla.org\\GRE"
+#define GRE_WIN_REG_LOC   L"Software\\mozilla.org\\GRE"
 #define XPCOM_DLL         "xpcom.dll"
+#define LXPCOM_DLL        L"xpcom.dll"
 #define XUL_DLL           "xul.dll"
+#define LXUL_DLL          L"xul.dll"
 
 #elif defined(XP_BEOS)
 
 #define XPCOM_SEARCH_KEY  "ADDON_PATH"
 #define GRE_CONF_NAME "gre.config"
 #define GRE_CONF_PATH "gre.conf"
 #define GRE_CONF_DIR  "gre.d"
 #define XPCOM_DLL "libxpcom"MOZ_DLL_SUFFIX
--- a/xpcom/glue/nsGREGlue.cpp
+++ b/xpcom/glue/nsGREGlue.cpp
@@ -41,16 +41,17 @@
 
 #include "nsINIParser.h"
 #include "nsVersionComparator.h"
 #include "nsXPCOMPrivate.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <wchar.h>
 
 #ifdef XP_WIN32
 # include <windows.h>
 # include <mbstring.h>
 # include <io.h>
 # define snprintf _snprintf
 # define R_OK 04
 #elif defined(XP_OS2)
@@ -96,21 +97,28 @@ static PRBool safe_strncat(char *dest, c
     ++dest, ++append;
   }
 
   *dest = '\0';
 
   return *append == '\0';
 }
 
+#ifdef XP_WIN
+static PRBool
+CheckVersion(const PRUnichar* toCheck,
+             const GREVersionRange *versions,
+             PRUint32 versionsLength);
+#endif
 static PRBool
 CheckVersion(const char* toCheck,
              const GREVersionRange *versions,
              PRUint32 versionsLength);
 
+
 #if defined(XP_MACOSX)
 
 static PRBool
 GRE_FindGREFramework(const char* rootPath,
                      const GREVersionRange *versions,
                      PRUint32 versionsLength,
                      const GREProperty *properties,
                      PRUint32 propertiesLength,
@@ -137,17 +145,17 @@ GRE_GetPathFromConfigFile(const char* fi
 #elif defined(XP_WIN)
 
 static PRBool
 GRE_GetPathFromRegKey(HKEY aRegKey,
                       const GREVersionRange *versions,
                       PRUint32 versionsLength,
                       const GREProperty *properties,
                       PRUint32 propertiesLength,
-                      char* buffer, PRUint32 buflen);
+                      PRUnichar* buffer, PRUint32 buflen);
 
 #endif
 
 nsresult
 GRE_GetGREPathWithProperties(const GREVersionRange *versions,
                              PRUint32 versionsLength,
                              const GREProperty *properties,
                              PRUint32 propertiesLength,
@@ -416,38 +424,38 @@ GRE_GetGREPathWithProperties(const GREVe
   //    subkeys such as 1.0, 1.1, 2.0 etc. under it.
   // 2. In this sample below we're looking for the location of GRE version 1.2
   //    i.e. we're compatible with GRE 1.2 and we're trying to find it's install
   //    location.
   //
   // Please see http://www.mozilla.org/projects/embedding/GRE.html for
   // more info.
   //
-  if (::RegOpenKeyEx(HKEY_CURRENT_USER, GRE_WIN_REG_LOC, 0,
-                     KEY_READ, &hRegKey) == ERROR_SUCCESS) {
-    PRBool ok = GRE_GetPathFromRegKey(hRegKey,
-                                      versions, versionsLength,
-                                      allProperties, allPropertiesLength,
-                                      aBuffer, aBufLen);
-    ::RegCloseKey(hRegKey);
+  if (::RegOpenKeyExW(HKEY_CURRENT_USER, GRE_WIN_REG_LOC, 0,
+                      KEY_READ, &hRegKey) == ERROR_SUCCESS) {
+      PRBool ok = GRE_GetPathFromRegKey(hRegKey,
+                                        versions, versionsLength,
+                                        allProperties, allPropertiesLength,
+                                        (WCHAR*) NS_ConvertUTF8toUTF16(aBuffer).get(), aBufLen);
+      ::RegCloseKey(hRegKey);
 
-    if (ok)
-      return NS_OK;
+      if (ok)
+          return NS_OK;
   }
 
-  if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, GRE_WIN_REG_LOC, 0,
-                     KEY_ENUMERATE_SUB_KEYS, &hRegKey) == ERROR_SUCCESS) {
-    PRBool ok = GRE_GetPathFromRegKey(hRegKey,
-                                      versions, versionsLength,
-                                      allProperties, allPropertiesLength,
-                                      aBuffer, aBufLen);
-    ::RegCloseKey(hRegKey);
+  if (::RegOpenKeyExW(HKEY_LOCAL_MACHINE, GRE_WIN_REG_LOC, 0,
+                      KEY_ENUMERATE_SUB_KEYS, &hRegKey) == ERROR_SUCCESS) {
+      PRBool ok = GRE_GetPathFromRegKey(hRegKey,
+                                        versions, versionsLength,
+                                        allProperties, allPropertiesLength,
+                                        (WCHAR*) NS_ConvertUTF8toUTF16(aBuffer).get(), aBufLen);
+      ::RegCloseKey(hRegKey);
 
-    if (ok)
-      return NS_OK;
+      if (ok)
+          return NS_OK;
   }
 #endif
 
   return NS_ERROR_FAILURE;
 }
 
 static PRBool
 CheckVersion(const char* toCheck,
@@ -473,16 +481,48 @@ CheckVersion(const char* toCheck,
       continue;
 
     return PR_TRUE;
   }
 
   return PR_FALSE;
 }
 
+#ifdef XP_WIN
+static PRBool
+CheckVersion(const PRUnichar* toCheck,
+             const GREVersionRange *versions,
+             PRUint32 versionsLength)
+{
+  
+  for (const GREVersionRange *versionsEnd = versions + versionsLength;
+       versions < versionsEnd;
+       ++versions) {
+      PRInt32 c = NS_CompareVersions(toCheck, NS_ConvertUTF8toUTF16(versions->lower).get());
+      if (c < 0)
+        continue;
+
+      if (!c && !versions->lowerInclusive)
+        continue;
+
+      c = NS_CompareVersions(toCheck, NS_ConvertUTF8toUTF16(versions->upper).get());
+      if (c > 0)
+        continue;
+
+      if (!c && !versions->upperInclusive)
+        continue;
+
+      return PR_TRUE;
+  }
+
+  return PR_FALSE;
+}
+#endif
+
+
 #ifdef XP_MACOSX
 PRBool
 GRE_FindGREFramework(const char* rootPath,
                      const GREVersionRange *versions,
                      PRUint32 versionsLength,
                      const GREProperty *properties,
                      PRUint32 propertiesLength,
                      char* buffer, PRUint32 buflen)
@@ -636,46 +676,46 @@ GRE_GetPathFromConfigFile(const char* fi
 
   parser.GetSections(CheckINIHeader, &c);
   return c.found;
 }
 
 #elif defined(XP_WIN)
 
 static PRBool
-CopyWithEnvExpansion(char* aDest, const char* aSource, PRUint32 aBufLen,
+CopyWithEnvExpansion(PRUnichar* aDest, const PRUnichar* aSource, PRUint32 aBufLen,
                      DWORD aType)
 {
   switch (aType) {
   case REG_SZ:
-    if (strlen(aSource) >= aBufLen)
+    if (wcslen(aSource) >= aBufLen)
       return PR_FALSE;
 
-    strcpy(aDest, aSource);
+    wcscpy(aDest, aSource);
     return PR_TRUE;
 
   case REG_EXPAND_SZ:
-    if (ExpandEnvironmentStrings(aSource, aDest, aBufLen) > aBufLen)
+    if (ExpandEnvironmentStringsW(aSource, aDest, aBufLen) > aBufLen)
       return PR_FALSE;
 
     return PR_TRUE;
   };
 
   // Whoops! We expected REG_SZ or REG_EXPAND_SZ, what happened here?
 
   return PR_FALSE;
 }
 
 PRBool
 GRE_GetPathFromRegKey(HKEY aRegKey,
                       const GREVersionRange *versions,
                       PRUint32 versionsLength,
                       const GREProperty *properties,
                       PRUint32 propertiesLength,
-                      char* aBuffer, PRUint32 aBufLen)
+                      PRUnichar* aBuffer, PRUint32 aBufLen)
 {
   // Formerly, GREs were registered at the registry key
   // HKLM/Software/mozilla.org/GRE/<version> valuepair GreHome=Path.
   // Nowadays, they are registered in any subkey of
   // Software/mozilla.org/GRE, with the following valuepairs:
   //   Version=<version> (REG_SZ)
   //   GreHome=<path>    (REG_SZ or REG_EXPAND_SZ)
   //   <Property>=<value> (REG_SZ)
@@ -689,63 +729,64 @@ GRE_GetPathFromRegKey(HKEY aRegKey,
   // with older glue. If this key is already taken (i.e. there is more than
   // one GRE of that version installed), it should append a unique number to
   // the version, for example:
   //   1.1 (already in use), 1.1_1, 1.1_2, etc...
 
   DWORD i = 0;
 
   while (PR_TRUE) {
-    char name[MAXPATHLEN + 1];
+    PRUnichar name[MAXPATHLEN + 1];
     DWORD nameLen = MAXPATHLEN;
-    if (::RegEnumKeyEx(aRegKey, i, name, &nameLen, NULL, NULL, NULL, NULL) !=
-        ERROR_SUCCESS) {
-      break;
+    if (::RegEnumKeyExW(aRegKey, i, name, &nameLen, NULL, NULL, NULL, NULL) !=
+          ERROR_SUCCESS) {
+        break;
     }
 
     HKEY subKey = NULL;
-    if (::RegOpenKeyEx(aRegKey, name, 0, KEY_QUERY_VALUE, &subKey) !=
-        ERROR_SUCCESS) {
-      continue;
+    if (::RegOpenKeyExW(aRegKey, name, 0, KEY_QUERY_VALUE, &subKey) !=
+          ERROR_SUCCESS) {
+        continue;
     }
 
-    char version[40];
+    PRUnichar version[40];
     DWORD versionlen = 40;
-    char pathbuf[MAXPATHLEN];
+    PRUnichar pathbuf[MAXPATHLEN];
     DWORD pathlen;
     DWORD pathtype;
 
     PRBool ok = PR_FALSE;
 
-    if (::RegQueryValueEx(subKey, "Version", NULL, NULL,
-                          (BYTE*) version, &versionlen) == ERROR_SUCCESS &&
-        CheckVersion(version, versions, versionsLength)) {
+    if (::RegQueryValueExW(subKey, L"Version", NULL, NULL,
+                           (BYTE*) version, &versionlen) == ERROR_SUCCESS &&
+          CheckVersion(version, versions, versionsLength)) {
 
       ok = PR_TRUE;
       const GREProperty *props = properties;
       const GREProperty *propsEnd = properties + propertiesLength;
       for (; ok && props < propsEnd; ++props) {
         pathlen = sizeof(pathbuf);
 
-        if (::RegQueryValueEx(subKey, props->property, NULL, &pathtype,
-                              (BYTE*) pathbuf, &pathlen) != ERROR_SUCCESS ||
-            strcmp(pathbuf, props->value))
-          ok = PR_FALSE;
+        if (::RegQueryValueExW(subKey, NS_ConvertUTF8toUTF16(props->property).get(), NULL, &pathtype,
+                               (BYTE*) pathbuf, &pathlen) != ERROR_SUCCESS ||
+              wcscmp(pathbuf,  NS_ConvertUTF8toUTF16(props->value).get()))
+            ok = PR_FALSE;
       }
 
       pathlen = sizeof(pathbuf);
       if (ok &&
-          (!::RegQueryValueEx(subKey, "GreHome", NULL, &pathtype,
+          (!::RegQueryValueExW(subKey, L"GreHome", NULL, &pathtype,
                               (BYTE*) pathbuf, &pathlen) == ERROR_SUCCESS ||
            !*pathbuf ||
            !CopyWithEnvExpansion(aBuffer, pathbuf, aBufLen, pathtype))) {
         ok = PR_FALSE;
       }
-      else if (!safe_strncat(aBuffer, "\\" XPCOM_DLL, aBufLen) ||
-               access(aBuffer, R_OK)) {
+      else if (!wcsncat(aBuffer, L"\\" LXPCOM_DLL, aBufLen) ||
+               _waccess(
+                        aBuffer, R_OK)) {
         ok = PR_FALSE;
       }
     }
 
     RegCloseKey(subKey);
 
     if (ok)
       return PR_TRUE;
--- a/xpcom/glue/nsVersionComparator.cpp
+++ b/xpcom/glue/nsVersionComparator.cpp
@@ -34,28 +34,46 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsVersionComparator.h"
 
 #include <stdlib.h>
 #include <string.h>
+#ifdef XP_WIN
+#include <wchar.h>
+#include "nsStringGlue.h"
+#endif
 
 struct VersionPart {
   PRInt32     numA;
 
   const char *strB;    // NOT null-terminated, can be a null pointer
   PRUint32    strBlen;
 
   PRInt32     numC;
 
   char       *extraD;  // null-terminated
 };
 
+#ifdef XP_WIN
+struct VersionPartW {
+  PRInt32     numA;
+
+  const PRUnichar *strB;    // NOT null-terminated, can be a null pointer
+  PRUint32    strBlen;
+
+  PRInt32     numC;
+
+  PRUnichar       *extraD;  // null-terminated
+
+};
+#endif
+
 /**
  * Parse a version part into a number and "extra text".
  *
  * @returns A pointer to the next versionpart, or null if none.
  */
 static char*
 ParseVP(char *part, VersionPart &result)
 {
@@ -114,16 +132,88 @@ ParseVP(char *part, VersionPart &result)
 
     if (!*dot)
       dot = nsnull;
   }
 
   return dot;
 }
 
+
+/**
+ * Parse a version part into a number and "extra text".
+ *
+ * @returns A pointer to the next versionpart, or null if none.
+ */
+#ifdef XP_WIN
+static PRUnichar*
+ParseVP(PRUnichar *part, VersionPartW &result)
+{
+
+  PRUnichar *dot;
+
+  result.numA = 0;
+  result.strB = nsnull;
+  result.strBlen = 0;
+  result.numC = 0;
+  result.extraD = nsnull;
+
+  if (!part)
+    return part;
+
+  dot = wcschr(part, '.');
+  if (dot)
+    *dot = '\0';
+
+  if (part[0] == '*' && part[1] == '\0') {
+    result.numA = PR_INT32_MAX;
+    result.strB = L"";
+  }
+  else {
+    result.numA = wcstol(part, const_cast<PRUnichar**>(&result.strB), 10);
+  }
+
+  if (!*result.strB) {
+    result.strB = nsnull;
+    result.strBlen = 0;
+  }
+  else {
+    if (result.strB[0] == '+') {
+      static const PRUnichar kPre[] = L"pre";
+
+      ++result.numA;
+      result.strB = kPre;
+      result.strBlen = sizeof(kPre) - 1;
+    }
+    else {
+      const PRUnichar *numstart = wcspbrk(result.strB, L"0123456789+-");
+      if (!numstart) {
+	result.strBlen = wcslen(result.strB);
+      }
+      else {
+	result.strBlen = numstart - result.strB;
+
+	result.numC = wcstol(numstart, &result.extraD, 10);
+	if (!*result.extraD)
+	  result.extraD = nsnull;
+      }
+    }
+  }
+
+  if (dot) {
+    ++dot;
+
+    if (!*dot)
+      dot = nsnull;
+  }
+
+  return dot;
+}
+#endif
+
 // compare two null-terminated strings, which may be null pointers
 static PRInt32
 ns_strcmp(const char *str1, const char *str2)
 {
   // any string is *before* no string
   if (!str1)
     return str2 != 0;
 
@@ -184,16 +274,74 @@ CompareVP(VersionPart &v1, VersionPart &
 
   r = ns_cmp(v1.numC, v2.numC);
   if (r)
     return r;
 
   return ns_strcmp(v1.extraD, v2.extraD);
 }
 
+/**
+ * Compares two VersionParts
+ */
+#ifdef XP_WIN
+static PRInt32
+CompareVP(VersionPartW &v1, VersionPartW &v2)
+{
+  PRInt32 r = ns_cmp(v1.numA, v2.numA);
+  if (r)
+    return r;
+
+  r = wcsncmp(v1.strB, v2.strB, PR_MIN(v1.strBlen,v2.strBlen));
+  if (r)
+    return r;
+
+  r = ns_cmp(v1.numC, v2.numC);
+  if (r)
+    return r;
+
+  return wcscmp(v1.extraD, v2.extraD);
+}
+
+
+PRInt32
+NS_CompareVersions(const PRUnichar *A, const PRUnichar *B)
+{
+  PRUnichar *A2 = wcsdup(A);
+  if (!A2)
+    return 1;
+
+  PRUnichar *B2 = wcsdup(B);
+  if (!B2) {
+    free(A2);
+    return 1;
+  }
+
+  PRInt32 result;
+  PRUnichar *a = A2, *b = B2;
+
+  do {
+    VersionPartW va, vb;
+
+    a = ParseVP(a, va);
+    b = ParseVP(b, vb);
+
+    result = CompareVP(va, vb);
+    if (result)
+      break;
+
+  } while (a || b);
+
+  free(A2);
+  free(B2);
+
+  return result;
+}
+#endif
+
 PRInt32
 NS_CompareVersions(const char *A, const char *B)
 {
   char *A2 = strdup(A);
   if (!A2)
     return 1;
 
   char *B2 = strdup(B);
--- a/xpcom/glue/nsVersionComparator.h
+++ b/xpcom/glue/nsVersionComparator.h
@@ -41,11 +41,19 @@
 #include "nscore.h"
 
 /**
  * Compare two version strings.
  *
  * @see nsIVersionComparator
  */
 PRInt32 NS_COM_GLUE
+NS_CompareVersions(const PRUnichar *A, const PRUnichar *B);
+
+/**
+ * Compare two version strings.
+ *
+ * @see nsIVersionComparator
+ */
+PRInt32 NS_COM_GLUE
 NS_CompareVersions(const char *A, const char *B);
 
 #endif // nsVersionComparator_h__
--- a/xpcom/glue/standalone/nsGlueLinkingWin.cpp
+++ b/xpcom/glue/standalone/nsGlueLinkingWin.cpp
@@ -34,19 +34,21 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsGlueLinking.h"
 #include "nsXPCOMGlue.h"
 
+#include "nsStringAPI.h"
 #include <windows.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <tchar.h>
 
 struct DependentLib
 {
     HINSTANCE     libHandle;
     DependentLib *next;
 };
 
 static DependentLib *sTop;
@@ -63,18 +65,19 @@ AppendDependentLib(HINSTANCE libHandle)
     d->libHandle = libHandle;
 
     sTop = d;
 }
 
 static void
 ReadDependentCB(const char *aDependentLib)
 {
+    
     HINSTANCE h =
-        LoadLibraryEx(aDependentLib, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+        LoadLibraryExW(NS_ConvertUTF8toUTF16(aDependentLib).get(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
     if (!h)
         return;
 
     AppendDependentLib(h);
 }
 
 // like strpbrk but finds the *last* char, not the first
 static char*
@@ -88,45 +91,126 @@ ns_strrpbrk(char *string, const char *st
                 // Since we're looking for the last char, we save "found"
                 // until we're at the end of the string.
             }
         }
     }
 
     return found;
 }
-
-GetFrozenFunctionsFunc
-XPCOMGlueLoad(const char *xpcomFile)
+// like strpbrk but finds the *last* char, not the first
+static wchar_t*
+ns_wcspbrk(wchar_t *string, const wchar_t *strCharSet)
 {
-    if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
-        xpcomFile = XPCOM_DLL;
-    }
-    else {
-        char xpcomDir[MAXPATHLEN];
-
-        _fullpath(xpcomDir, xpcomFile, sizeof(xpcomDir));
-        char *lastSlash = ns_strrpbrk(xpcomDir, "/\\");
-        if (lastSlash) {
-            *lastSlash = '\0';
-
-            XPCOMGlueLoadDependentLibs(xpcomDir, ReadDependentCB);
-
-            _snprintf(lastSlash, MAXPATHLEN - strlen(xpcomDir), "\\" XUL_DLL);
-
-            sXULLibrary =
-                LoadLibraryEx(xpcomDir, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    wchar_t *found = NULL;
+    for (; *string; ++string) {
+        for (const wchar_t *search = strCharSet; *search; ++search) {
+            if (*search == *string) {
+                found = string;
+                // Since we're looking for the last char, we save "found"
+                // until we're at the end of the string.
+            }
         }
     }
 
-    HINSTANCE h =
-        LoadLibraryEx(xpcomFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    return found;
+}
+
+bool ns_isRelPath(wchar_t* path)
+{
+#ifdef WINCE
+    if (path[0] == '\\')
+        return false;
+#else
+    if (path[1] == ':')
+        return false;
+#endif
+    return true;
+    
+}
+
+GetFrozenFunctionsFunc
+XPCOMGlueLoad(const char *aXpcomFile)
+{
+    wchar_t xpcomFile[MAXPATHLEN];
+    MultiByteToWideChar(CP_ACP, 0, aXpcomFile,-1,
+                        xpcomFile, MAXPATHLEN);
+   
+    
+    if (xpcomFile[0] == '.' && xpcomFile[1] == '\0') {
+        wcscpy(xpcomFile, LXPCOM_DLL);
+    }
+    else {
+        wchar_t xpcomDir[MAXPATHLEN];
+        
+        if (ns_isRelPath(xpcomFile))
+        {
+            _wfullpath
+                (xpcomDir, xpcomFile, sizeof(xpcomDir));
+        } 
+        else 
+        {
+            wcscpy(xpcomDir, xpcomFile);
+        }
+        wchar_t *lastSlash = ns_wcspbrk(xpcomDir, L"/\\");
+        if (lastSlash) {
+            *lastSlash = '\0';
+            char xpcomDir_narrow[MAXPATHLEN];
+            WideCharToMultiByte(CP_ACP, 0, xpcomDir,-1,
+                                xpcomDir_narrow, MAX_PATH, NULL, NULL);
 
-    if (!h)
+            XPCOMGlueLoadDependentLibs(xpcomDir_narrow, ReadDependentCB);
+            
+            _snwprintf(lastSlash, MAXPATHLEN - wcslen(xpcomDir), L"\\" LXUL_DLL);
+            sXULLibrary =
+                LoadLibraryExW(xpcomDir, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+
+#ifdef DEBUG
+            if (!sXULLibrary) 
+            {
+                LPVOID lpMsgBuf;
+                FormatMessage(
+                              FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                              FORMAT_MESSAGE_FROM_SYSTEM |
+                              FORMAT_MESSAGE_IGNORE_INSERTS,
+                              NULL,
+                              GetLastError(),
+                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                              (LPTSTR) &lpMsgBuf,
+                              0,
+                              NULL
+                              );
+                wprintf(L"Error loading xul.dll: %s\n", lpMsgBuf);
+            }
+#endif //DEBUG                
+        }
+    }
+    HINSTANCE h =
+        LoadLibraryExW(xpcomFile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+
+
+    if (!h) 
+    {
+#ifdef DEBUG
+        LPVOID lpMsgBuf;
+        FormatMessage(
+                      FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                      FORMAT_MESSAGE_FROM_SYSTEM |
+                      FORMAT_MESSAGE_IGNORE_INSERTS,
+                      NULL,
+                      GetLastError(),
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                      (LPTSTR) &lpMsgBuf,
+                      0,
+                      NULL
+                      );
+        wprintf(L"Error loading xpcom.dll: %s\n", lpMsgBuf);
+#endif        
         return nsnull;
+    }
 
     AppendDependentLib(h);
 
     GetFrozenFunctionsFunc sym =
         (GetFrozenFunctionsFunc) GetProcAddress(h, "NS_GetFrozenFunctions");
 
     if (!sym)
         XPCOMGlueUnload();
--- a/xpcom/glue/standalone/nsXPCOMGlue.cpp
+++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp
@@ -61,16 +61,17 @@ nsresult XPCOMGlueStartup(const char* xp
 {
     xpcomFunctions.version = XPCOM_GLUE_VERSION;
     xpcomFunctions.size    = sizeof(XPCOMFunctions);
 
     GetFrozenFunctionsFunc func = nsnull;
 
     if (!xpcomFile)
         xpcomFile = XPCOM_DLL;
+    
 
     func = XPCOMGlueLoad(xpcomFile);
 
     if (!func)
         return NS_ERROR_FAILURE;
 
     nsresult rv = (*func)(&xpcomFunctions, nsnull);
     if (NS_FAILED(rv)) {
--- a/xpcom/io/SpecialSystemDirectory.cpp
+++ b/xpcom/io/SpecialSystemDirectory.cpp
@@ -122,17 +122,17 @@ static nsGetKnownFolderPath gGetKnownFol
 static HINSTANCE gShell32DLLInst = NULL;
 #endif
 
 NS_COM void StartupSpecialSystemDirectory()
 {
 #if defined (XP_WIN)
     // SHGetKnownFolderPath is only available on Windows Vista
     // so that we need to use GetProcAddress to get the pointer.
-    gShell32DLLInst = LoadLibrary("Shell32.dll");
+    gShell32DLLInst = LoadLibraryW(L"shell32.dll");
     if(gShell32DLLInst)
     {
         gGetKnownFolderPath = (nsGetKnownFolderPath) 
             GetProcAddress(gShell32DLLInst, "SHGetKnownFolderPath");
     }
 #endif
 }
 
--- a/xpcom/io/nsLocalFileWin.cpp
+++ b/xpcom/io/nsLocalFileWin.cpp
@@ -57,17 +57,20 @@
 #include "prmem.h"
 #include "nsHashKeys.h"
 
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 
 #include <direct.h>
 #include <windows.h>
+
+#ifndef WINCE
 #include <aclapi.h>
+#endif
 
 #include "shellapi.h"
 #include "shlguid.h"
 
 #include  <io.h>
 #include  <stdio.h>
 #include  <stdlib.h>
 #include  <mbstring.h>
@@ -105,18 +108,18 @@ public:
     NS_DECL_NSISIMPLEENUMERATOR
     nsresult Init();
 private:
     /* mDrives and mLetter share data
      * Init sets them.
      * HasMoreElements reads mLetter.
      * GetNext advances mLetter.
      */
-    nsCString mDrives;
-    const char *mLetter;
+    nsString mDrives;
+    const PRUnichar *mLetter;
 };
 
 //----------------------------------------------------------------------------
 // short cut resolver
 //----------------------------------------------------------------------------
 class ShortcutResolver
 {
 public:
@@ -2985,17 +2988,17 @@ nsresult nsDriveEnumerator::Init()
 {
     /* If the length passed to GetLogicalDriveStrings is smaller
      * than the length of the string it would return, it returns
      * the length required for the string. */
     DWORD length = GetLogicalDriveStrings(0, 0);
     /* The string is null terminated */
     if (!EnsureStringLength(mDrives, length+1))
         return NS_ERROR_OUT_OF_MEMORY;
-    if (!GetLogicalDriveStrings(length, mDrives.BeginWriting()))
+    if (!GetLogicalDriveStringsW(length, mDrives.BeginWriting()))
         return NS_ERROR_FAILURE;
     mLetter = mDrives.get();
     return NS_OK;
 }
 
 NS_IMETHODIMP nsDriveEnumerator::HasMoreElements(PRBool *aHasMore)
 {
     *aHasMore = *mLetter != '\0';
@@ -3005,17 +3008,17 @@ NS_IMETHODIMP nsDriveEnumerator::HasMore
 NS_IMETHODIMP nsDriveEnumerator::GetNext(nsISupports **aNext)
 {
     /* GetLogicalDrives stored in mLetter is a concatenation
      * of null terminated strings, followed by a null terminator. */
     if (!*mLetter) {
         *aNext = nsnull;
         return NS_OK;
     }
-    NS_ConvertASCIItoUTF16 drive(mLetter);
+    nsString drive(mDrives);
     mLetter += drive.Length() + 1;
     nsILocalFile *file;
     nsresult rv = NS_NewLocalFile(drive, PR_FALSE, &file);
 
     *aNext = file;
     return rv;
 }
 #endif
--- a/xpcom/windbgdlg/Makefile.in
+++ b/xpcom/windbgdlg/Makefile.in
@@ -41,10 +41,12 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 SIMPLE_PROGRAMS	= windbgdlg$(BIN_SUFFIX)
 
 CPPSRCS		= windbgdlg.cpp
 
+OS_LIBS += $(call EXPAND_LIBNAME, shell32)
+
 include $(topsrcdir)/config/rules.mk
 
--- a/xpcom/windbgdlg/windbgdlg.cpp
+++ b/xpcom/windbgdlg/windbgdlg.cpp
@@ -37,16 +37,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* Windows only app to show a modal debug dialog - launched by nsDebug.cpp */
 
 #include <windows.h>
 #include <stdlib.h>
+#include <shellapi.h>
 
 int WINAPI 
 WinMain(HINSTANCE  hInstance, HINSTANCE  hPrevInstance, 
         LPSTR  lpszCmdLine, int  nCmdShow)
 {
     /* support for auto answering based on words in the assertion.
      * the assertion message is sent as a series of arguements (words) to the commandline.
      * set a "word" to 0xffffffff to let the word not affect this code.
@@ -54,38 +55,39 @@ WinMain(HINSTANCE  hInstance, HINSTANCE 
      * set a "word" to 0x5 to ignore (program should continue).
      * set a "word" to 0x4 to retry (should fall into debugger).
      * set a "word" to 0x3 to abort (die).
      */
     DWORD regType;
     DWORD regValue = -1;
     DWORD regLength = sizeof regValue;
     HKEY hkeyCU, hkeyLM;
-    RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyCU);
-    RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyLM);
-    const char * const * argv = __argv;
-    for (int i = __argc - 1; regValue == (DWORD)-1 && i; --i) {
+    RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyCU);
+    RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\mozilla.org\\windbgdlg", 0, KEY_READ, &hkeyLM);
+    int argc =0;
+    LPWSTR *argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+    for (int i = argc - 1; regValue == (DWORD)-1 && i; --i) {
         bool ok = false;
         if (hkeyCU)
-            ok = RegQueryValueEx(hkeyCU, argv[i], 0, &regType, (LPBYTE)&regValue, &regLength) == ERROR_SUCCESS;
+            ok = RegQueryValueExW(hkeyCU, argv[i], 0, &regType, (LPBYTE)&regValue, &regLength) == ERROR_SUCCESS;
         if (!ok && hkeyLM)
-            ok = RegQueryValueEx(hkeyLM, argv[i], 0, &regType, (LPBYTE)&regValue, &regLength) == ERROR_SUCCESS;
+            ok = RegQueryValueExW(hkeyLM, argv[i], 0, &regType, (LPBYTE)&regValue, &regLength) == ERROR_SUCCESS;
         if (!ok)
             regValue = -1;
     }
     if (hkeyCU)
         RegCloseKey(hkeyCU);
     if (hkeyLM)
         RegCloseKey(hkeyLM);
     if (regValue != (DWORD)-1 && regValue != (DWORD)-2)
         return regValue;
-    static char msg[4048];
+    static WCHAR msg[4048];
 
-    wsprintf(msg,
-             "%s\n\nClick Abort to exit the Application.\n"
-             "Click Retry to Debug the Application..\n"
-             "Click Ignore to continue running the Application.", 
+    wsprintfW(msg,
+             L"%s\n\nClick Abort to exit the Application.\n"
+             L"Click Retry to Debug the Application..\n"
+             L"Click Ignore to continue running the Application.", 
              lpszCmdLine);
              
-    return MessageBox(NULL, msg, "NSGlue_Assertion",
+    return MessageBoxW(NULL, msg, L"NSGlue_Assertion",
                       MB_ICONSTOP | MB_SYSTEMMODAL| 
                       MB_ABORTRETRYIGNORE | MB_DEFBUTTON3);
 }