Index: os_win.c =================================================================== RCS file: /cvsroot/mozilla/db/sqlite3/src/os_win.c,v retrieving revision 1.2.8.4 diff -u -8 -p -r1.2.8.4 os_win.c --- os_win.c 22 May 2006 19:12:32 -0000 1.2.8.4 +++ os_win.c 18 Jul 2006 22:33:46 -0000 @@ -126,19 +126,16 @@ int sqlite3_os_type = 0; /* ** Convert a UTF-8 string to UTF-32. Space to hold the returned string ** is obtained from sqliteMalloc. */ static WCHAR *utf8ToUnicode(const char *zFilename){ int nChar; WCHAR *zWideFilename; - if( !isNT() ){ - return 0; - } nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) ); if( zWideFilename==0 ){ return 0; } nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); if( nChar==0 ){ sqliteFree(zWideFilename); @@ -164,16 +161,93 @@ static char *unicodeToUtf8(const WCHAR * 0, 0); if( nByte == 0 ){ sqliteFree(zFilename); zFilename = 0; } return zFilename; } +/* +** Convert a multibyte character string to UTF-32, based on the current Ansi codepage (CP_ACP). +** Space to hold the returned string is obtained from sqliteMalloc. +*/ +static WCHAR *mbcsToUnicode(const char *zFilename){ + int nByte; + WCHAR *zMbcsFilename; + + nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); + zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) ); + if( zMbcsFilename==0 ){ + return 0; + } + nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, zMbcsFilename, nByte); + if( nByte==0 ){ + sqliteFree(zMbcsFilename); + zMbcsFilename = 0; + } + return zMbcsFilename; +} + +/* +** Convert UTF-32 to multibyte character string, based on the user's Ansi codepage (CP_ACP). +** Space to hold the returned string is obtained from sqliteMalloc(). +*/ +static char *unicodeToMbcs(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + + nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = sqliteMalloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + sqliteFree(zFilename); + zFilename = 0; + } + return zFilename; +} + +/* +** Convert multibyte character string to UTF-8. Space to hold the returned string is +** obtained from sqliteMalloc(). +*/ +static char *mbcsToUtf8(const char *zFilename){ + char *zFilenameUtf8; + WCHAR *zTmpWide; + + zTmpWide = mbcsToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameUtf8 = unicodeToUtf8(zTmpWide); + sqliteFree(zTmpWide); + return zFilenameUtf8; +} + +/* +** Convert UTF-8 to multibyte character string. Space to hold the returned string is +** obtained from sqliteMalloc(). +*/ +static char *utf8ToMbcs(const char *zFilename){ + char *zFilenameMbcs; + WCHAR *zTmpWide; + + zTmpWide = utf8ToUnicode(zFilename); + if( zTmpWide==0 ){ + return 0; + } + zFilenameMbcs = unicodeToMbcs(zTmpWide); + sqliteFree(zTmpWide); + return zFilenameMbcs; +} + #if OS_WINCE /************************************************************************* ** This section contains code for WinCE only. */ /* ** WindowsCE does not have a localtime() function. So create a ** substitute. */ @@ -470,51 +544,58 @@ static BOOL winceLockFileEx( } return FALSE; } /* ** End of the special code for wince *****************************************************************************/ #endif /* OS_WINCE */ +static void *convertUtf8Filename(const char *zFilename){ + void *zConverted = 0; + if( isNT() ){ + zConverted = utf8ToUnicode(zFilename); + }else{ + zConverted = utf8ToMbcs(zFilename); + } + /* caller will handle out of memory */ + return zConverted; +} + /* ** Delete the named file */ int sqlite3WinDelete(const char *zFilename){ - WCHAR *zWide = utf8ToUnicode(zFilename); - if( zWide ){ - DeleteFileW(zWide); - sqliteFree(zWide); - }else{ -#if OS_WINCE + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ) return SQLITE_NOMEM; -#else - DeleteFileA(zFilename); -#endif + if( isNT() ){ + DeleteFileW((WCHAR*)zConverted); + }else{ + DeleteFileA((char*)zConverted); } + sqliteFree(zConverted); TRACE2("DELETE \"%s\"\n", zFilename); return SQLITE_OK; } /* ** Return TRUE if the named file exists. */ int sqlite3WinFileExists(const char *zFilename){ int exists = 0; - WCHAR *zWide = utf8ToUnicode(zFilename); - if( zWide ){ - exists = GetFileAttributesW(zWide) != 0xffffffff; - sqliteFree(zWide); - }else{ -#if OS_WINCE + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ) return SQLITE_NOMEM; -#else - exists = GetFileAttributesA(zFilename) != 0xffffffff; -#endif + if( isNT() ){ + exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff; + }else{ + exists = GetFileAttributesA((char*)zConverted) != 0xffffffff; } + sqliteFree(zConverted); return exists; } /* Forward declaration */ static int allocateWinFile(winFile *pInit, OsFile **pId); /* ** Attempt to open a file for both reading and writing. If that @@ -531,82 +612,84 @@ static int allocateWinFile(winFile *pIni */ int sqlite3WinOpenReadWrite( const char *zFilename, OsFile **pId, int *pReadonly ){ winFile f; HANDLE h; - WCHAR *zWide = utf8ToUnicode(zFilename); + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ) + return SQLITE_NOMEM; assert( *pId==0 ); - if( zWide ){ - h = CreateFileW(zWide, + + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ - h = CreateFileW(zWide, + h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ - sqliteFree(zWide); + sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } #if OS_WINCE if (!winceCreateLock(zFilename, &f)){ CloseHandle(h); - sqliteFree(zWide); + sqliteFree(zConverted); return SQLITE_CANTOPEN; } #endif - sqliteFree(zWide); }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - h = CreateFileA(zFilename, + h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ - h = CreateFileA(zFilename, + h = CreateFileA((char*)zConverted, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); if( h==INVALID_HANDLE_VALUE ){ + sqliteFree(zConverted); return SQLITE_CANTOPEN; } *pReadonly = 1; }else{ *pReadonly = 0; } -#endif /* OS_WINCE */ } + + sqliteFree(zConverted); + f.h = h; #if OS_WINCE f.zDeleteOnClose = 0; #endif TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); return allocateWinFile(&f, pId); } @@ -624,48 +707,46 @@ int sqlite3WinOpenReadWrite( ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){ winFile f; HANDLE h; int fileflags; - WCHAR *zWide = utf8ToUnicode(zFilename); + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ) + return SQLITE_NOMEM; assert( *pId == 0 ); fileflags = FILE_FLAG_RANDOM_ACCESS; #if !OS_WINCE if( delFlag ){ fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE; } #endif - if( zWide ){ - h = CreateFileW(zWide, + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); - sqliteFree(zWide); }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - h = CreateFileA(zFilename, + h = CreateFileA((char*)zConverted, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, fileflags, NULL ); -#endif /* OS_WINCE */ } + sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h; #if OS_WINCE f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0; f.hMutex = NULL; #endif @@ -678,42 +759,40 @@ int sqlite3WinOpenExclusive(const char * ** ** On success, write the file handle into *id and return SQLITE_OK. ** ** On failure, return SQLITE_CANTOPEN. */ int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){ winFile f; HANDLE h; - WCHAR *zWide = utf8ToUnicode(zFilename); + void *zConverted = convertUtf8Filename(zFilename); + if( zConverted==0 ) + return SQLITE_NOMEM; assert( *pId==0 ); - if( zWide ){ - h = CreateFileW(zWide, + if( isNT() ){ + h = CreateFileW((WCHAR*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); - sqliteFree(zWide); }else{ -#if OS_WINCE - return SQLITE_NOMEM; -#else - h = CreateFileA(zFilename, + h = CreateFileA((char*)zConverted, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL ); -#endif } + sqliteFree(zConverted); if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } f.h = h; #if OS_WINCE f.zDeleteOnClose = 0; f.hMutex = NULL; #endif @@ -769,19 +848,31 @@ int sqlite3WinTempFileName(char *zBuf){ char *zMulti; WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); zMulti = unicodeToUtf8(zWidePath); if( zMulti ){ strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; sqliteFree(zMulti); + }else{ + return SQLITE_NOMEM; } }else{ - GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); + char *zUtf8; + char zMbcsPath[SQLITE_TEMPNAME_SIZE]; + GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath); + zUtf8 = mbcsToUtf8(zMbcsPath); + if( zUtf8 ){ + strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30); + zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + sqliteFree(zUtf8); + }else{ + return SQLITE_NOMEM; + } } for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} zTempPath[i] = 0; for(;;){ sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); j = strlen(zBuf); sqlite3Randomness(15, &zBuf[j]); for(i=0; i<15; i++, j++){ @@ -977,30 +1068,29 @@ static int unlockReadLock(winFile *pFile #ifndef SQLITE_OMIT_PAGER_PRAGMAS /* ** Check that a given pathname is a directory and is writable ** */ int sqlite3WinIsDirWritable(char *zDirname){ int fileAttr; - WCHAR *zWide; + void *zConverted; if( zDirname==0 ) return 0; if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0; - zWide = utf8ToUnicode(zDirname); - if( zWide ){ - fileAttr = GetFileAttributesW(zWide); - sqliteFree(zWide); + + zConverted = convertUtf8Filename(zDirname); + if( zConverted==0 ) + return SQLITE_NOMEM; + if( isNT() ){ + fileAttr = GetFileAttributesW((WCHAR*)zConverted); }else{ -#if OS_WINCE - return 0; -#else - fileAttr = GetFileAttributesA(zDirname); -#endif + fileAttr = GetFileAttributesA((char*)zConverted); } + sqliteFree(zConverted); if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ return 0; } return 1; } #endif /* SQLITE_OMIT_PAGER_PRAGMAS */ @@ -1213,34 +1303,43 @@ char *sqlite3WinFullPathname(const char nByte = strlen(zRelative) + MAX_PATH + 1001; zFull = sqliteMalloc( nByte ); if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #elif OS_WINCE /* WinCE has no concept of a relative pathname, or so I am told. */ zFull = sqliteStrDup(zRelative); #else - char *zNotUsed; - WCHAR *zWide; int nByte; - zWide = utf8ToUnicode(zRelative); - if( zWide ){ + void *zConverted; + zConverted = convertUtf8Filename(zRelative); + if( isNT() ){ WCHAR *zTemp, *zNotUsedW; - nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1; + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, &zNotUsedW) + 1; zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); - if( zTemp==0 ) return 0; - GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW); - sqliteFree(zWide); + if( zTemp==0 ){ + sqliteFree(zConverted); + return 0; + } + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, &zNotUsedW); + sqliteFree(zConverted); zFull = unicodeToUtf8(zTemp); sqliteFree(zTemp); }else{ - nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1; - zFull = sqliteMalloc( nByte*sizeof(zFull[0]) ); - if( zFull==0 ) return 0; - GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed); + char *zTemp, *zNotUsed; + nByte = GetFullPathNameA((char*)zConverted, 0, 0, &zNotUsed) + 1; + zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ){ + sqliteFree(zConverted); + return 0; + } + GetFullPathNameA((char*)zConverted, nByte, zTemp, &zNotUsed); + sqliteFree(zConverted); + zFull = mbcsToUtf8(zTemp); + sqliteFree(zTemp); } #endif return zFull; } /* ** The fullSync option is meaningless on windows. This is a no-op. */