bug 162361 : Unicode file i/o in XPCOM/IO (cannot open files whose names contain characters outside the current locale: e.g. Japanese/Chinese on French Windows) : r/sr=darin, r=bsmedberg

This commit is contained in:
jshin%mailaps.org 2006-03-22 04:26:30 +00:00
parent f2f9ff880f
commit ebc7ee6742
12 changed files with 1816 additions and 629 deletions

View File

@ -979,6 +979,11 @@ nsXREDirProvider::GetUserDataDirectory(nsILocalFile** aFile, PRBool aLocal)
#error dont_know_how_to_get_product_dir_on_your_platform
#endif
#ifdef DEBUG_jungshik
nsCAutoString cwd;
localDir->GetNativePath(cwd);
printf("nsXREDirProvider::GetUserDataDirectory: %s\n", cwd.get());
#endif
rv = EnsureDirectoryExists(localDir);
NS_ENSURE_SUCCESS(rv, rv);
@ -993,8 +998,19 @@ nsXREDirProvider::EnsureDirectoryExists(nsIFile* aDirectory)
PRBool exists;
nsresult rv = aDirectory->Exists(&exists);
NS_ENSURE_SUCCESS(rv, rv);
#ifdef DEBUG_jungshik
if (!exists) {
nsCAutoString cwd;
aDirectory->GetNativePath(cwd);
printf("nsXREDirProvider::EnsureDirectoryExists: %s does not\n", cwd.get());
}
#endif
if (!exists)
rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0700);
#ifdef DEBUG_jungshik
if (NS_FAILED(rv))
NS_WARNING("nsXREDirProvider::EnsureDirectoryExists: create failed");
#endif
return rv;
}

View File

@ -46,6 +46,7 @@
#include "nsIEventQueueService.h"
#include "nsIEventQueue.h"
#include "nsComponentManagerUtils.h"
#include "nsNativeCharsetUtils.h"
#include <objbase.h>
#include <initguid.h>
@ -181,37 +182,6 @@ LRESULT CALLBACK DetectWindowMove(int code, WPARAM wParam, LPARAM lParam)
#define MAX_MENU_NAME 128
#define MAX_FILTER_NAME 256
int ConvertAtoW(LPCSTR aStrInA, int aBufferSize, LPWSTR aStrOutW)
{
return MultiByteToWideChar(CP_ACP, 0, aStrInA, -1, aStrOutW, aBufferSize) ;
}
int ConvertWtoA(LPCWSTR aStrInW, int aBufferSizeOut, LPSTR aStrOutA)
{
if ((!aStrInW) || (!aStrOutA) || (aBufferSizeOut <= 0))
return 0;
int numCharsConverted = WideCharToMultiByte(CP_ACP, 0, aStrInW, -1,
aStrOutA, aBufferSizeOut, "?", NULL);
if (!numCharsConverted) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Overflow, add missing null termination but return 0
aStrOutA[aBufferSizeOut-1] = '\0';
}
else {
// Other error, clear string and return 0
aStrOutA[0] = '\0';
}
}
else if (numCharsConverted < aBufferSizeOut) {
// Add 2nd null (really necessary?)
aStrOutA[numCharsConverted] = '\0';
}
return numCharsConverted;
}
BOOL CallOpenSaveFileNameA(LPOPENFILENAMEW aFileNameW, BOOL aOpen)
{
BOOL rtn;
@ -252,13 +222,14 @@ BOOL CallOpenSaveFileNameA(LPOPENFILENAMEW aFileNameW, BOOL aOpen)
ofnA.lpstrFilter = filterA;
}
if (aFileNameW->lpstrCustomFilter) {
ConvertWtoA(aFileNameW->lpstrCustomFilter, MAX_FILTER_NAME, customFilterA);
NS_ConvertWtoA(aFileNameW->lpstrCustomFilter, MAX_FILTER_NAME,
customFilterA, "?");
ofnA.lpstrCustomFilter = customFilterA;
ofnA.nMaxCustFilter = MAX_FILTER_NAME;
}
ofnA.nFilterIndex = aFileNameW->nFilterIndex; // Index of pair of filter strings. Should be ok.
if (aFileNameW->lpstrFile) {
ConvertWtoA(aFileNameW->lpstrFile, FILE_BUFFER_SIZE, fileA);
NS_ConvertWtoA(aFileNameW->lpstrFile, FILE_BUFFER_SIZE, fileA, "?");
ofnA.lpstrFile = fileA;
ofnA.nMaxFile = FILE_BUFFER_SIZE;
if (strlen(fileA)) {
@ -269,27 +240,28 @@ BOOL CallOpenSaveFileNameA(LPOPENFILENAMEW aFileNameW, BOOL aOpen)
}
}
if (aFileNameW->lpstrFileTitle) {
ConvertWtoA(aFileNameW->lpstrFileTitle, MAX_PATH, fileTitleA);
NS_ConvertWtoA(aFileNameW->lpstrFileTitle, MAX_PATH, fileTitleA, "?");
ofnA.lpstrFileTitle = fileTitleA;
ofnA.nMaxFileTitle = MAX_PATH;
}
if (aFileNameW->lpstrInitialDir) {
ConvertWtoA(aFileNameW->lpstrInitialDir, MAX_PATH, initDirA);
NS_ConvertWtoA(aFileNameW->lpstrInitialDir, MAX_PATH, initDirA, "?");
ofnA.lpstrInitialDir = initDirA;
}
if (aFileNameW->lpstrTitle) {
ConvertWtoA(aFileNameW->lpstrTitle, MAX_PATH, titleA);
NS_ConvertWtoA(aFileNameW->lpstrTitle, MAX_PATH, titleA, "?");
ofnA.lpstrTitle = titleA;
}
ofnA.Flags = aFileNameW->Flags;
if (aFileNameW->lpstrDefExt) {
ConvertWtoA(aFileNameW->lpstrDefExt, MAX_PATH, defExtA);
NS_ConvertWtoA(aFileNameW->lpstrDefExt, MAX_PATH, defExtA, "?");
ofnA.lpstrDefExt = defExtA;
}
ofnA.lCustData = aFileNameW->lCustData; // Warning: No WtoA() is done to application-defined data
// Warning: No WtoA() is done to application-defined data
ofnA.lCustData = aFileNameW->lCustData;
ofnA.lpfnHook = aFileNameW->lpfnHook;
if (aFileNameW->lpTemplateName) {
ConvertWtoA(aFileNameW->lpTemplateName, MAX_PATH, tempNameA);
NS_ConvertWtoA(aFileNameW->lpTemplateName, MAX_PATH, tempNameA, "?");
ofnA.lpTemplateName = tempNameA;
}
@ -319,7 +291,7 @@ BOOL CallOpenSaveFileNameA(LPOPENFILENAMEW aFileNameW, BOOL aOpen)
aFileNameW->lpstrFile[lenW+1] = '\0';
}
else {
ConvertAtoW(ofnA.lpstrFile, aFileNameW->nMaxFile, aFileNameW->lpstrFile);
NS_ConvertAtoW(ofnA.lpstrFile, aFileNameW->nMaxFile, aFileNameW->lpstrFile);
}
}
@ -345,7 +317,7 @@ int WINAPI nsGetClassName(HWND aWnd, LPWSTR aClassName, int aMaxCount)
if (!GetClassNameA(aWnd, classNameA, MAX_CLASS_NAME))
return 0;
aMaxCount = ConvertAtoW(classNameA, MAX_CLASS_NAME, aClassName);
aMaxCount = NS_ConvertAtoW(classNameA, MAX_CLASS_NAME, aClassName);
return aMaxCount;
}
@ -368,9 +340,9 @@ HWND WINAPI nsCreateWindowEx(DWORD aExStyle,
// Convert class name and Window name from Unicode to ANSI
if (aClassNameW)
ConvertWtoA(aClassNameW, MAX_CLASS_NAME, classNameA);
NS_ConvertWtoA(aClassNameW, MAX_CLASS_NAME, classNameA, "?");
if (aWindowNameW)
ConvertWtoA(aWindowNameW, MAX_CLASS_NAME, windowNameA);
NS_ConvertWtoA(aWindowNameW, MAX_CLASS_NAME, windowNameA, "?");
// so far only NULL is passed
if (aParam != NULL) {
@ -393,7 +365,7 @@ LRESULT WINAPI nsSendMessage(HWND aWnd, UINT aMsg, WPARAM awParam, LPARAM alPara
if (WM_SETTEXT == aMsg) {
char title[MAX_PATH];
if (alParam) // Note: Window titles are truncated to 159 chars by Windows
ConvertWtoA((LPCWSTR)alParam, MAX_PATH, title);
NS_ConvertWtoA((LPCWSTR)alParam, MAX_PATH, title, "?");
return SendMessageA(aWnd, aMsg, awParam, (LPARAM)&title);
}
@ -421,11 +393,11 @@ ATOM WINAPI nsRegisterClass(const WNDCLASSW *aClassW)
wClass.lpszClassName = classNameA;
if (aClassW->lpszClassName)
ConvertWtoA(aClassW->lpszClassName, MAX_CLASS_NAME, classNameA);
NS_ConvertWtoA(aClassW->lpszClassName, MAX_CLASS_NAME, classNameA, "?");
wClass.lpszMenuName = menuNameA;
if (aClassW->lpszMenuName)
ConvertWtoA(aClassW->lpszMenuName, MAX_MENU_NAME, menuNameA);
NS_ConvertWtoA(aClassW->lpszMenuName, MAX_MENU_NAME, menuNameA, "?");
return RegisterClassA(&wClass);
}
@ -435,7 +407,7 @@ BOOL WINAPI nsUnregisterClass(LPCWSTR aClassW, HINSTANCE aInst)
char classA[MAX_PATH+1];
if (aClassW) {
ConvertWtoA(aClassW, MAX_PATH, classA);
NS_ConvertWtoA(aClassW, MAX_PATH, classA, "?");
return UnregisterClassA((LPCSTR)classA, aInst);
}
return FALSE;
@ -447,9 +419,9 @@ BOOL WINAPI nsSHGetPathFromIDList(LPCITEMIDLIST aIdList, LPWSTR aPathW)
char pathA[MAX_PATH+1];
if (aPathW) {
ConvertWtoA(aPathW, MAX_PATH, pathA);
NS_ConvertWtoA(aPathW, MAX_PATH, pathA, "?");
if (SHGetPathFromIDListA(aIdList, pathA)) {
ConvertAtoW(pathA, MAX_PATH, aPathW);
NS_ConvertAtoW(pathA, MAX_PATH, aPathW);
return TRUE;
}
}
@ -468,11 +440,11 @@ LPITEMIDLIST WINAPI nsSHBrowseForFolder(LPBROWSEINFOW aBiW)
biA.hwndOwner = aBiW->hwndOwner;
biA.pidlRoot = aBiW->pidlRoot;
if (aBiW->pszDisplayName) {
ConvertWtoA(aBiW->pszDisplayName, MAX_PATH, displayNameA);
NS_ConvertWtoA(aBiW->pszDisplayName, MAX_PATH, displayNameA, "?");
biA.pszDisplayName = displayNameA;
}
if (aBiW->lpszTitle) {
ConvertWtoA(aBiW->lpszTitle, MAX_PATH, titleA);
NS_ConvertWtoA(aBiW->lpszTitle, MAX_PATH, titleA, "?");
biA.lpszTitle = titleA;
}
biA.ulFlags = aBiW->ulFlags;
@ -482,7 +454,7 @@ LPITEMIDLIST WINAPI nsSHBrowseForFolder(LPBROWSEINFOW aBiW)
itemIdList = SHBrowseForFolderA(&biA);
if (biA.pszDisplayName) {
ConvertAtoW(biA.pszDisplayName, MAX_PATH, aBiW->pszDisplayName);
NS_ConvertAtoW(biA.pszDisplayName, MAX_PATH, aBiW->pszDisplayName);
}
return itemIdList;
}

View File

@ -88,6 +88,7 @@ ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
CPPSRCS += nsLocalFileOSX.cpp
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
CPPSRCS += nsWinAPIs.cpp
CPPSRCS += nsLocalFileWin.cpp
else
CPPSRCS += nsLocalFileUnix.cpp
@ -119,7 +120,7 @@ ifneq (,$(filter mac cocoa,$(MOZ_WIDGET_TOOLKIT)))
EXPORTS += nsLocalFileOSX.h
else
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
EXPORTS += nsLocalFileWin.h
EXPORTS += nsLocalFileWin.h nsWinAPIs.h
else
EXPORTS += nsLocalFileUnix.h
endif # windows

View File

@ -24,6 +24,7 @@
* Doug Turner <dougt@netscape.com>
* IBM Corp.
* Fredrik Holmqvist <thesuckiestemail@yahoo.se>
* Jungshik Shin <jshin@i18nl10n.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -45,6 +46,8 @@
#if defined(XP_WIN)
#include "nsNativeCharsetUtils.h"
#include "nsWinAPIs.h"
#include <windows.h>
#include <shlobj.h>
#include <stdlib.h>
@ -111,9 +114,24 @@
#endif
#if defined (XP_WIN)
typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath, int nFolder, BOOL fCreate);
GetSpecialPathProc gGetSpecialPathProc = NULL;
typedef BOOL (WINAPI * GetSpecialPathProc) (HWND hwndOwner, LPSTR lpszPath,
int nFolder, BOOL fCreate);
typedef BOOL (WINAPI * nsGetSpecialFolderPathW) (HWND hwndOwner,
LPWSTR lpszPath,
int nFolder, BOOL fCreate);
typedef BOOL (WINAPI * nsGetSpecialFolderPathA) (HWND hwndOwner,
LPSTR lpszPath, int nFolder,
BOOL fCreate);
static GetSpecialPathProc gGetSpecialPathProc = NULL;
static nsGetSpecialFolderPathA gGetSpecialFolderPathA = NULL;
static nsGetSpecialFolderPathW gGetSpecialFolderPath = NULL;
static HINSTANCE gShell32DLLInst = NULL;
static BOOL WINAPI NS_GetSpecialFolderPath(HWND hwndOwner, LPWSTR aPath,
int aFolder, BOOL fCreate);
#endif
NS_COM void StartupSpecialSystemDirectory()
{
@ -123,13 +141,24 @@ NS_COM void StartupSpecialSystemDirectory()
startup. Replacing these older calls with a single call to SHGetSpecialFolderPath
effectively removes these calls from the performace radar. We need to
support the older way of file location lookup on systems that do not have
IE4. (Note: gets the ansi version: SHGetSpecialFolderPathA).
IE4.
*/
gShell32DLLInst = LoadLibrary("Shell32.dll");
if(gShell32DLLInst)
{
gGetSpecialPathProc = (GetSpecialPathProc) GetProcAddress(gShell32DLLInst,
"SHGetSpecialFolderPathA");
if (NS_UseUnicode())
{
gGetSpecialFolderPath = (nsGetSpecialFolderPathW)
GetProcAddress(gShell32DLLInst, "SHGetSpecialFolderPathW");
}
else
{
gGetSpecialFolderPathA = (nsGetSpecialFolderPathA)
GetProcAddress(gShell32DLLInst, "SHGetSpecialFolderPathA");
// need to check because it's not available on Win95 without IE.
if (gGetSpecialFolderPathA)
gGetSpecialFolderPath = NS_GetSpecialFolderPath;
}
}
#endif
}
@ -137,12 +166,12 @@ NS_COM void StartupSpecialSystemDirectory()
NS_COM void ShutdownSpecialSystemDirectory()
{
#if defined (XP_WIN)
if (gShell32DLLInst)
{
FreeLibrary(gShell32DLLInst);
gShell32DLLInst = NULL;
gGetSpecialPathProc = NULL;
}
if (gShell32DLLInst)
{
FreeLibrary(gShell32DLLInst);
gShell32DLLInst = NULL;
gGetSpecialFolderPath = NULL;
}
#endif
}
@ -152,29 +181,27 @@ NS_COM void ShutdownSpecialSystemDirectory()
static nsresult GetWindowsFolder(int folder, nsILocalFile** aFile)
//----------------------------------------------------------------------------------------
{
if (gGetSpecialPathProc) {
TCHAR path[MAX_PATH];
HRESULT result = gGetSpecialPathProc(NULL, path, folder, true);
if (gGetSpecialFolderPath) { // With MS IE 4.0 or higher
WCHAR path[MAX_PATH + 2];
HRESULT result = gGetSpecialFolderPath(NULL, path, folder, true);
if (!SUCCEEDED(result))
return NS_ERROR_FAILURE;
// Append the trailing slash
int len = strlen(path);
if (len>1 && path[len-1] != '\\')
int len = wcslen(path);
if (len > 1 && path[len - 1] != L'\\')
{
path[len] = '\\';
path[len + 1] = '\0';
path[len] = L'\\';
path[++len] = L'\0';
}
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path, len), PR_TRUE, aFile);
}
nsresult rv = NS_ERROR_FAILURE;
LPMALLOC pMalloc = NULL;
LPSTR pBuffer = NULL;
LPWSTR pBuffer = NULL;
LPITEMIDLIST pItemIDList = NULL;
int len;
@ -183,26 +210,25 @@ static nsresult GetWindowsFolder(int folder, nsILocalFile** aFile)
return NS_ERROR_FAILURE;
// Allocate a buffer
if ((pBuffer = (LPSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
return NS_ERROR_FAILURE;
if ((pBuffer = (LPWSTR) pMalloc->Alloc(MAX_PATH + 2)) == NULL)
return NS_ERROR_OUT_OF_MEMORY;
// Get the PIDL for the folder.
if (!SUCCEEDED(SHGetSpecialFolderLocation(
NULL, folder, &pItemIDList)))
if (!SUCCEEDED(SHGetSpecialFolderLocation(NULL, folder, &pItemIDList)))
goto Clean;
if (!SUCCEEDED(SHGetPathFromIDList(pItemIDList, pBuffer)))
if (!SUCCEEDED(nsWinAPIs::mSHGetPathFromIDList(pItemIDList, pBuffer)))
goto Clean;
// Append the trailing slash
len = strlen(pBuffer);
pBuffer[len] = '\\';
pBuffer[len + 1] = '\0';
len = wcslen(pBuffer);
pBuffer[len] = L'\\';
pBuffer[++len] = L'\0';
// Assign the directory
rv = NS_NewNativeLocalFile(nsDependentCString(pBuffer),
PR_TRUE,
aFile);
rv = NS_NewLocalFile(nsDependentString(pBuffer, len),
PR_TRUE,
aFile);
Clean:
// Clean up.
@ -216,6 +242,27 @@ Clean:
return rv;
}
// Assume that this function is always invoked with aPath with the capacity
// no smaller than MAX_PATH. It's possible because it's only referred to in
// this file and we have made sure that they're indeed.
static BOOL WINAPI NS_GetSpecialFolderPath(HWND hwndOwner,
LPWSTR aPath,
int aFolder, BOOL fCreate)
{
char path[MAX_PATH];
if (gGetSpecialFolderPathA(hwndOwner, path, aFolder, fCreate))
{
if (NS_ConvertAtoW(path, 0, aPath) > MAX_PATH)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return NS_ConvertAtoW(path, MAX_PATH, aPath) ? TRUE : FALSE;
}
return FALSE;
}
#endif // XP_WIN
#if defined (XP_BEOS)
@ -268,16 +315,23 @@ GetUnixHomeDir(nsILocalFile** aFile)
nsresult
GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
nsILocalFile** aFile)
nsILocalFile** aFile)
{
#if defined(XP_WIN)
WCHAR path[MAX_PATH];
#else
char path[MAXPATHLEN];
#endif
switch (aSystemSystemDirectory)
{
case OS_CurrentWorkingDirectory:
#if defined(XP_WIN)
if (!_getcwd(path, MAXPATHLEN))
if (!nsWinAPIs::mGetCwd(path, MAX_PATH))
return NS_ERROR_FAILURE;
return NS_NewLocalFile(nsDependentString(path),
PR_TRUE,
aFile);
#elif defined(XP_OS2)
if (DosQueryPathInfo( ".", FIL_QUERYFULLNAME, path, MAXPATHLEN))
return NS_ERROR_FAILURE;
@ -285,23 +339,25 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
if(!getcwd(path, MAXPATHLEN))
return NS_ERROR_FAILURE;
#endif
#if !defined(XP_WIN)
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
#endif
case OS_DriveDirectory:
#if defined (XP_WIN)
{
PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
if (len)
{
if ( path[1] == ':' && path[2] == '\\' )
path[3] = 0;
}
PRInt32 len = nsWinAPIs::mGetWindowsDirectory(path, MAX_PATH);
if (len == 0)
break;
if (path[1] == PRUnichar(':') && path[2] == PRUnichar('\\'))
path[3] = 0;
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path),
PR_TRUE,
aFile);
}
#elif defined(XP_OS2)
{
@ -325,10 +381,12 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
case OS_TemporaryDirectory:
#if defined (XP_WIN) && !defined (WINCE)
{
DWORD len = GetTempPath(_MAX_PATH, path);
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
DWORD len = nsWinAPIs::mGetTempPath(MAX_PATH, path);
if (len == 0)
break;
return NS_NewLocalFile(nsDependentString(path, len),
PR_TRUE,
aFile);
}
#elif defined (WINCE)
{
@ -381,33 +439,33 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
#if defined (XP_WIN)
case Win_SystemDirectory:
{
PRInt32 len = GetSystemDirectory( path, _MAX_PATH );
PRInt32 len = nsWinAPIs::mGetSystemDirectory(path, MAX_PATH);
// Need enough space to add the trailing backslash
if (len > _MAX_PATH-2)
if (!len || len > MAX_PATH - 2)
break;
path[len] = '\\';
path[len+1] = '\0';
path[len] = L'\\';
path[++len] = L'\0';
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path, len),
PR_TRUE,
aFile);
}
case Win_WindowsDirectory:
{
PRInt32 len = GetWindowsDirectory( path, _MAX_PATH );
PRInt32 len = nsWinAPIs::mGetWindowsDirectory(path, MAX_PATH);
// Need enough space to add the trailing backslash
if (len > _MAX_PATH-2)
if (!len || len > MAX_PATH - 2)
break;
path[len] = '\\';
path[len+1] = '\0';
path[len] = L'\\';
path[++len] = L'\0';
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path, len),
PR_TRUE,
aFile);
}
case Win_ProgramFiles:
@ -417,39 +475,46 @@ GetSpecialSystemDirectory(SystemDirectories aSystemSystemDirectory,
case Win_HomeDirectory:
{
if (GetEnvironmentVariable(TEXT("HOME"), path, _MAX_PATH) > 0)
PRInt32 len;
if ((len =
nsWinAPIs::mGetEnvironmentVariable(L"HOME", path,
MAX_PATH)) > 0)
{
PRInt32 len = strlen(path);
// Need enough space to add the trailing backslash
if (len > _MAX_PATH - 2)
if (len > MAX_PATH - 2)
break;
path[len] = '\\';
path[len+1] = '\0';
path[len] = L'\\';
path[++len] = L'\0';
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path, len),
PR_TRUE,
aFile);
}
if (GetEnvironmentVariable(TEXT("HOMEDRIVE"), path, _MAX_PATH) > 0)
len = nsWinAPIs::mGetEnvironmentVariable(L"HOMEDRIVE",
path, MAX_PATH);
if (0 < len && len < MAX_PATH)
{
char temp[_MAX_PATH];
if (GetEnvironmentVariable(TEXT("HOMEPATH"), temp, _MAX_PATH) > 0)
strncat(path, temp, _MAX_PATH);
WCHAR temp[MAX_PATH];
DWORD len2 = nsWinAPIs::mGetEnvironmentVariable(L"HOMEPATH",
temp,
MAX_PATH);
if (0 < len2 && len + len2 < MAX_PATH)
wcsncat(path, temp, len2);
PRInt32 len = strlen(path);
len = wcslen(path);
// Need enough space to add the trailing backslash
if (len > _MAX_PATH - 2)
if (len > MAX_PATH - 2)
break;
path[len] = '\\';
path[len+1] = '\0';
path[len] = L'\\';
path[++len] = L'\0';
return NS_NewNativeLocalFile(nsDependentCString(path),
PR_TRUE,
aFile);
return NS_NewLocalFile(nsDependentString(path, len),
PR_TRUE,
aFile);
}
}
case Win_Desktop:

View File

@ -57,6 +57,7 @@
#include <Processes.h>
#include <Gestalt.h>
#elif defined(XP_WIN)
#include "nsWinAPIs.h"
#include <windows.h>
#include <shlobj.h>
#include <stdlib.h>
@ -156,14 +157,15 @@ nsDirectoryService::GetCurrentProcessDirectory(nsILocalFile** aFile)
#ifdef XP_WIN
char buf[MAX_PATH];
if ( ::GetModuleFileName(0, buf, sizeof(buf)) ) {
// chop of the executable name by finding the rightmost backslash
char* lastSlash = PL_strrchr(buf, '\\');
PRUnichar buf[MAX_PATH];
if ( nsWinAPIs::mGetModuleFileName(0, buf, sizeof(buf)) )
{
// chop off the executable name by finding the rightmost backslash
PRUnichar* lastSlash = wcsrchr(buf, L'\\');
if (lastSlash)
*(lastSlash + 1) = '\0';
localFile->InitWithNativePath(nsDependentCString(buf));
*(lastSlash + 1) = L'\0';
localFile->InitWithPath(nsDependentString(buf));
*aFile = localFile;
return NS_OK;
}

View File

@ -61,7 +61,7 @@ void NS_ShutdownLocalFile()
nsLocalFile::GlobalShutdown();
}
#if !defined(XP_MAC) && !defined(XP_MACOSX)
#if !defined(XP_MAC) && !defined(XP_MACOSX) && !defined(XP_WIN)
NS_IMETHODIMP
nsLocalFile::InitWithFile(nsILocalFile *aFile)
{

File diff suppressed because it is too large Load Diff

View File

@ -99,14 +99,15 @@ private:
PRPackedBool mFollowSymlinks; // should we follow symlinks when working on this file
// this string will always be in native format!
nsCString mWorkingPath;
// this will be the resolved path of shortcuts, it will *NEVER* be returned to the user
nsCString mResolvedPath;
nsString mWorkingPath;
// this will be the resolved path of shortcuts, it will *NEVER*
// be returned to the user
nsString mResolvedPath;
// this string, if not empty, is the *short* pathname that represents
// mWorkingPath
nsCString mShortWorkingPath;
nsString mShortWorkingPath;
PRFileInfo64 mFileInfo64;
@ -117,12 +118,16 @@ private:
void EnsureShortPath();
nsresult CopyMove(nsIFile *newParentDir, const nsACString &newName, PRBool followSymlinks, PRBool move);
nsresult CopySingleFile(nsIFile *source, nsIFile* dest, const nsACString &newName, PRBool followSymlinks, PRBool move);
nsresult CopyMove(nsIFile *newParentDir, const nsAString &newName,
PRBool followSymlinks, PRBool move);
nsresult CopySingleFile(nsIFile *source, nsIFile* dest,
const nsAString &newName,
PRBool followSymlinks, PRBool move);
nsresult SetModDate(PRInt64 aLastModifiedTime, const char *filePath);
nsresult SetModDate(PRInt64 aLastModifiedTime, const PRUnichar *filePath);
nsresult HasFileAttribute(DWORD fileAttrib, PRBool *_retval);
nsresult AppendNativeInternal(const nsAFlatCString &node, PRBool multipleComponents);
nsresult AppendInternal(const nsAFlatString &node,
PRBool multipleComponents);
};
#endif

View File

@ -134,6 +134,7 @@ utf16_to_isolatin1(const PRUnichar **input, PRUint32 *inputLeft, char **output,
#include <langinfo.h> // nl_langinfo
#include <iconv.h> // iconv_open, iconv, iconv_close
#include <errno.h>
#include "plstr.h"
#if defined(HAVE_ICONV_WITH_CONST_INPUT)
#define ICONV_INPUT(x) (x)
@ -931,14 +932,40 @@ NS_CopyUnicodeToNative(const nsAString &input, nsACString &output)
return NS_OK;
}
void
NS_StartupNativeCharsetUtils()
// moved from widget/src/windows/nsToolkit.cpp
NS_COM PRInt32
NS_ConvertAtoW(const char *aStrInA, int aBufferSize, PRUnichar *aStrOutW)
{
return MultiByteToWideChar(CP_ACP, 0, aStrInA, -1, aStrOutW, aBufferSize);
}
void
NS_ShutdownNativeCharsetUtils()
NS_COM PRInt32
NS_ConvertWtoA(const PRUnichar *aStrInW, int aBufferSizeOut,
char *aStrOutA, const char *aDefault)
{
if ((!aStrInW) || (!aStrOutA) || (aBufferSizeOut <= 0))
return 0;
int numCharsConverted = WideCharToMultiByte(CP_ACP, 0, aStrInW, -1,
aStrOutA, aBufferSizeOut,
aDefault, NULL);
if (!numCharsConverted) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Overflow, add missing null termination but return 0
aStrOutA[aBufferSizeOut-1] = '\0';
}
else {
// Other error, clear string and return 0
aStrOutA[0] = '\0';
}
}
else if (numCharsConverted < aBufferSizeOut) {
// Add 2nd null (really necessary?)
aStrOutA[numCharsConverted] = '\0';
}
return numCharsConverted;
}
//-----------------------------------------------------------------------------

View File

@ -54,6 +54,15 @@
/**
* thread-safe conversion routines that do not depend on uconv libraries.
*/
#if defined(XP_WIN)
#include "prtypes.h"
NS_COM PRInt32 NS_ConvertAtoW(const char *aStrInA, int aBufferSize,
PRUnichar *aStrOutW);
// For path names, the default char cannot be '?', so we use '_' instead.
NS_COM PRInt32 NS_ConvertWtoA(const PRUnichar *aStrInW, int aBufferSizeOut,
char *aStrOutA, const char *aDefault="_");
#endif
NS_COM nsresult NS_CopyNativeToUnicode(const nsACString &input, nsAString &output);
NS_COM nsresult NS_CopyUnicodeToNative(const nsAString &input, nsACString &output);

647
xpcom/io/nsWinAPIs.cpp Normal file
View File

@ -0,0 +1,647 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Jungshik Shin
* <jshin@i18nl10n.com>. Portions created by the Initial Developer
* are Copyright (C) 2006 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* 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 "nscore.h"
#include "nsString.h"
#include "nsNativeCharsetUtils.h"
#include "nsWinAPIs.h"
#include <windows.h>
#include <WinError.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <direct.h>
static inline void ConvertArg(LPCWSTR str, nsCAutoString &cstr,
const char* (&ptr))
{
if (str) {
NS_CopyUnicodeToNative(nsDependentString(str), cstr);
ptr = cstr.get();
}
else
ptr = NULL;
}
template <class T>
static inline PRBool SetLengthAndCheck(T &aStr, DWORD aLen)
{
aStr.SetLength(aLen);
if (aStr.Length() != aLen) {
SetLastError(ERROR_OUTOFMEMORY);
return PR_FALSE;
}
return PR_TRUE;
}
//
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/getting_system_information.asp
BOOL WINAPI nsSHGetPathFromIDListW(LPCITEMIDLIST aIdList, LPWSTR aPathW)
{
if (aPathW) {
char pathA[MAX_PATH];
if (SHGetPathFromIDListA(aIdList, pathA)) {
NS_ConvertAtoW(pathA, MAX_PATH, aPathW);
return TRUE;
}
}
return FALSE;
}
// GetSystemDirectory, GetWindowsDirectory, GetTempPath, GetEnvironmentVariable
// return the required buffer size including the terminating null if the buffer
// passed is too small to hold the result while they return the number of
// characters stored in the buffer excluding the terminating null if it's
// large enough. Therefore, just checking whether the return value is zero
// is not sufficient. We also need to make sure that the return value is
// smaller than the buffer size passed to them.
UINT WINAPI nsGetSystemDirectoryW(LPWSTR aPathW, UINT aSize)
{
char pathA[MAX_PATH];
int len;
if (aPathW && GetSystemDirectoryA(pathA, MAX_PATH) < MAX_PATH &&
(len = NS_ConvertAtoW(pathA, aSize, aPathW)))
return len - 1; // terminating null is not included
else
return 0;
}
UINT WINAPI nsGetWindowsDirectoryW(LPWSTR aPathW, UINT aSize)
{
char pathA[MAX_PATH];
int len;
if (aPathW && GetWindowsDirectoryA(pathA, MAX_PATH) < MAX_PATH &&
(len = NS_ConvertAtoW(pathA, aSize, aPathW)))
return len - 1; // terminating null is not included
else
return 0;
}
DWORD WINAPI nsGetTempPathW(DWORD aLen, LPWSTR aPathW)
{
char pathA[MAX_PATH];
DWORD len;
if (aPathW && GetTempPathA(MAX_PATH, pathA) < MAX_PATH &&
(len = NS_ConvertAtoW(pathA, aLen, aPathW)))
return len - 1; // terminating null is not included
return 0;
}
DWORD WINAPI nsGetEnvironmentVariableW(LPCWSTR aName, LPWSTR aValue, DWORD aSize)
{
if (!aName || !aValue || aSize <= 0)
return 0;
nsCAutoString nameA;
NS_CopyUnicodeToNative(nsDependentString(aName), nameA);
const DWORD maxValueLen = 32767; // the maximum length of an env. variable
nsCAutoString value;
DWORD sizeA = NS_MIN(maxValueLen, aSize * 2);
if (!SetLengthAndCheck(value, sizeA))
return 0;
char *buf = value.BeginWriting();
DWORD len;
if (!(len = GetEnvironmentVariableA(nameA.get(), buf, sizeA)))
return 0;
if (len > sizeA) {
if (sizeA < maxValueLen) {
if (!SetLengthAndCheck(value, len))
return 0;
buf = value.BeginWriting();
len = GetEnvironmentVariableA(nameA.get(), buf, len);
}
else
// sizeA >= maxValueLen and still failed.
return 0;
}
// terminating null is not included in the length
return (len = NS_ConvertAtoW(buf, aSize, aValue)) ? len - 1 : 0;
}
BOOL WINAPI nsCreateDirectoryW(LPCWSTR aPath, LPSECURITY_ATTRIBUTES aSecAttr)
{
if (!aPath) {
SetLastError(ERROR_BAD_ARGUMENTS);
return FALSE;
}
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return CreateDirectoryA(pathA.get(), aSecAttr);
}
HANDLE WINAPI nsCreateFileW(LPCWSTR aPath, DWORD aAccess,
DWORD aMode, LPSECURITY_ATTRIBUTES aSecAttr,
DWORD aCreat, DWORD aFlags, HANDLE aTemplate)
{
if (!aPath) {
SetLastError(ERROR_BAD_ARGUMENTS);
return INVALID_HANDLE_VALUE;
}
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return CreateFileA(pathA.get(), aAccess, aMode, aSecAttr, aCreat,
aFlags, aTemplate);
}
HINSTANCE WINAPI nsShellExecuteW(HWND aWin, LPCWSTR aOp, LPCWSTR aFile,
LPCWSTR aParam, LPCWSTR aDir, INT aShowCmd)
{
nsCAutoString op, file, param, dir;
const char *pOp, *pFile, *pParam, *pDir;
ConvertArg(aOp, op, pOp);
ConvertArg(aFile, file, pFile);
ConvertArg(aParam, param, pParam);
ConvertArg(aDir, dir, pDir);
return ShellExecuteA(aWin, pOp, pFile, pParam, pDir, aShowCmd);
}
BOOL WINAPI nsCopyFileW(LPCWSTR aSrc, LPCWSTR aDest, BOOL aNoOverwrite)
{
nsCAutoString src, dest;
const char *pSrc, *pDest;
ConvertArg(aSrc, src, pSrc);
ConvertArg(aDest, dest, pDest);
return CopyFileA(pSrc, pDest, aNoOverwrite);
}
BOOL WINAPI nsMoveFileW(LPCWSTR aSrc, LPCWSTR aDest)
{
nsCAutoString src, dest;
const char *pSrc, *pDest;
ConvertArg(aSrc, src, pSrc);
ConvertArg(aDest, dest, pDest);
return MoveFileA(pSrc, pDest);
}
BOOL WINAPI nsGetFileVersionInfoW(LPCWSTR aPath, DWORD aHandle, DWORD aLen,
LPVOID aData)
{
nsCAutoString path;
const char *pPath;
ConvertArg(aPath, path, pPath);
return GetFileVersionInfoA(pPath, aHandle, aLen, aData);
}
DWORD WINAPI nsGetFileVersionInfoSizeW(LPCWSTR aPath, LPDWORD aHandle)
{
nsCAutoString path;
const char *pPath;
ConvertArg(aPath, path, pPath);
return GetFileVersionInfoSizeA(pPath, aHandle);
}
DWORD WINAPI nsGetFileAttributesW(LPCWSTR aPath)
{
nsCAutoString path;
const char *pPath;
ConvertArg(aPath, path, pPath);
return GetFileAttributesA(pPath);
}
BOOL WINAPI nsGetFileAttributesExW(LPCWSTR aPath, GET_FILEEX_INFO_LEVELS aLevel,
LPVOID aInfo)
{
NS_ASSERTION(aLevel == GetFileExInfoStandard, "invalid level specified");
NS_ASSERTION(nsWinAPIs::mCopyFile != CopyFileW,
"Win APIs pointers are reset to the stubs of 'W' APIs");
nsCAutoString path;
const char *pPath;
ConvertArg(aPath, path, pPath);
// present on Win 98/ME
if (nsWinAPIs::mGetFileAttributesExA)
#ifdef DEBUG_jungshik
{
BOOL rv = nsWinAPIs::mGetFileAttributesExA(pPath, aLevel, aInfo);
if (!rv) {
printf("nsGetFileAttributesExW with file=%s failed\n", pPath);
printf("Last error is %d\n", GetLastError());
}
return rv;
}
#else
return nsWinAPIs::mGetFileAttributesExA(pPath, aLevel, aInfo);
#endif
// fallback for Win95 without IE4 or later where GetFileAttributesEx
// is missing.
if (aLevel != GetFileExInfoStandard) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// FindFirstFile expands wildcard characters so that we need to make
// sure that the path contains no wildcard.
if (NULL != wcspbrk(aPath, L"?*"))
return FALSE;
WIN32_FIND_DATAA fdata;
HANDLE handle = FindFirstFileA(pPath, &fdata);
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
// XXX : FindFirstFile doesn't work with a root directory
// or a path ending with a slash/back slash.
// We can work around it as in NSPR (w95io.c), but don't bother
// because Windows 95 without IE4 or later is a rare beast so that
// it's not worth duplicating ~40 lines of the NSPR code here to
// support a path ending with a slash/back slash or a root path.
// Note that even MS's emulation of GetFileAttributesEx for Win95
// (included in Visual C++) doesn't, either.
WIN32_FILE_ATTRIBUTE_DATA *fadata=
(WIN32_FILE_ATTRIBUTE_DATA *) aInfo;
fadata->dwFileAttributes = fdata.dwFileAttributes;
fadata->ftCreationTime = fdata.ftCreationTime;
fadata->ftLastAccessTime = fdata.ftLastAccessTime;
fadata->ftLastWriteTime = fdata.ftLastWriteTime;
fadata->nFileSizeHigh = fdata.nFileSizeHigh;
fadata->nFileSizeLow = fdata.nFileSizeLow;
FindClose(handle);
return TRUE;
}
DWORD WINAPI nsGetShortPathNameW(LPCWSTR aLPath, LPWSTR aSPath, DWORD aLen)
{
if (!aLPath || !aSPath) {
SetLastError(ERROR_BAD_ARGUMENTS);
return 0;
}
nsCAutoString lPath;
NS_CopyUnicodeToNative(nsDependentString(aLPath), lPath);
// MAX_PATH is the max path length including the terminating null.
if (lPath.Length() >= MAX_PATH) {
SetLastError(ERROR_BAD_ARGUMENTS);
return 0;
}
nsCAutoString sPath;
if (!SetLengthAndCheck(sPath, aLen))
return 0;
char *pSpath = sPath.BeginWriting();
DWORD lenA = GetShortPathNameA(lPath.get(), pSpath, aLen);
if (lenA > aLen) {
if (!SetLengthAndCheck(sPath, lenA))
return 0;
pSpath = sPath.BeginWriting();
lenA = GetShortPathNameA(lPath.get(), pSpath, lenA);
}
if (!lenA)
return 0;
// see if |aSPath| is large enough to hold the result
DWORD lenW = NS_ConvertAtoW(pSpath, 0, aSPath);
if (lenW > aLen)
// aSPath is too small. just return the required size.
return lenW;
// terminating null is not included in the return value
return (lenW = NS_ConvertAtoW(pSpath, aLen, aSPath)) ? lenW - 1 : 0;
}
BOOL WINAPI nsGetDiskFreeSpaceW(LPCWSTR aDir, LPDWORD aSpC, LPDWORD aBpS,
LPDWORD aNFC, LPDWORD aTNC)
{
nsCAutoString dir;
const char *pDir;
ConvertArg(aDir, dir, pDir);
return GetDiskFreeSpaceA(pDir, aSpC, aBpS, aNFC, aTNC);
}
typedef BOOL (WINAPI *fpGetDiskFreeSpaceExA)(LPCSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes);
BOOL WINAPI nsGetDiskFreeSpaceExW(LPCWSTR aDir, PULARGE_INTEGER aFBA,
PULARGE_INTEGER aTNB, PULARGE_INTEGER aTNFB)
{
// Attempt to check disk space using the GetDiskFreeSpaceExA function.
// --- FROM MSDN ---
// The GetDiskFreeSpaceEx function is available beginning with Windows 95 OEM Service
// Release 2 (OSR2). To determine whether GetDiskFreeSpaceEx is available, call
// GetModuleHandle to get the handle to Kernel32.dll. Then you can call GetProcAddress.
// It is not necessary to call LoadLibrary on Kernel32.dll because it is already loaded
// into every process address space.
fpGetDiskFreeSpaceExA pGetDiskFreeSpaceExA = (fpGetDiskFreeSpaceExA)
GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
if (!pGetDiskFreeSpaceExA)
return 0;
nsCAutoString dir;
const char *pDir;
ConvertArg(aDir, dir, pDir);
return pGetDiskFreeSpaceExA(pDir, aFBA, aTNB, aTNFB);
}
DWORD WINAPI nsGetModuleFileNameW(HMODULE aModule, LPWSTR aName, DWORD aSize)
{
if (!aName || aSize <= 0) {
SetLastError(ERROR_BAD_ARGUMENTS);
return 0;
}
DWORD len;
char buf[MAX_PATH + 1];
if (!(len = GetModuleFileNameA(aModule, buf, MAX_PATH)))
return 0;
// just in case, null-terminate
buf[MAX_PATH] = '\0';
len = NS_ConvertAtoW(buf, 0, aName);
if (len <= aSize)
return (len = NS_ConvertAtoW(buf, aSize, aName)) ? len - 1 : 0;
// buffer is not large enough. just truncate the result to the first
// |aSize| characters.
nsAutoString temp;
if (!SetLengthAndCheck(temp, len))
return 0;
PRUnichar *pTmp = temp.BeginWriting();
NS_ConvertAtoW(buf, len, pTmp);
memcpy(aName, pTmp, aSize * 2);
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return aSize;
}
wchar_t* nsGetCwdW(wchar_t *aBuf, int aMaxLen)
{
if (aMaxLen <= 0)
return NULL;
// One 16-bit unit in UTF-16 can take as many as 2 bytes in legacy Windows
// codepage used on Windows 9x/ME (note that we don't have to worry about
// UTF-8 and GB18030 because they're not used on Windows 9x/ME)
char *cwdA = _getcwd(NULL, aMaxLen * 2);
if (!cwdA)
return NULL;
// see if we're given a buffer large enough to hold the result
int len = NS_ConvertAtoW(cwdA, 0, aBuf);
if ((len > aMaxLen && aBuf) || len == 0) {
free(cwdA);
return NULL;
}
if (!aBuf)
// errno = ENOMEM;
aBuf = (wchar_t *) malloc(len * sizeof(wchar_t));
if (!aBuf) {
free(cwdA);
return NULL;
}
len = NS_ConvertAtoW(cwdA, NS_MAX(len, aMaxLen), aBuf);
free(cwdA);
return len ? aBuf : NULL;
}
wchar_t* nsGetDCwdW(int aDrive, wchar_t *aBuf, int aMaxLen)
{
if (aMaxLen <= 0)
return NULL;
// One 16-bit unit in UTF-16 can take as many as 2 bytes in legacy Windows codepage
// used on Windows 9x/ME (note that we don't have to worry about
// UTF-8 and GB18030 because they're not used on Windows 9x/ME)
char *cwdA = _getdcwd(aDrive, NULL, aMaxLen * 2);
if (!cwdA)
return NULL;
// see if we're given a buffer large enough to hold the result
int len = NS_ConvertAtoW(cwdA, 0, aBuf);
if ((len > aMaxLen && aBuf) || len == 0) {
//errno = ERANGE;
free(cwdA);
return NULL;
}
if (!aBuf)
aBuf = (wchar_t *) malloc(len * sizeof(wchar_t));
if (!aBuf) {
free(cwdA);
return NULL;
}
len = NS_ConvertAtoW(cwdA, NS_MAX(len, aMaxLen), aBuf);
free(cwdA);
return len ? aBuf : NULL;
}
FILE* nsFopenW(const wchar_t *aPath, const wchar_t *aMode)
{
if (!aPath) return NULL;
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return fopen(pathA.get(),
NS_LossyConvertUTF16toASCII(aMode).get());
}
int nsRemoveW(const wchar_t *aPath)
{
if (!aPath) return -1;
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return remove(pathA.get());
}
int nsRmdirW(const wchar_t *aPath)
{
if (!aPath) return -1;
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return _rmdir(pathA.get());
}
int nsChmodW(const wchar_t *aPath, int aMode)
{
if (!aPath) return -1;
nsCAutoString pathA;
NS_CopyUnicodeToNative(nsDependentString(aPath), pathA);
return _chmod(pathA.get(), aMode);
}
PRBool nsWinAPIs::sUseUnicode = -1; // not yet initialized
// All but three APIs are initialized to 'W' versions.
// Exceptions are SHGetPathFromIDList, GetFileAttributesEx, GetFreeDiskSpaceEx
// for which even stubs are not available on Win95 so that we set
// them to our own implementation initially. Yet another exception needs to be
// made for GetFileAttributesEx because even its 'A' version doesn't exist on
// Win95. The corresponding function pointer is set to NULL initially
// and its existence is checked using GetProcAddress on Win 9x/ME.
nsSHGetPathFromIDList nsWinAPIs::mSHGetPathFromIDList = nsSHGetPathFromIDListW;
nsGetSystemDirectory nsWinAPIs::mGetSystemDirectory = GetSystemDirectoryW;
nsGetWindowsDirectory nsWinAPIs::mGetWindowsDirectory = GetWindowsDirectoryW;
nsGetTempPath nsWinAPIs::mGetTempPath = GetTempPathW;
nsGetEnvironmentVariable nsWinAPIs::mGetEnvironmentVariable = GetEnvironmentVariableW;
nsCreateDirectory nsWinAPIs::mCreateDirectory = CreateDirectoryW;
nsCreateFile nsWinAPIs::mCreateFile = CreateFileW;
nsShellExecute nsWinAPIs::mShellExecute = ShellExecuteW;
nsCopyFile nsWinAPIs::mCopyFile = CopyFileW;
nsMoveFile nsWinAPIs::mMoveFile = MoveFileW;
nsGetFileVersionInfo nsWinAPIs::mGetFileVersionInfo = GetFileVersionInfoW;
nsGetFileVersionInfoSize nsWinAPIs::mGetFileVersionInfoSize = GetFileVersionInfoSizeW;
nsGetFileAttributes nsWinAPIs::mGetFileAttributes = GetFileAttributesW;
nsGetFileAttributesEx nsWinAPIs::mGetFileAttributesEx = nsGetFileAttributesExW;
nsGetFileAttributesExA nsWinAPIs::mGetFileAttributesExA = NULL;
nsGetShortPathName nsWinAPIs::mGetShortPathName = GetShortPathNameW;
nsGetDiskFreeSpace nsWinAPIs::mGetDiskFreeSpace = GetDiskFreeSpaceW;
nsGetDiskFreeSpaceEx nsWinAPIs::mGetDiskFreeSpaceEx = nsGetDiskFreeSpaceExW;
nsGetModuleFileName nsWinAPIs::mGetModuleFileName = GetModuleFileNameW;
nsGetCwd nsWinAPIs::mGetCwd = _wgetcwd;
nsGetDCwd nsWinAPIs::mGetDCwd = _wgetdcwd;
nsFopen nsWinAPIs::mFopen = _wfopen;
nsRemove nsWinAPIs::mRemove = _wremove;
nsRmdir nsWinAPIs::mRmdir = _wrmdir;
nsChmod nsWinAPIs::mChmod = _wchmod;
// This is a dummy variable to make sure that WinAPI is initialized
// at the very start. Note that |sDummy| must be defined AFTER
// all the function pointers for Win APIs are defined. Otherwise,
// what's done in |GlobalInit| would have no effect.
PRBool nsWinAPIs::sDummy = nsWinAPIs::GlobalInit();
PRBool
nsWinAPIs::GlobalInit()
{
// Find out if we are running on a unicode enabled version of Windows
OSVERSIONINFOA osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(osvi);
if (!GetVersionExA(&osvi)) {
sUseUnicode = PR_FALSE;
} else {
sUseUnicode = (osvi.dwPlatformId >= VER_PLATFORM_WIN32_NT);
}
#ifdef DEBUG
// In debug builds, allow explicit use of ANSI methods for testing purposes.
if (getenv("WINAPI_USE_ANSI"))
sUseUnicode = PR_FALSE;
#endif
HINSTANCE kernel32 = ::GetModuleHandle("kernel32.dll");
// on Win 9x/ME, use our own implementations of 'W' APIs
// which eventually calls 'A' APIs
if (!sUseUnicode) {
NS_WARNING("Windows 'A' APIs will be used !!");
mGetSystemDirectory = nsGetSystemDirectoryW;
mGetWindowsDirectory = nsGetWindowsDirectoryW;
mGetTempPath = nsGetTempPathW;
mGetEnvironmentVariable = nsGetEnvironmentVariableW;
mCreateFile = nsCreateFileW;
mCreateDirectory = nsCreateDirectoryW;
mShellExecute = nsShellExecuteW;
mCopyFile = nsCopyFileW;
mMoveFile = nsMoveFileW;
mGetFileVersionInfo = nsGetFileVersionInfoW;
mGetFileVersionInfoSize = nsGetFileVersionInfoSizeW;
mGetFileAttributes = nsGetFileAttributesW;
mGetShortPathName = nsGetShortPathNameW;
mGetDiskFreeSpace = nsGetDiskFreeSpaceW;
mGetModuleFileName = nsGetModuleFileNameW;
mGetCwd = nsGetCwdW;
mGetDCwd = nsGetDCwdW;
mFopen = nsFopenW;
mRemove = nsRemoveW;
mRmdir = nsRmdirW;
mChmod = nsChmodW;
// absent on Win 95.
mGetFileAttributesExA = (nsGetFileAttributesExA)
GetProcAddress(kernel32, "GetFileAttributesExA");
}
else {
HINSTANCE shell32 = LoadLibrary("Shell32.dll");
if (shell32)
mSHGetPathFromIDList = (nsSHGetPathFromIDList)
GetProcAddress(shell32, "SHGetPathFromIDListW");
mGetFileAttributesEx = (nsGetFileAttributesEx)
GetProcAddress(kernel32, "GetFileAttributesExW");
mGetDiskFreeSpaceEx = (nsGetDiskFreeSpaceEx)
GetProcAddress(kernel32, "GetDiskFreeSpaceExW");
NS_ASSERTION(mSHGetPathFromIDList && mGetFileAttributesEx &&
mGetDiskFreeSpaceEx, "failed to get proc. addresses");
}
return PR_TRUE;
}
NS_COM PRBool
NS_UseUnicode()
{
return nsWinAPIs::sUseUnicode;
}

133
xpcom/io/nsWinAPIs.h Normal file
View File

@ -0,0 +1,133 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Jungshik Shin
* <jshin@i18nl10n.com>. Portions created by the Initial Developer
* are Copyright (C) 2006 the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* 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 ***** */
#ifndef nsWinAPIs_h__
#define nsWinAPIs_h__
#include "prtypes.h"
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
typedef BOOL (WINAPI * nsSHGetPathFromIDList) (LPCITEMIDLIST pidList, LPWSTR pszPath);
typedef UINT (WINAPI * nsGetSystemDirectory) (LPWSTR lpBuffer, UINT usize);
typedef UINT (WINAPI * nsGetWindowsDirectory) (LPWSTR lpBuffer, UINT usize);
typedef DWORD (WINAPI * nsGetTempPath) (DWORD len, LPWSTR lpBuffer);
typedef DWORD (WINAPI * nsGetEnvironmentVariable) (LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize);
typedef BOOL (WINAPI * nsCreateDirectory) (LPCWSTR aDir,
LPSECURITY_ATTRIBUTES aSecAttr);
typedef HANDLE (WINAPI * nsCreateFile) (LPCWSTR aPath, DWORD aAccess,
DWORD aMode,
LPSECURITY_ATTRIBUTES aSecAttr,
DWORD aCreat, DWORD aFlags,
HANDLE aTemplate);
typedef HINSTANCE (WINAPI * nsShellExecute) (HWND hwnd, LPCWSTR lpOperation,
LPCWSTR lpFile,
LPCWSTR lpParameters,
LPCWSTR lpDirectory,
INT nShowCmd);
typedef BOOL (WINAPI * nsCopyFile) (LPCWSTR aSrc, LPCWSTR aDest, BOOL aNoOverwrite);
typedef BOOL (WINAPI * nsMoveFile) (LPCWSTR aSrc, LPCWSTR aDest);
typedef BOOL (WINAPI * nsGetFileVersionInfo) (LPCWSTR aPath, DWORD aHandle, DWORD aLen,
LPVOID aData);
typedef DWORD (WINAPI * nsGetFileVersionInfoSize) (LPCWSTR aPath, LPDWORD aHandle);
typedef DWORD (WINAPI * nsGetFileAttributes) (LPCWSTR aPath);
typedef BOOL (WINAPI * nsGetFileAttributesEx) (LPCWSTR aPath, GET_FILEEX_INFO_LEVELS aLevel,
LPVOID aInfo);
typedef BOOL (WINAPI * nsGetFileAttributesExA) (LPCSTR aPath, GET_FILEEX_INFO_LEVELS aLevel,
LPVOID aInfo);
typedef DWORD (WINAPI * nsGetShortPathName) (LPCWSTR aLPATH, LPWSTR aSPATH, DWORD aLen);
typedef BOOL (WINAPI * nsGetDiskFreeSpace) (LPCWSTR aDir, LPDWORD aSpC,
LPDWORD aBpS, LPDWORD aNFC, LPDWORD aTNC);
typedef BOOL (WINAPI * nsGetDiskFreeSpaceEx) (LPCWSTR aDir,
PULARGE_INTEGER aFBA,
PULARGE_INTEGER aTNB,
PULARGE_INTEGER aTNFB);
typedef DWORD (WINAPI * nsGetModuleFileName) (HMODULE aModule, LPWSTR aName, DWORD aSize);
typedef wchar_t* (*nsGetCwd) (wchar_t *buffer, int maxlen);
typedef wchar_t* (*nsGetDCwd) (int aDrive, wchar_t *aPath, int aMaxLen);
typedef FILE* (*nsFopen) (const wchar_t *aName, const wchar_t *aMode);
typedef int (*nsRemove) (const wchar_t *aPath);
typedef int (*nsRmdir) (const wchar_t *aPath);
typedef int (*nsChmod) (const wchar_t *aName, int pmode);
class nsWinAPIs {
public:
static nsSHGetPathFromIDList mSHGetPathFromIDList;
static nsGetSystemDirectory mGetSystemDirectory;
static nsGetWindowsDirectory mGetWindowsDirectory;
static nsGetTempPath mGetTempPath;
static nsGetEnvironmentVariable mGetEnvironmentVariable;
static nsCreateDirectory mCreateDirectory;
static nsCreateFile mCreateFile;
static nsShellExecute mShellExecute;
static nsCopyFile mCopyFile;
static nsMoveFile mMoveFile;
static nsGetFileVersionInfo mGetFileVersionInfo;
static nsGetFileVersionInfoSize mGetFileVersionInfoSize;
static nsGetFileAttributes mGetFileAttributes;
static nsGetFileAttributesEx mGetFileAttributesEx;
static nsGetFileAttributesExA mGetFileAttributesExA;
static nsGetShortPathName mGetShortPathName;
static nsGetDiskFreeSpace mGetDiskFreeSpace;
static nsGetDiskFreeSpaceEx mGetDiskFreeSpaceEx;
static nsGetModuleFileName mGetModuleFileName;
static nsGetCwd mGetCwd;
static nsFopen mFopen;
static nsGetDCwd mGetDCwd;
static nsRemove mRemove;
static nsRmdir mRmdir;
static nsChmod mChmod;
private:
nsWinAPIs() {}
static PRBool GlobalInit();
static PRBool sUseUnicode;
friend NS_COM PRBool NS_UseUnicode();
friend NS_COM void NS_StartupWinAPIs();
// a dummy variable to make sure that |GlobalInit| is invoked
// before the first use |nsLocalFileWin| that relies on Windows APIs
// set up in |GlobalInit|
static PRBool sDummy;
};
NS_COM PRBool NS_UseUnicode();
#endif