From: drh Date: Mon, 5 Sep 2005 19:08:29 +0000 (+0000) Subject: Use the unicode API to win32 where available. X-Git-Tag: version-3.6.10~3503 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c0929987158d14d2ec4e343fe9b7ddbd344607de;p=thirdparty%2Fsqlite.git Use the unicode API to win32 where available. Tickets #1407, #1396, #1331, #1243, #1206 (CVS 2656) FossilOrigin-Name: 3ec58c673ae4cf0695ea0c287cc9bcbdcdb1a200 --- diff --git a/manifest b/manifest index 5c1e0ad094..21bb975660 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sover-aggressive\soptimization\sof\sORDER\sBY\sas\sreported\son\sthe\smailing\slist.\s(CVS\s2655) -D 2005-09-01T17:47:51 +C Use\sthe\sunicode\sAPI\sto\swin32\swhere\savailable.\r\nTickets\s#1407,\s#1396,\s#1331,\s#1243,\s#1206\s(CVS\s2656) +D 2005-09-05T19:08:29 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -54,7 +54,7 @@ F src/os_test.c 91e5f22dd89491e5e1554820e715805f43fa4ece F src/os_test.h 903c93554c23d88f34f667f1979e4a1cee792af3 F src/os_unix.c b4c4592589113db088662ef7570967ec36022b5d F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e -F src/os_win.c fe7b99cfcfb61d9bf54493ddf5857885a657fb89 +F src/os_win.c 8b80f418aefd2ceabe3580f680f5dcc244cf2344 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c cd9896287a8fd33cc267bd0c2b69c421a4808169 F src/pager.h 17b13225abd93c1e9f470060f40a21b9edb5a164 @@ -69,7 +69,7 @@ F src/sqlite.h.in d6561d51025d08de4f455607f3f9f9aa76e855d5 F src/sqliteInt.h 845ff6f8019f80baafb1bdbb8ef80fcd04d9d0f9 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c ac94682f9e601dd373912c46414a5a842db2089a -F src/test1.c ca4b959ce0a966ede87727cd8d3f5905743dfd4e +F src/test1.c 006fafaa3456d20db37951b94c9d9becac64568e F src/test2.c 792f203be69fea88668fa221321194f0a28dfdfa F src/test3.c f4e6a16a602091696619a1171bda25c0e3df49f7 F src/test4.c a8fd681e139e1c61f22a77d07fc3a99cb28fff3f @@ -306,7 +306,7 @@ F www/tclsqlite.tcl 3df553505b6efcad08f91e9b975deb2e6c9bb955 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 81259a01f1e85ba50a1d017b1282bf841b16f0a5 -R 9230534585e06aeccca811dde76702e9 +P efbb4bc83cd86b6a26d58c5818c58c2e3edaab18 +R d11951b0db345c53b16225d15ddfa80a U drh -Z 91850feb3a4a5d6eb41e5886f9a1b320 +Z ce91eee65efcee02daeb83c44469f09e diff --git a/manifest.uuid b/manifest.uuid index 21e59d0f35..6799ed3610 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -efbb4bc83cd86b6a26d58c5818c58c2e3edaab18 \ No newline at end of file +3ec58c673ae4cf0695ea0c287cc9bcbdcdb1a200 \ No newline at end of file diff --git a/src/os_win.c b/src/os_win.c index ea2ca26089..4e98a25f2a 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -41,11 +41,99 @@ */ #ifndef SQLITE_OMIT_DISKIO +/* +** The following variable is (normally) set once and never changes +** thereafter. It records whether the operating system is Win95 +** or WinNT. +** +** 0: Operating system unknown. +** 1: Operating system is Win95. +** 2: Operating system is WinNT. +** +** In order to facilitate testing on a WinNT system, the test fixture +** can manually set this value to 1 to emulate Win98 behavior. +*/ +int sqlite3_os_type = 0; + +/* +** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. +** Return false (zero) for Win95, Win98, or WinME. +** +** Here is an interesting observation: Win95, Win98, and WinME lack +** the LockFileEx() API. But we can still statically link against that +** API as long as we don't call it win running Win95/98/ME. A call to +** this routine is used to determine if the host is Win95/98/ME or +** WinNT/2K/XP so that we will know whether or not we can safely call +** the LockFileEx() API. +*/ +static int isNT(void){ + if( sqlite3_os_type==0 ){ + OSVERSIONINFO sInfo; + sInfo.dwOSVersionInfoSize = sizeof(sInfo); + GetVersionEx(&sInfo); + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; + } + return sqlite3_os_type==2; +} + +/* +** 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 nByte; + WCHAR *zWideFilename; + + if( !isNT() ){ + return 0; + } + nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR); + zWideFilename = sqliteMalloc( nByte ); + if( zWideFilename==0 ){ + return 0; + } + nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte); + if( nByte==0 ){ + sqliteFree(zWideFilename); + zWideFilename = 0; + } + return zWideFilename; +} + +/* +** Convert UTF-32 to UTF-8. Space to hold the returned string is +** obtained from sqliteMalloc(). +*/ +static char *unicodeToUtf8(const WCHAR *zWideFilename){ + int nByte; + char *zFilename; + + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); + zFilename = sqliteMalloc( nByte ); + if( zFilename==0 ){ + return 0; + } + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, + 0, 0); + if( nByte == 0 ){ + sqliteFree(zFilename); + zFilename = 0; + } + return zFilename; +} + + /* ** Delete the named file */ int sqlite3OsDelete(const char *zFilename){ - DeleteFileA(zFilename); + WCHAR *zWide = utf8ToUnicode(zFilename); + if( zWide ){ + DeleteFileW(zWide); + sqliteFree(zWide); + }else{ + DeleteFileA(zFilename); + } TRACE2("DELETE \"%s\"\n", zFilename); return SQLITE_OK; } @@ -54,7 +142,15 @@ int sqlite3OsDelete(const char *zFilename){ ** Return TRUE if the named file exists. */ int sqlite3OsFileExists(const char *zFilename){ - return GetFileAttributesA(zFilename) != 0xffffffff; + int exists = 0; + WCHAR *zWide = utf8ToUnicode(zFilename); + if( zWide ){ + exists = GetFileAttributesW(zWide) != 0xffffffff; + sqliteFree(zWide); + }else{ + exists = GetFileAttributesA(zFilename) != 0xffffffff; + } + return exists; } /* @@ -76,30 +172,60 @@ int sqlite3OsOpenReadWrite( int *pReadonly ){ HANDLE h; + WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); - h = CreateFileA(zFilename, - 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, - GENERIC_READ, - FILE_SHARE_READ, + if( zWide ){ + h = CreateFileW(zWide, + 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 ){ - return SQLITE_CANTOPEN; + h = CreateFileW(zWide, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + sqliteFree(zWide); + return SQLITE_CANTOPEN; + } + *pReadonly = 1; + }else{ + *pReadonly = 0; } - *pReadonly = 1; + sqliteFree(zWide); }else{ - *pReadonly = 0; + h = CreateFileA(zFilename, + 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, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + if( h==INVALID_HANDLE_VALUE ){ + return SQLITE_CANTOPEN; + } + *pReadonly = 1; + }else{ + *pReadonly = 0; + } } id->h = h; id->locktype = NO_LOCK; @@ -128,6 +254,7 @@ int sqlite3OsOpenReadWrite( int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ HANDLE h; int fileflags; + WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); if( delFlag ){ fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS @@ -135,14 +262,26 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ }else{ fileflags = FILE_FLAG_RANDOM_ACCESS; } - h = CreateFileA(zFilename, - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - CREATE_ALWAYS, - fileflags, - NULL - ); + if( zWide ){ + h = CreateFileW(zWide, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + sqliteFree(zWide); + }else{ + h = CreateFileA(zFilename, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + fileflags, + NULL + ); + } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } @@ -164,15 +303,28 @@ int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ */ int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ HANDLE h; + WCHAR *zWide = utf8ToUnicode(zFilename); assert( !id->isOpen ); - h = CreateFileA(zFilename, - GENERIC_READ, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, - NULL - ); + if( zWide ){ + h = CreateFileW(zWide, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + sqliteFree(zWide); + }else{ + h = CreateFileA(zFilename, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL + ); + } if( h==INVALID_HANDLE_VALUE ){ return SQLITE_CANTOPEN; } @@ -229,6 +381,16 @@ int sqlite3OsTempFileName(char *zBuf){ if( sqlite3_temp_directory ){ strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30); zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + }else if( isNT() ){ + char *zMulti; + WCHAR zWidePath[SQLITE_TEMPNAME_SIZE]; + GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath); + zMulti = unicodeToUtf8(zWidePath); + if( zMulti ){ + memcpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30); + zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0; + sqliteFree(zMulti); + } }else{ GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath); } @@ -364,28 +526,6 @@ int sqlite3OsFileSize(OsFile *id, i64 *pSize){ return SQLITE_OK; } -/* -** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. -** Return false (zero) for Win95, Win98, or WinME. -** -** Here is an interesting observation: Win95, Win98, and WinME lack -** the LockFileEx() API. But we can still statically link against that -** API as long as we don't call it win running Win95/98/ME. A call to -** this routine is used to determine if the host is Win95/98/ME or -** WinNT/2K/XP so that we will know whether or not we can safely call -** the LockFileEx() API. -*/ -static int isNT(void){ - static int osType = 0; /* 0=unknown 1=win95 2=winNT */ - if( osType==0 ){ - OSVERSIONINFO sInfo; - sInfo.dwOSVersionInfoSize = sizeof(sInfo); - GetVersionEx(&sInfo); - osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; - } - return osType==2; -} - /* ** Acquire a reader lock. ** Different API routines are called depending on whether or not this @@ -426,11 +566,18 @@ static int unlockReadLock(OsFile *id){ ** Check that a given pathname is a directory and is writable ** */ -int sqlite3OsIsDirWritable(char *zBuf){ +int sqlite3OsIsDirWritable(char *zDirname){ int fileAttr; - if(! zBuf ) return 0; - if(! isNT() && strlen(zBuf) > MAX_PATH ) return 0; - fileAttr = GetFileAttributesA(zBuf); + WCHAR *zWide; + if( zDirname==0 ) return 0; + if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0; + zWide = utf8ToUnicode(zDirname); + if( zWide ){ + fileAttr = GetFileAttributesW(zWide); + sqliteFree(zWide); + }else{ + fileAttr = GetFileAttributesA(zDirname); + } if( fileAttr == 0xffffffff ) return 0; if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){ return 0; @@ -641,6 +788,7 @@ int sqlite3OsUnlock(OsFile *id, int locktype){ char *sqlite3OsFullPathname(const char *zRelative){ char *zNotUsed; char *zFull; + WCHAR *zWide; int nByte; #ifdef __CYGWIN__ nByte = strlen(zRelative) + MAX_PATH + 1001; @@ -648,10 +796,22 @@ char *sqlite3OsFullPathname(const char *zRelative){ if( zFull==0 ) return 0; if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0; #else - nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1; - zFull = sqliteMalloc( nByte ); - if( zFull==0 ) return 0; - GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed); + zWide = utf8ToUnicode(zRelative); + if( zWide ){ + WCHAR *zTemp, *zNotUsedW; + nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1; + zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) ); + if( zTemp==0 ) return 0; + GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW); + sqliteFree(zWide); + 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); + } #endif return zFull; } diff --git a/src/test1.c b/src/test1.c index 3b555a39ef..37345a080c 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.158 2005/09/01 12:16:29 drh Exp $ +** $Id: test1.c,v 1.159 2005/09/05 19:08:29 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -3157,6 +3157,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_memMax; extern char sqlite3_query_plan[]; extern int sqlite3_like_count; +#if OS_WIN + extern int sqlite3_os_type; +#endif #ifdef SQLITE_DEBUG extern int sqlite3_vdbe_addop_trace; #endif @@ -3185,6 +3188,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ (char*)&sqlite3_os_trace, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_where_trace", (char*)&sqlite3_where_trace, TCL_LINK_INT); +#if OS_WIN + Tcl_LinkVar(interp, "sqlite_os_type", + (char*)&sqlite3_os_type, TCL_LINK_INT); +#endif #ifdef SQLITE_DEBUG Tcl_LinkVar(interp, "sqlite_addop_trace", (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);