1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sql/SQLite/os_win.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1623 @@
1.4 +/*
1.5 +** 2004 May 22
1.6 +**
1.7 +** The author disclaims copyright to this source code. In place of
1.8 +** a legal notice, here is a blessing:
1.9 +**
1.10 +** May you do good and not evil.
1.11 +** May you find forgiveness for yourself and forgive others.
1.12 +** May you share freely, never taking more than you give.
1.13 +**
1.14 +******************************************************************************
1.15 +**
1.16 +** This file contains code that is specific to windows.
1.17 +**
1.18 +** $Id: os_win.c,v 1.132 2008/07/31 01:34:34 shane Exp $
1.19 +*/
1.20 +#include "sqliteInt.h"
1.21 +#if SQLITE_OS_WIN /* This file is used for windows only */
1.22 +
1.23 +
1.24 +/*
1.25 +** A Note About Memory Allocation:
1.26 +**
1.27 +** This driver uses malloc()/free() directly rather than going through
1.28 +** the SQLite-wrappers sqlite3_malloc()/sqlite3_free(). Those wrappers
1.29 +** are designed for use on embedded systems where memory is scarce and
1.30 +** malloc failures happen frequently. Win32 does not typically run on
1.31 +** embedded systems, and when it does the developers normally have bigger
1.32 +** problems to worry about than running out of memory. So there is not
1.33 +** a compelling need to use the wrappers.
1.34 +**
1.35 +** But there is a good reason to not use the wrappers. If we use the
1.36 +** wrappers then we will get simulated malloc() failures within this
1.37 +** driver. And that causes all kinds of problems for our tests. We
1.38 +** could enhance SQLite to deal with simulated malloc failures within
1.39 +** the OS driver, but the code to deal with those failure would not
1.40 +** be exercised on Linux (which does not need to malloc() in the driver)
1.41 +** and so we would have difficulty writing coverage tests for that
1.42 +** code. Better to leave the code out, we think.
1.43 +**
1.44 +** The point of this discussion is as follows: When creating a new
1.45 +** OS layer for an embedded system, if you use this file as an example,
1.46 +** avoid the use of malloc()/free(). Those routines work ok on windows
1.47 +** desktops but not so well in embedded systems.
1.48 +*/
1.49 +
1.50 +#include <winbase.h>
1.51 +
1.52 +#ifdef __CYGWIN__
1.53 +# include <sys/cygwin.h>
1.54 +#endif
1.55 +
1.56 +/*
1.57 +** Macros used to determine whether or not to use threads.
1.58 +*/
1.59 +#if defined(THREADSAFE) && THREADSAFE
1.60 +# define SQLITE_W32_THREADS 1
1.61 +#endif
1.62 +
1.63 +/*
1.64 +** Include code that is common to all os_*.c files
1.65 +*/
1.66 +#include "os_common.h"
1.67 +
1.68 +/*
1.69 +** Determine if we are dealing with WindowsCE - which has a much
1.70 +** reduced API.
1.71 +*/
1.72 +#if defined(SQLITE_OS_WINCE)
1.73 +# define AreFileApisANSI() 1
1.74 +#endif
1.75 +
1.76 +/*
1.77 +** WinCE lacks native support for file locking so we have to fake it
1.78 +** with some code of our own.
1.79 +*/
1.80 +#if SQLITE_OS_WINCE
1.81 +typedef struct winceLock {
1.82 + int nReaders; /* Number of reader locks obtained */
1.83 + BOOL bPending; /* Indicates a pending lock has been obtained */
1.84 + BOOL bReserved; /* Indicates a reserved lock has been obtained */
1.85 + BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
1.86 +} winceLock;
1.87 +#endif
1.88 +
1.89 +/*
1.90 +** The winFile structure is a subclass of sqlite3_file* specific to the win32
1.91 +** portability layer.
1.92 +*/
1.93 +typedef struct winFile winFile;
1.94 +struct winFile {
1.95 + const sqlite3_io_methods *pMethod;/* Must be first */
1.96 + HANDLE h; /* Handle for accessing the file */
1.97 + unsigned char locktype; /* Type of lock currently held on this file */
1.98 + short sharedLockByte; /* Randomly chosen byte used as a shared lock */
1.99 +#if SQLITE_OS_WINCE
1.100 + WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
1.101 + HANDLE hMutex; /* Mutex used to control access to shared lock */
1.102 + HANDLE hShared; /* Shared memory segment used for locking */
1.103 + winceLock local; /* Locks obtained by this instance of winFile */
1.104 + winceLock *shared; /* Global shared lock memory for the file */
1.105 +#endif
1.106 +};
1.107 +
1.108 +
1.109 +/*
1.110 +** The following variable is (normally) set once and never changes
1.111 +** thereafter. It records whether the operating system is Win95
1.112 +** or WinNT.
1.113 +**
1.114 +** 0: Operating system unknown.
1.115 +** 1: Operating system is Win95.
1.116 +** 2: Operating system is WinNT.
1.117 +**
1.118 +** In order to facilitate testing on a WinNT system, the test fixture
1.119 +** can manually set this value to 1 to emulate Win98 behavior.
1.120 +*/
1.121 +#ifdef SQLITE_TEST
1.122 +int sqlite3_os_type = 0;
1.123 +#else
1.124 +static int sqlite3_os_type = 0;
1.125 +#endif
1.126 +
1.127 +/*
1.128 +** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
1.129 +** or WinCE. Return false (zero) for Win95, Win98, or WinME.
1.130 +**
1.131 +** Here is an interesting observation: Win95, Win98, and WinME lack
1.132 +** the LockFileEx() API. But we can still statically link against that
1.133 +** API as long as we don't call it win running Win95/98/ME. A call to
1.134 +** this routine is used to determine if the host is Win95/98/ME or
1.135 +** WinNT/2K/XP so that we will know whether or not we can safely call
1.136 +** the LockFileEx() API.
1.137 +*/
1.138 +#if SQLITE_OS_WINCE
1.139 +# define isNT() (1)
1.140 +#else
1.141 + static int isNT(void){
1.142 + if( sqlite3_os_type==0 ){
1.143 + OSVERSIONINFO sInfo;
1.144 + sInfo.dwOSVersionInfoSize = sizeof(sInfo);
1.145 + GetVersionEx(&sInfo);
1.146 + sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
1.147 + }
1.148 + return sqlite3_os_type==2;
1.149 + }
1.150 +#endif /* SQLITE_OS_WINCE */
1.151 +
1.152 +/*
1.153 +** Convert a UTF-8 string to microsoft unicode (UTF-16?).
1.154 +**
1.155 +** Space to hold the returned string is obtained from malloc.
1.156 +*/
1.157 +static WCHAR *utf8ToUnicode(const char *zFilename){
1.158 + int nChar;
1.159 + WCHAR *zWideFilename;
1.160 +
1.161 + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
1.162 + zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) );
1.163 + if( zWideFilename==0 ){
1.164 + return 0;
1.165 + }
1.166 + nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
1.167 + if( nChar==0 ){
1.168 + free(zWideFilename);
1.169 + zWideFilename = 0;
1.170 + }
1.171 + return zWideFilename;
1.172 +}
1.173 +
1.174 +/*
1.175 +** Convert microsoft unicode to UTF-8. Space to hold the returned string is
1.176 +** obtained from malloc().
1.177 +*/
1.178 +static char *unicodeToUtf8(const WCHAR *zWideFilename){
1.179 + int nByte;
1.180 + char *zFilename;
1.181 +
1.182 + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
1.183 + zFilename = malloc( nByte );
1.184 + if( zFilename==0 ){
1.185 + return 0;
1.186 + }
1.187 + nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
1.188 + 0, 0);
1.189 + if( nByte == 0 ){
1.190 + free(zFilename);
1.191 + zFilename = 0;
1.192 + }
1.193 + return zFilename;
1.194 +}
1.195 +
1.196 +/*
1.197 +** Convert an ansi string to microsoft unicode, based on the
1.198 +** current codepage settings for file apis.
1.199 +**
1.200 +** Space to hold the returned string is obtained
1.201 +** from malloc.
1.202 +*/
1.203 +static WCHAR *mbcsToUnicode(const char *zFilename){
1.204 + int nByte;
1.205 + WCHAR *zMbcsFilename;
1.206 + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1.207 +
1.208 + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR);
1.209 + zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) );
1.210 + if( zMbcsFilename==0 ){
1.211 + return 0;
1.212 + }
1.213 + nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
1.214 + if( nByte==0 ){
1.215 + free(zMbcsFilename);
1.216 + zMbcsFilename = 0;
1.217 + }
1.218 + return zMbcsFilename;
1.219 +}
1.220 +
1.221 +/*
1.222 +** Convert microsoft unicode to multibyte character string, based on the
1.223 +** user's Ansi codepage.
1.224 +**
1.225 +** Space to hold the returned string is obtained from
1.226 +** malloc().
1.227 +*/
1.228 +static char *unicodeToMbcs(const WCHAR *zWideFilename){
1.229 + int nByte;
1.230 + char *zFilename;
1.231 + int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1.232 +
1.233 + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
1.234 + zFilename = malloc( nByte );
1.235 + if( zFilename==0 ){
1.236 + return 0;
1.237 + }
1.238 + nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte,
1.239 + 0, 0);
1.240 + if( nByte == 0 ){
1.241 + free(zFilename);
1.242 + zFilename = 0;
1.243 + }
1.244 + return zFilename;
1.245 +}
1.246 +
1.247 +/*
1.248 +** Convert multibyte character string to UTF-8. Space to hold the
1.249 +** returned string is obtained from malloc().
1.250 +*/
1.251 +static char *mbcsToUtf8(const char *zFilename){
1.252 + char *zFilenameUtf8;
1.253 + WCHAR *zTmpWide;
1.254 +
1.255 + zTmpWide = mbcsToUnicode(zFilename);
1.256 + if( zTmpWide==0 ){
1.257 + return 0;
1.258 + }
1.259 + zFilenameUtf8 = unicodeToUtf8(zTmpWide);
1.260 + free(zTmpWide);
1.261 + return zFilenameUtf8;
1.262 +}
1.263 +
1.264 +/*
1.265 +** Convert UTF-8 to multibyte character string. Space to hold the
1.266 +** returned string is obtained from malloc().
1.267 +*/
1.268 +static char *utf8ToMbcs(const char *zFilename){
1.269 + char *zFilenameMbcs;
1.270 + WCHAR *zTmpWide;
1.271 +
1.272 + zTmpWide = utf8ToUnicode(zFilename);
1.273 + if( zTmpWide==0 ){
1.274 + return 0;
1.275 + }
1.276 + zFilenameMbcs = unicodeToMbcs(zTmpWide);
1.277 + free(zTmpWide);
1.278 + return zFilenameMbcs;
1.279 +}
1.280 +
1.281 +#if SQLITE_OS_WINCE
1.282 +/*************************************************************************
1.283 +** This section contains code for WinCE only.
1.284 +*/
1.285 +/*
1.286 +** WindowsCE does not have a localtime() function. So create a
1.287 +** substitute.
1.288 +*/
1.289 +#include <time.h>
1.290 +struct tm *__cdecl localtime(const time_t *t)
1.291 +{
1.292 + static struct tm y;
1.293 + FILETIME uTm, lTm;
1.294 + SYSTEMTIME pTm;
1.295 + sqlite3_int64 t64;
1.296 + t64 = *t;
1.297 + t64 = (t64 + 11644473600)*10000000;
1.298 + uTm.dwLowDateTime = t64 & 0xFFFFFFFF;
1.299 + uTm.dwHighDateTime= t64 >> 32;
1.300 + FileTimeToLocalFileTime(&uTm,&lTm);
1.301 + FileTimeToSystemTime(&lTm,&pTm);
1.302 + y.tm_year = pTm.wYear - 1900;
1.303 + y.tm_mon = pTm.wMonth - 1;
1.304 + y.tm_wday = pTm.wDayOfWeek;
1.305 + y.tm_mday = pTm.wDay;
1.306 + y.tm_hour = pTm.wHour;
1.307 + y.tm_min = pTm.wMinute;
1.308 + y.tm_sec = pTm.wSecond;
1.309 + return &y;
1.310 +}
1.311 +
1.312 +/* This will never be called, but defined to make the code compile */
1.313 +#define GetTempPathA(a,b)
1.314 +
1.315 +#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
1.316 +#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
1.317 +#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
1.318 +
1.319 +#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)]
1.320 +
1.321 +/*
1.322 +** Acquire a lock on the handle h
1.323 +*/
1.324 +static void winceMutexAcquire(HANDLE h){
1.325 + DWORD dwErr;
1.326 + do {
1.327 + dwErr = WaitForSingleObject(h, INFINITE);
1.328 + } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
1.329 +}
1.330 +/*
1.331 +** Release a lock acquired by winceMutexAcquire()
1.332 +*/
1.333 +#define winceMutexRelease(h) ReleaseMutex(h)
1.334 +
1.335 +/*
1.336 +** Create the mutex and shared memory used for locking in the file
1.337 +** descriptor pFile
1.338 +*/
1.339 +static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
1.340 + WCHAR *zTok;
1.341 + WCHAR *zName = utf8ToUnicode(zFilename);
1.342 + BOOL bInit = TRUE;
1.343 +
1.344 + /* Initialize the local lockdata */
1.345 + ZeroMemory(&pFile->local, sizeof(pFile->local));
1.346 +
1.347 + /* Replace the backslashes from the filename and lowercase it
1.348 + ** to derive a mutex name. */
1.349 + zTok = CharLowerW(zName);
1.350 + for (;*zTok;zTok++){
1.351 + if (*zTok == '\\') *zTok = '_';
1.352 + }
1.353 +
1.354 + /* Create/open the named mutex */
1.355 + pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
1.356 + if (!pFile->hMutex){
1.357 + free(zName);
1.358 + return FALSE;
1.359 + }
1.360 +
1.361 + /* Acquire the mutex before continuing */
1.362 + winceMutexAcquire(pFile->hMutex);
1.363 +
1.364 + /* Since the names of named mutexes, semaphores, file mappings etc are
1.365 + ** case-sensitive, take advantage of that by uppercasing the mutex name
1.366 + ** and using that as the shared filemapping name.
1.367 + */
1.368 + CharUpperW(zName);
1.369 + pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
1.370 + PAGE_READWRITE, 0, sizeof(winceLock),
1.371 + zName);
1.372 +
1.373 + /* Set a flag that indicates we're the first to create the memory so it
1.374 + ** must be zero-initialized */
1.375 + if (GetLastError() == ERROR_ALREADY_EXISTS){
1.376 + bInit = FALSE;
1.377 + }
1.378 +
1.379 + free(zName);
1.380 +
1.381 + /* If we succeeded in making the shared memory handle, map it. */
1.382 + if (pFile->hShared){
1.383 + pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
1.384 + FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
1.385 + /* If mapping failed, close the shared memory handle and erase it */
1.386 + if (!pFile->shared){
1.387 + CloseHandle(pFile->hShared);
1.388 + pFile->hShared = NULL;
1.389 + }
1.390 + }
1.391 +
1.392 + /* If shared memory could not be created, then close the mutex and fail */
1.393 + if (pFile->hShared == NULL){
1.394 + winceMutexRelease(pFile->hMutex);
1.395 + CloseHandle(pFile->hMutex);
1.396 + pFile->hMutex = NULL;
1.397 + return FALSE;
1.398 + }
1.399 +
1.400 + /* Initialize the shared memory if we're supposed to */
1.401 + if (bInit) {
1.402 + ZeroMemory(pFile->shared, sizeof(winceLock));
1.403 + }
1.404 +
1.405 + winceMutexRelease(pFile->hMutex);
1.406 + return TRUE;
1.407 +}
1.408 +
1.409 +/*
1.410 +** Destroy the part of winFile that deals with wince locks
1.411 +*/
1.412 +static void winceDestroyLock(winFile *pFile){
1.413 + if (pFile->hMutex){
1.414 + /* Acquire the mutex */
1.415 + winceMutexAcquire(pFile->hMutex);
1.416 +
1.417 + /* The following blocks should probably assert in debug mode, but they
1.418 + are to cleanup in case any locks remained open */
1.419 + if (pFile->local.nReaders){
1.420 + pFile->shared->nReaders --;
1.421 + }
1.422 + if (pFile->local.bReserved){
1.423 + pFile->shared->bReserved = FALSE;
1.424 + }
1.425 + if (pFile->local.bPending){
1.426 + pFile->shared->bPending = FALSE;
1.427 + }
1.428 + if (pFile->local.bExclusive){
1.429 + pFile->shared->bExclusive = FALSE;
1.430 + }
1.431 +
1.432 + /* De-reference and close our copy of the shared memory handle */
1.433 + UnmapViewOfFile(pFile->shared);
1.434 + CloseHandle(pFile->hShared);
1.435 +
1.436 + /* Done with the mutex */
1.437 + winceMutexRelease(pFile->hMutex);
1.438 + CloseHandle(pFile->hMutex);
1.439 + pFile->hMutex = NULL;
1.440 + }
1.441 +}
1.442 +
1.443 +/*
1.444 +** An implementation of the LockFile() API of windows for wince
1.445 +*/
1.446 +static BOOL winceLockFile(
1.447 + HANDLE *phFile,
1.448 + DWORD dwFileOffsetLow,
1.449 + DWORD dwFileOffsetHigh,
1.450 + DWORD nNumberOfBytesToLockLow,
1.451 + DWORD nNumberOfBytesToLockHigh
1.452 +){
1.453 + winFile *pFile = HANDLE_TO_WINFILE(phFile);
1.454 + BOOL bReturn = FALSE;
1.455 +
1.456 + if (!pFile->hMutex) return TRUE;
1.457 + winceMutexAcquire(pFile->hMutex);
1.458 +
1.459 + /* Wanting an exclusive lock? */
1.460 + if (dwFileOffsetLow == SHARED_FIRST
1.461 + && nNumberOfBytesToLockLow == SHARED_SIZE){
1.462 + if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
1.463 + pFile->shared->bExclusive = TRUE;
1.464 + pFile->local.bExclusive = TRUE;
1.465 + bReturn = TRUE;
1.466 + }
1.467 + }
1.468 +
1.469 + /* Want a read-only lock? */
1.470 + else if ((dwFileOffsetLow >= SHARED_FIRST &&
1.471 + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) &&
1.472 + nNumberOfBytesToLockLow == 1){
1.473 + if (pFile->shared->bExclusive == 0){
1.474 + pFile->local.nReaders ++;
1.475 + if (pFile->local.nReaders == 1){
1.476 + pFile->shared->nReaders ++;
1.477 + }
1.478 + bReturn = TRUE;
1.479 + }
1.480 + }
1.481 +
1.482 + /* Want a pending lock? */
1.483 + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){
1.484 + /* If no pending lock has been acquired, then acquire it */
1.485 + if (pFile->shared->bPending == 0) {
1.486 + pFile->shared->bPending = TRUE;
1.487 + pFile->local.bPending = TRUE;
1.488 + bReturn = TRUE;
1.489 + }
1.490 + }
1.491 + /* Want a reserved lock? */
1.492 + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
1.493 + if (pFile->shared->bReserved == 0) {
1.494 + pFile->shared->bReserved = TRUE;
1.495 + pFile->local.bReserved = TRUE;
1.496 + bReturn = TRUE;
1.497 + }
1.498 + }
1.499 +
1.500 + winceMutexRelease(pFile->hMutex);
1.501 + return bReturn;
1.502 +}
1.503 +
1.504 +/*
1.505 +** An implementation of the UnlockFile API of windows for wince
1.506 +*/
1.507 +static BOOL winceUnlockFile(
1.508 + HANDLE *phFile,
1.509 + DWORD dwFileOffsetLow,
1.510 + DWORD dwFileOffsetHigh,
1.511 + DWORD nNumberOfBytesToUnlockLow,
1.512 + DWORD nNumberOfBytesToUnlockHigh
1.513 +){
1.514 + winFile *pFile = HANDLE_TO_WINFILE(phFile);
1.515 + BOOL bReturn = FALSE;
1.516 +
1.517 + if (!pFile->hMutex) return TRUE;
1.518 + winceMutexAcquire(pFile->hMutex);
1.519 +
1.520 + /* Releasing a reader lock or an exclusive lock */
1.521 + if (dwFileOffsetLow >= SHARED_FIRST &&
1.522 + dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){
1.523 + /* Did we have an exclusive lock? */
1.524 + if (pFile->local.bExclusive){
1.525 + pFile->local.bExclusive = FALSE;
1.526 + pFile->shared->bExclusive = FALSE;
1.527 + bReturn = TRUE;
1.528 + }
1.529 +
1.530 + /* Did we just have a reader lock? */
1.531 + else if (pFile->local.nReaders){
1.532 + pFile->local.nReaders --;
1.533 + if (pFile->local.nReaders == 0)
1.534 + {
1.535 + pFile->shared->nReaders --;
1.536 + }
1.537 + bReturn = TRUE;
1.538 + }
1.539 + }
1.540 +
1.541 + /* Releasing a pending lock */
1.542 + else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
1.543 + if (pFile->local.bPending){
1.544 + pFile->local.bPending = FALSE;
1.545 + pFile->shared->bPending = FALSE;
1.546 + bReturn = TRUE;
1.547 + }
1.548 + }
1.549 + /* Releasing a reserved lock */
1.550 + else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
1.551 + if (pFile->local.bReserved) {
1.552 + pFile->local.bReserved = FALSE;
1.553 + pFile->shared->bReserved = FALSE;
1.554 + bReturn = TRUE;
1.555 + }
1.556 + }
1.557 +
1.558 + winceMutexRelease(pFile->hMutex);
1.559 + return bReturn;
1.560 +}
1.561 +
1.562 +/*
1.563 +** An implementation of the LockFileEx() API of windows for wince
1.564 +*/
1.565 +static BOOL winceLockFileEx(
1.566 + HANDLE *phFile,
1.567 + DWORD dwFlags,
1.568 + DWORD dwReserved,
1.569 + DWORD nNumberOfBytesToLockLow,
1.570 + DWORD nNumberOfBytesToLockHigh,
1.571 + LPOVERLAPPED lpOverlapped
1.572 +){
1.573 + /* If the caller wants a shared read lock, forward this call
1.574 + ** to winceLockFile */
1.575 + if (lpOverlapped->Offset == SHARED_FIRST &&
1.576 + dwFlags == 1 &&
1.577 + nNumberOfBytesToLockLow == SHARED_SIZE){
1.578 + return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
1.579 + }
1.580 + return FALSE;
1.581 +}
1.582 +/*
1.583 +** End of the special code for wince
1.584 +*****************************************************************************/
1.585 +#endif /* SQLITE_OS_WINCE */
1.586 +
1.587 +/*****************************************************************************
1.588 +** The next group of routines implement the I/O methods specified
1.589 +** by the sqlite3_io_methods object.
1.590 +******************************************************************************/
1.591 +
1.592 +/*
1.593 +** Close a file.
1.594 +**
1.595 +** It is reported that an attempt to close a handle might sometimes
1.596 +** fail. This is a very unreasonable result, but windows is notorious
1.597 +** for being unreasonable so I do not doubt that it might happen. If
1.598 +** the close fails, we pause for 100 milliseconds and try again. As
1.599 +** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
1.600 +** giving up and returning an error.
1.601 +*/
1.602 +#define MX_CLOSE_ATTEMPT 3
1.603 +static int winClose(sqlite3_file *id){
1.604 + int rc, cnt = 0;
1.605 + winFile *pFile = (winFile*)id;
1.606 + OSTRACE2("CLOSE %d\n", pFile->h);
1.607 + do{
1.608 + rc = CloseHandle(pFile->h);
1.609 + }while( rc==0 && cnt++ < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
1.610 +#if SQLITE_OS_WINCE
1.611 +#define WINCE_DELETION_ATTEMPTS 3
1.612 + winceDestroyLock(pFile);
1.613 + if( pFile->zDeleteOnClose ){
1.614 + int cnt = 0;
1.615 + while(
1.616 + DeleteFileW(pFile->zDeleteOnClose)==0
1.617 + && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
1.618 + && cnt++ < WINCE_DELETION_ATTEMPTS
1.619 + ){
1.620 + Sleep(100); /* Wait a little before trying again */
1.621 + }
1.622 + free(pFile->zDeleteOnClose);
1.623 + }
1.624 +#endif
1.625 + OpenCounter(-1);
1.626 + return rc ? SQLITE_OK : SQLITE_IOERR;
1.627 +}
1.628 +
1.629 +/*
1.630 +** Some microsoft compilers lack this definition.
1.631 +*/
1.632 +#ifndef INVALID_SET_FILE_POINTER
1.633 +# define INVALID_SET_FILE_POINTER ((DWORD)-1)
1.634 +#endif
1.635 +
1.636 +/*
1.637 +** Read data from a file into a buffer. Return SQLITE_OK if all
1.638 +** bytes were read successfully and SQLITE_IOERR if anything goes
1.639 +** wrong.
1.640 +*/
1.641 +static int winRead(
1.642 + sqlite3_file *id, /* File to read from */
1.643 + void *pBuf, /* Write content into this buffer */
1.644 + int amt, /* Number of bytes to read */
1.645 + sqlite3_int64 offset /* Begin reading at this offset */
1.646 +){
1.647 + LONG upperBits = (offset>>32) & 0x7fffffff;
1.648 + LONG lowerBits = offset & 0xffffffff;
1.649 + DWORD rc;
1.650 + DWORD got;
1.651 + winFile *pFile = (winFile*)id;
1.652 + assert( id!=0 );
1.653 + SimulateIOError(return SQLITE_IOERR_READ);
1.654 + OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype);
1.655 + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
1.656 + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
1.657 + return SQLITE_FULL;
1.658 + }
1.659 + if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){
1.660 + return SQLITE_IOERR_READ;
1.661 + }
1.662 + if( got==(DWORD)amt ){
1.663 + return SQLITE_OK;
1.664 + }else{
1.665 + memset(&((char*)pBuf)[got], 0, amt-got);
1.666 + return SQLITE_IOERR_SHORT_READ;
1.667 + }
1.668 +}
1.669 +
1.670 +/*
1.671 +** Write data from a buffer into a file. Return SQLITE_OK on success
1.672 +** or some other error code on failure.
1.673 +*/
1.674 +static int winWrite(
1.675 + sqlite3_file *id, /* File to write into */
1.676 + const void *pBuf, /* The bytes to be written */
1.677 + int amt, /* Number of bytes to write */
1.678 + sqlite3_int64 offset /* Offset into the file to begin writing at */
1.679 +){
1.680 + LONG upperBits = (offset>>32) & 0x7fffffff;
1.681 + LONG lowerBits = offset & 0xffffffff;
1.682 + DWORD rc;
1.683 + DWORD wrote;
1.684 + winFile *pFile = (winFile*)id;
1.685 + assert( id!=0 );
1.686 + SimulateIOError(return SQLITE_IOERR_WRITE);
1.687 + SimulateDiskfullError(return SQLITE_FULL);
1.688 + OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype);
1.689 + rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
1.690 + if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
1.691 + return SQLITE_FULL;
1.692 + }
1.693 + assert( amt>0 );
1.694 + while(
1.695 + amt>0
1.696 + && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0
1.697 + && wrote>0
1.698 + ){
1.699 + amt -= wrote;
1.700 + pBuf = &((char*)pBuf)[wrote];
1.701 + }
1.702 + if( !rc || amt>(int)wrote ){
1.703 + return SQLITE_FULL;
1.704 + }
1.705 + return SQLITE_OK;
1.706 +}
1.707 +
1.708 +/*
1.709 +** Truncate an open file to a specified size
1.710 +*/
1.711 +static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
1.712 + LONG upperBits = (nByte>>32) & 0x7fffffff;
1.713 + LONG lowerBits = nByte & 0xffffffff;
1.714 + winFile *pFile = (winFile*)id;
1.715 + OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte);
1.716 + SimulateIOError(return SQLITE_IOERR_TRUNCATE);
1.717 + SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
1.718 + SetEndOfFile(pFile->h);
1.719 + return SQLITE_OK;
1.720 +}
1.721 +
1.722 +#ifdef SQLITE_TEST
1.723 +/*
1.724 +** Count the number of fullsyncs and normal syncs. This is used to test
1.725 +** that syncs and fullsyncs are occuring at the right times.
1.726 +*/
1.727 +int sqlite3_sync_count = 0;
1.728 +int sqlite3_fullsync_count = 0;
1.729 +#endif
1.730 +
1.731 +/*
1.732 +** Make sure all writes to a particular file are committed to disk.
1.733 +*/
1.734 +static int winSync(sqlite3_file *id, int flags){
1.735 + winFile *pFile = (winFile*)id;
1.736 + OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype);
1.737 +#ifdef SQLITE_TEST
1.738 + if( flags & SQLITE_SYNC_FULL ){
1.739 + sqlite3_fullsync_count++;
1.740 + }
1.741 + sqlite3_sync_count++;
1.742 +#endif
1.743 + if( FlushFileBuffers(pFile->h) ){
1.744 + return SQLITE_OK;
1.745 + }else{
1.746 + return SQLITE_IOERR;
1.747 + }
1.748 +}
1.749 +
1.750 +/*
1.751 +** Determine the current size of a file in bytes
1.752 +*/
1.753 +static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
1.754 + winFile *pFile = (winFile*)id;
1.755 + DWORD upperBits, lowerBits;
1.756 + SimulateIOError(return SQLITE_IOERR_FSTAT);
1.757 + lowerBits = GetFileSize(pFile->h, &upperBits);
1.758 + *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
1.759 + return SQLITE_OK;
1.760 +}
1.761 +
1.762 +/*
1.763 +** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
1.764 +*/
1.765 +#ifndef LOCKFILE_FAIL_IMMEDIATELY
1.766 +# define LOCKFILE_FAIL_IMMEDIATELY 1
1.767 +#endif
1.768 +
1.769 +/*
1.770 +** Acquire a reader lock.
1.771 +** Different API routines are called depending on whether or not this
1.772 +** is Win95 or WinNT.
1.773 +*/
1.774 +static int getReadLock(winFile *pFile){
1.775 + int res;
1.776 + if( isNT() ){
1.777 + OVERLAPPED ovlp;
1.778 + ovlp.Offset = SHARED_FIRST;
1.779 + ovlp.OffsetHigh = 0;
1.780 + ovlp.hEvent = 0;
1.781 + res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
1.782 + 0, SHARED_SIZE, 0, &ovlp);
1.783 + }else{
1.784 + int lk;
1.785 + sqlite3_randomness(sizeof(lk), &lk);
1.786 + pFile->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
1.787 + res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
1.788 + }
1.789 + return res;
1.790 +}
1.791 +
1.792 +/*
1.793 +** Undo a readlock
1.794 +*/
1.795 +static int unlockReadLock(winFile *pFile){
1.796 + int res;
1.797 + if( isNT() ){
1.798 + res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
1.799 + }else{
1.800 + res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
1.801 + }
1.802 + return res;
1.803 +}
1.804 +
1.805 +/*
1.806 +** Lock the file with the lock specified by parameter locktype - one
1.807 +** of the following:
1.808 +**
1.809 +** (1) SHARED_LOCK
1.810 +** (2) RESERVED_LOCK
1.811 +** (3) PENDING_LOCK
1.812 +** (4) EXCLUSIVE_LOCK
1.813 +**
1.814 +** Sometimes when requesting one lock state, additional lock states
1.815 +** are inserted in between. The locking might fail on one of the later
1.816 +** transitions leaving the lock state different from what it started but
1.817 +** still short of its goal. The following chart shows the allowed
1.818 +** transitions and the inserted intermediate states:
1.819 +**
1.820 +** UNLOCKED -> SHARED
1.821 +** SHARED -> RESERVED
1.822 +** SHARED -> (PENDING) -> EXCLUSIVE
1.823 +** RESERVED -> (PENDING) -> EXCLUSIVE
1.824 +** PENDING -> EXCLUSIVE
1.825 +**
1.826 +** This routine will only increase a lock. The winUnlock() routine
1.827 +** erases all locks at once and returns us immediately to locking level 0.
1.828 +** It is not possible to lower the locking level one step at a time. You
1.829 +** must go straight to locking level 0.
1.830 +*/
1.831 +static int winLock(sqlite3_file *id, int locktype){
1.832 + int rc = SQLITE_OK; /* Return code from subroutines */
1.833 + int res = 1; /* Result of a windows lock call */
1.834 + int newLocktype; /* Set pFile->locktype to this value before exiting */
1.835 + int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
1.836 + winFile *pFile = (winFile*)id;
1.837 +
1.838 + assert( pFile!=0 );
1.839 + OSTRACE5("LOCK %d %d was %d(%d)\n",
1.840 + pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
1.841 +
1.842 + /* If there is already a lock of this type or more restrictive on the
1.843 + ** OsFile, do nothing. Don't use the end_lock: exit path, as
1.844 + ** sqlite3OsEnterMutex() hasn't been called yet.
1.845 + */
1.846 + if( pFile->locktype>=locktype ){
1.847 + return SQLITE_OK;
1.848 + }
1.849 +
1.850 + /* Make sure the locking sequence is correct
1.851 + */
1.852 + assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
1.853 + assert( locktype!=PENDING_LOCK );
1.854 + assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
1.855 +
1.856 + /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
1.857 + ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
1.858 + ** the PENDING_LOCK byte is temporary.
1.859 + */
1.860 + newLocktype = pFile->locktype;
1.861 + if( pFile->locktype==NO_LOCK
1.862 + || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
1.863 + ){
1.864 + int cnt = 3;
1.865 + while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
1.866 + /* Try 3 times to get the pending lock. The pending lock might be
1.867 + ** held by another reader process who will release it momentarily.
1.868 + */
1.869 + OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
1.870 + Sleep(1);
1.871 + }
1.872 + gotPendingLock = res;
1.873 + }
1.874 +
1.875 + /* Acquire a shared lock
1.876 + */
1.877 + if( locktype==SHARED_LOCK && res ){
1.878 + assert( pFile->locktype==NO_LOCK );
1.879 + res = getReadLock(pFile);
1.880 + if( res ){
1.881 + newLocktype = SHARED_LOCK;
1.882 + }
1.883 + }
1.884 +
1.885 + /* Acquire a RESERVED lock
1.886 + */
1.887 + if( locktype==RESERVED_LOCK && res ){
1.888 + assert( pFile->locktype==SHARED_LOCK );
1.889 + res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
1.890 + if( res ){
1.891 + newLocktype = RESERVED_LOCK;
1.892 + }
1.893 + }
1.894 +
1.895 + /* Acquire a PENDING lock
1.896 + */
1.897 + if( locktype==EXCLUSIVE_LOCK && res ){
1.898 + newLocktype = PENDING_LOCK;
1.899 + gotPendingLock = 0;
1.900 + }
1.901 +
1.902 + /* Acquire an EXCLUSIVE lock
1.903 + */
1.904 + if( locktype==EXCLUSIVE_LOCK && res ){
1.905 + assert( pFile->locktype>=SHARED_LOCK );
1.906 + res = unlockReadLock(pFile);
1.907 + OSTRACE2("unreadlock = %d\n", res);
1.908 + res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
1.909 + if( res ){
1.910 + newLocktype = EXCLUSIVE_LOCK;
1.911 + }else{
1.912 + OSTRACE2("error-code = %d\n", GetLastError());
1.913 + getReadLock(pFile);
1.914 + }
1.915 + }
1.916 +
1.917 + /* If we are holding a PENDING lock that ought to be released, then
1.918 + ** release it now.
1.919 + */
1.920 + if( gotPendingLock && locktype==SHARED_LOCK ){
1.921 + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
1.922 + }
1.923 +
1.924 + /* Update the state of the lock has held in the file descriptor then
1.925 + ** return the appropriate result code.
1.926 + */
1.927 + if( res ){
1.928 + rc = SQLITE_OK;
1.929 + }else{
1.930 + OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
1.931 + locktype, newLocktype);
1.932 + rc = SQLITE_BUSY;
1.933 + }
1.934 + pFile->locktype = newLocktype;
1.935 + return rc;
1.936 +}
1.937 +
1.938 +/*
1.939 +** This routine checks if there is a RESERVED lock held on the specified
1.940 +** file by this or any other process. If such a lock is held, return
1.941 +** non-zero, otherwise zero.
1.942 +*/
1.943 +static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
1.944 + int rc;
1.945 + winFile *pFile = (winFile*)id;
1.946 + assert( pFile!=0 );
1.947 + if( pFile->locktype>=RESERVED_LOCK ){
1.948 + rc = 1;
1.949 + OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
1.950 + }else{
1.951 + rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
1.952 + if( rc ){
1.953 + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
1.954 + }
1.955 + rc = !rc;
1.956 + OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
1.957 + }
1.958 + *pResOut = rc;
1.959 + return SQLITE_OK;
1.960 +}
1.961 +
1.962 +/*
1.963 +** Lower the locking level on file descriptor id to locktype. locktype
1.964 +** must be either NO_LOCK or SHARED_LOCK.
1.965 +**
1.966 +** If the locking level of the file descriptor is already at or below
1.967 +** the requested locking level, this routine is a no-op.
1.968 +**
1.969 +** It is not possible for this routine to fail if the second argument
1.970 +** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
1.971 +** might return SQLITE_IOERR;
1.972 +*/
1.973 +static int winUnlock(sqlite3_file *id, int locktype){
1.974 + int type;
1.975 + winFile *pFile = (winFile*)id;
1.976 + int rc = SQLITE_OK;
1.977 + assert( pFile!=0 );
1.978 + assert( locktype<=SHARED_LOCK );
1.979 + OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
1.980 + pFile->locktype, pFile->sharedLockByte);
1.981 + type = pFile->locktype;
1.982 + if( type>=EXCLUSIVE_LOCK ){
1.983 + UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
1.984 + if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
1.985 + /* This should never happen. We should always be able to
1.986 + ** reacquire the read lock */
1.987 + rc = SQLITE_IOERR_UNLOCK;
1.988 + }
1.989 + }
1.990 + if( type>=RESERVED_LOCK ){
1.991 + UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
1.992 + }
1.993 + if( locktype==NO_LOCK && type>=SHARED_LOCK ){
1.994 + unlockReadLock(pFile);
1.995 + }
1.996 + if( type>=PENDING_LOCK ){
1.997 + UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
1.998 + }
1.999 + pFile->locktype = locktype;
1.1000 + return rc;
1.1001 +}
1.1002 +
1.1003 +/*
1.1004 +** Control and query of the open file handle.
1.1005 +*/
1.1006 +static int winFileControl(sqlite3_file *id, int op, void *pArg){
1.1007 + switch( op ){
1.1008 + case SQLITE_FCNTL_LOCKSTATE: {
1.1009 + *(int*)pArg = ((winFile*)id)->locktype;
1.1010 + return SQLITE_OK;
1.1011 + }
1.1012 + }
1.1013 + return SQLITE_ERROR;
1.1014 +}
1.1015 +
1.1016 +/*
1.1017 +** Return the sector size in bytes of the underlying block device for
1.1018 +** the specified file. This is almost always 512 bytes, but may be
1.1019 +** larger for some devices.
1.1020 +**
1.1021 +** SQLite code assumes this function cannot fail. It also assumes that
1.1022 +** if two files are created in the same file-system directory (i.e.
1.1023 +** a database and its journal file) that the sector size will be the
1.1024 +** same for both.
1.1025 +*/
1.1026 +static int winSectorSize(sqlite3_file *id){
1.1027 + return SQLITE_DEFAULT_SECTOR_SIZE;
1.1028 +}
1.1029 +
1.1030 +/*
1.1031 +** Return a vector of device characteristics.
1.1032 +*/
1.1033 +static int winDeviceCharacteristics(sqlite3_file *id){
1.1034 + return 0;
1.1035 +}
1.1036 +
1.1037 +/*
1.1038 +** This vector defines all the methods that can operate on an
1.1039 +** sqlite3_file for win32.
1.1040 +*/
1.1041 +static const sqlite3_io_methods winIoMethod = {
1.1042 + 1, /* iVersion */
1.1043 + winClose,
1.1044 + winRead,
1.1045 + winWrite,
1.1046 + winTruncate,
1.1047 + winSync,
1.1048 + winFileSize,
1.1049 + winLock,
1.1050 + winUnlock,
1.1051 + winCheckReservedLock,
1.1052 + winFileControl,
1.1053 + winSectorSize,
1.1054 + winDeviceCharacteristics
1.1055 +};
1.1056 +
1.1057 +/***************************************************************************
1.1058 +** Here ends the I/O methods that form the sqlite3_io_methods object.
1.1059 +**
1.1060 +** The next block of code implements the VFS methods.
1.1061 +****************************************************************************/
1.1062 +
1.1063 +/*
1.1064 +** Convert a UTF-8 filename into whatever form the underlying
1.1065 +** operating system wants filenames in. Space to hold the result
1.1066 +** is obtained from malloc and must be freed by the calling
1.1067 +** function.
1.1068 +*/
1.1069 +static void *convertUtf8Filename(const char *zFilename){
1.1070 + void *zConverted = 0;
1.1071 + if( isNT() ){
1.1072 + zConverted = utf8ToUnicode(zFilename);
1.1073 + }else{
1.1074 + zConverted = utf8ToMbcs(zFilename);
1.1075 + }
1.1076 + /* caller will handle out of memory */
1.1077 + return zConverted;
1.1078 +}
1.1079 +
1.1080 +/*
1.1081 +** Create a temporary file name in zBuf. zBuf must be big enough to
1.1082 +** hold at pVfs->mxPathname characters.
1.1083 +*/
1.1084 +static int getTempname(int nBuf, char *zBuf){
1.1085 + static char zChars[] =
1.1086 + "abcdefghijklmnopqrstuvwxyz"
1.1087 + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1.1088 + "0123456789";
1.1089 + size_t i, j;
1.1090 + char zTempPath[MAX_PATH+1];
1.1091 + if( sqlite3_temp_directory ){
1.1092 + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
1.1093 + }else if( isNT() ){
1.1094 + char *zMulti;
1.1095 + WCHAR zWidePath[MAX_PATH];
1.1096 + GetTempPathW(MAX_PATH-30, zWidePath);
1.1097 + zMulti = unicodeToUtf8(zWidePath);
1.1098 + if( zMulti ){
1.1099 + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
1.1100 + free(zMulti);
1.1101 + }else{
1.1102 + return SQLITE_NOMEM;
1.1103 + }
1.1104 + }else{
1.1105 + char *zUtf8;
1.1106 + char zMbcsPath[MAX_PATH];
1.1107 + GetTempPathA(MAX_PATH-30, zMbcsPath);
1.1108 + zUtf8 = mbcsToUtf8(zMbcsPath);
1.1109 + if( zUtf8 ){
1.1110 + sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
1.1111 + free(zUtf8);
1.1112 + }else{
1.1113 + return SQLITE_NOMEM;
1.1114 + }
1.1115 + }
1.1116 + for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
1.1117 + zTempPath[i] = 0;
1.1118 + sqlite3_snprintf(nBuf-30, zBuf,
1.1119 + "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
1.1120 + j = strlen(zBuf);
1.1121 + sqlite3_randomness(20, &zBuf[j]);
1.1122 + for(i=0; i<20; i++, j++){
1.1123 + zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
1.1124 + }
1.1125 + zBuf[j] = 0;
1.1126 + OSTRACE2("TEMP FILENAME: %s\n", zBuf);
1.1127 + return SQLITE_OK;
1.1128 +}
1.1129 +
1.1130 +/*
1.1131 +** The return value of getLastErrorMsg
1.1132 +** is zero if the error message fits in the buffer, or non-zero
1.1133 +** otherwise (if the message was truncated).
1.1134 +*/
1.1135 +static int getLastErrorMsg(int nBuf, char *zBuf){
1.1136 + DWORD error = GetLastError();
1.1137 +
1.1138 +#if SQLITE_OS_WINCE
1.1139 + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
1.1140 +#else
1.1141 + /* FormatMessage returns 0 on failure. Otherwise it
1.1142 + ** returns the number of TCHARs written to the output
1.1143 + ** buffer, excluding the terminating null char.
1.1144 + */
1.1145 + if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
1.1146 + NULL,
1.1147 + error,
1.1148 + 0,
1.1149 + zBuf,
1.1150 + nBuf-1,
1.1151 + 0))
1.1152 + {
1.1153 + sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
1.1154 + }
1.1155 +#endif
1.1156 +
1.1157 + return 0;
1.1158 +}
1.1159 +
1.1160 +
1.1161 +/*
1.1162 +** Open a file.
1.1163 +*/
1.1164 +static int winOpen(
1.1165 + sqlite3_vfs *pVfs, /* Not used */
1.1166 + const char *zName, /* Name of the file (UTF-8) */
1.1167 + sqlite3_file *id, /* Write the SQLite file handle here */
1.1168 + int flags, /* Open mode flags */
1.1169 + int *pOutFlags /* Status return flags */
1.1170 +){
1.1171 + HANDLE h;
1.1172 + DWORD dwDesiredAccess;
1.1173 + DWORD dwShareMode;
1.1174 + DWORD dwCreationDisposition;
1.1175 + DWORD dwFlagsAndAttributes = 0;
1.1176 + int isTemp;
1.1177 + winFile *pFile = (winFile*)id;
1.1178 + void *zConverted; /* Filename in OS encoding */
1.1179 + const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
1.1180 + char zTmpname[MAX_PATH+1]; /* Buffer used to create temp filename */
1.1181 +
1.1182 + /* If the second argument to this function is NULL, generate a
1.1183 + ** temporary file name to use
1.1184 + */
1.1185 + if( !zUtf8Name ){
1.1186 + int rc = getTempname(MAX_PATH+1, zTmpname);
1.1187 + if( rc!=SQLITE_OK ){
1.1188 + return rc;
1.1189 + }
1.1190 + zUtf8Name = zTmpname;
1.1191 + }
1.1192 +
1.1193 + /* Convert the filename to the system encoding. */
1.1194 + zConverted = convertUtf8Filename(zUtf8Name);
1.1195 + if( zConverted==0 ){
1.1196 + return SQLITE_NOMEM;
1.1197 + }
1.1198 +
1.1199 + if( flags & SQLITE_OPEN_READWRITE ){
1.1200 + dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
1.1201 + }else{
1.1202 + dwDesiredAccess = GENERIC_READ;
1.1203 + }
1.1204 + if( flags & SQLITE_OPEN_CREATE ){
1.1205 + dwCreationDisposition = OPEN_ALWAYS;
1.1206 + }else{
1.1207 + dwCreationDisposition = OPEN_EXISTING;
1.1208 + }
1.1209 + if( flags & SQLITE_OPEN_MAIN_DB ){
1.1210 + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1.1211 + }else{
1.1212 + dwShareMode = 0;
1.1213 + }
1.1214 + if( flags & SQLITE_OPEN_DELETEONCLOSE ){
1.1215 +#if SQLITE_OS_WINCE
1.1216 + dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
1.1217 +#else
1.1218 + dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
1.1219 + | FILE_ATTRIBUTE_HIDDEN
1.1220 + | FILE_FLAG_DELETE_ON_CLOSE;
1.1221 +#endif
1.1222 + isTemp = 1;
1.1223 + }else{
1.1224 + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
1.1225 + isTemp = 0;
1.1226 + }
1.1227 + /* Reports from the internet are that performance is always
1.1228 + ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
1.1229 + dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
1.1230 + if( isNT() ){
1.1231 + h = CreateFileW((WCHAR*)zConverted,
1.1232 + dwDesiredAccess,
1.1233 + dwShareMode,
1.1234 + NULL,
1.1235 + dwCreationDisposition,
1.1236 + dwFlagsAndAttributes,
1.1237 + NULL
1.1238 + );
1.1239 + }else{
1.1240 + h = CreateFileA((char*)zConverted,
1.1241 + dwDesiredAccess,
1.1242 + dwShareMode,
1.1243 + NULL,
1.1244 + dwCreationDisposition,
1.1245 + dwFlagsAndAttributes,
1.1246 + NULL
1.1247 + );
1.1248 + }
1.1249 + if( h==INVALID_HANDLE_VALUE ){
1.1250 + free(zConverted);
1.1251 + if( flags & SQLITE_OPEN_READWRITE ){
1.1252 + return winOpen(0, zName, id,
1.1253 + ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags);
1.1254 + }else{
1.1255 + return SQLITE_CANTOPEN;
1.1256 + }
1.1257 + }
1.1258 + if( pOutFlags ){
1.1259 + if( flags & SQLITE_OPEN_READWRITE ){
1.1260 + *pOutFlags = SQLITE_OPEN_READWRITE;
1.1261 + }else{
1.1262 + *pOutFlags = SQLITE_OPEN_READONLY;
1.1263 + }
1.1264 + }
1.1265 + memset(pFile, 0, sizeof(*pFile));
1.1266 + pFile->pMethod = &winIoMethod;
1.1267 + pFile->h = h;
1.1268 +#if SQLITE_OS_WINCE
1.1269 + if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) ==
1.1270 + (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)
1.1271 + && !winceCreateLock(zName, pFile)
1.1272 + ){
1.1273 + CloseHandle(h);
1.1274 + free(zConverted);
1.1275 + return SQLITE_CANTOPEN;
1.1276 + }
1.1277 + if( isTemp ){
1.1278 + pFile->zDeleteOnClose = zConverted;
1.1279 + }else
1.1280 +#endif
1.1281 + {
1.1282 + free(zConverted);
1.1283 + }
1.1284 + OpenCounter(+1);
1.1285 + return SQLITE_OK;
1.1286 +}
1.1287 +
1.1288 +/*
1.1289 +** Delete the named file.
1.1290 +**
1.1291 +** Note that windows does not allow a file to be deleted if some other
1.1292 +** process has it open. Sometimes a virus scanner or indexing program
1.1293 +** will open a journal file shortly after it is created in order to do
1.1294 +** whatever it does. While this other process is holding the
1.1295 +** file open, we will be unable to delete it. To work around this
1.1296 +** problem, we delay 100 milliseconds and try to delete again. Up
1.1297 +** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
1.1298 +** up and returning an error.
1.1299 +*/
1.1300 +#define MX_DELETION_ATTEMPTS 5
1.1301 +static int winDelete(
1.1302 + sqlite3_vfs *pVfs, /* Not used on win32 */
1.1303 + const char *zFilename, /* Name of file to delete */
1.1304 + int syncDir /* Not used on win32 */
1.1305 +){
1.1306 + int cnt = 0;
1.1307 + int rc;
1.1308 + DWORD error;
1.1309 + void *zConverted = convertUtf8Filename(zFilename);
1.1310 + if( zConverted==0 ){
1.1311 + return SQLITE_NOMEM;
1.1312 + }
1.1313 + SimulateIOError(return SQLITE_IOERR_DELETE);
1.1314 + if( isNT() ){
1.1315 + do{
1.1316 + DeleteFileW(zConverted);
1.1317 + }while( ( ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
1.1318 + || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
1.1319 + && (cnt++ < MX_DELETION_ATTEMPTS)
1.1320 + && (Sleep(100), 1) );
1.1321 + }else{
1.1322 + do{
1.1323 + DeleteFileA(zConverted);
1.1324 + }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
1.1325 + || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
1.1326 + && (cnt++ < MX_DELETION_ATTEMPTS)
1.1327 + && (Sleep(100), 1) );
1.1328 + }
1.1329 + free(zConverted);
1.1330 + OSTRACE2("DELETE \"%s\"\n", zFilename);
1.1331 + return ( (rc==INVALID_FILE_ATTRIBUTES)
1.1332 + && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
1.1333 +}
1.1334 +
1.1335 +/*
1.1336 +** Check the existance and status of a file.
1.1337 +*/
1.1338 +static int winAccess(
1.1339 + sqlite3_vfs *pVfs, /* Not used on win32 */
1.1340 + const char *zFilename, /* Name of file to check */
1.1341 + int flags, /* Type of test to make on this file */
1.1342 + int *pResOut /* OUT: Result */
1.1343 +){
1.1344 + DWORD attr;
1.1345 + int rc;
1.1346 + void *zConverted = convertUtf8Filename(zFilename);
1.1347 + if( zConverted==0 ){
1.1348 + return SQLITE_NOMEM;
1.1349 + }
1.1350 + if( isNT() ){
1.1351 + attr = GetFileAttributesW((WCHAR*)zConverted);
1.1352 + }else{
1.1353 + attr = GetFileAttributesA((char*)zConverted);
1.1354 + }
1.1355 + free(zConverted);
1.1356 + switch( flags ){
1.1357 + case SQLITE_ACCESS_READ:
1.1358 + case SQLITE_ACCESS_EXISTS:
1.1359 + rc = attr!=INVALID_FILE_ATTRIBUTES;
1.1360 + break;
1.1361 + case SQLITE_ACCESS_READWRITE:
1.1362 + rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
1.1363 + break;
1.1364 + default:
1.1365 + assert(!"Invalid flags argument");
1.1366 + }
1.1367 + *pResOut = rc;
1.1368 + return SQLITE_OK;
1.1369 +}
1.1370 +
1.1371 +
1.1372 +/*
1.1373 +** Turn a relative pathname into a full pathname. Write the full
1.1374 +** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
1.1375 +** bytes in size.
1.1376 +*/
1.1377 +static int winFullPathname(
1.1378 + sqlite3_vfs *pVfs, /* Pointer to vfs object */
1.1379 + const char *zRelative, /* Possibly relative input path */
1.1380 + int nFull, /* Size of output buffer in bytes */
1.1381 + char *zFull /* Output buffer */
1.1382 +){
1.1383 +
1.1384 +#if defined(__CYGWIN__)
1.1385 + cygwin_conv_to_full_win32_path(zRelative, zFull);
1.1386 + return SQLITE_OK;
1.1387 +#endif
1.1388 +
1.1389 +#if SQLITE_OS_WINCE
1.1390 + /* WinCE has no concept of a relative pathname, or so I am told. */
1.1391 + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
1.1392 + return SQLITE_OK;
1.1393 +#endif
1.1394 +
1.1395 +#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
1.1396 + int nByte;
1.1397 + void *zConverted;
1.1398 + char *zOut;
1.1399 + zConverted = convertUtf8Filename(zRelative);
1.1400 + if( isNT() ){
1.1401 + WCHAR *zTemp;
1.1402 + nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3;
1.1403 + zTemp = malloc( nByte*sizeof(zTemp[0]) );
1.1404 + if( zTemp==0 ){
1.1405 + free(zConverted);
1.1406 + return SQLITE_NOMEM;
1.1407 + }
1.1408 + GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0);
1.1409 + free(zConverted);
1.1410 + zOut = unicodeToUtf8(zTemp);
1.1411 + free(zTemp);
1.1412 + }else{
1.1413 + char *zTemp;
1.1414 + nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
1.1415 + zTemp = malloc( nByte*sizeof(zTemp[0]) );
1.1416 + if( zTemp==0 ){
1.1417 + free(zConverted);
1.1418 + return SQLITE_NOMEM;
1.1419 + }
1.1420 + GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
1.1421 + free(zConverted);
1.1422 + zOut = mbcsToUtf8(zTemp);
1.1423 + free(zTemp);
1.1424 + }
1.1425 + if( zOut ){
1.1426 + sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
1.1427 + free(zOut);
1.1428 + return SQLITE_OK;
1.1429 + }else{
1.1430 + return SQLITE_NOMEM;
1.1431 + }
1.1432 +#endif
1.1433 +}
1.1434 +
1.1435 +#ifndef SQLITE_OMIT_LOAD_EXTENSION
1.1436 +/*
1.1437 +** Interfaces for opening a shared library, finding entry points
1.1438 +** within the shared library, and closing the shared library.
1.1439 +*/
1.1440 +/*
1.1441 +** Interfaces for opening a shared library, finding entry points
1.1442 +** within the shared library, and closing the shared library.
1.1443 +*/
1.1444 +static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
1.1445 + HANDLE h;
1.1446 + void *zConverted = convertUtf8Filename(zFilename);
1.1447 + if( zConverted==0 ){
1.1448 + return 0;
1.1449 + }
1.1450 + if( isNT() ){
1.1451 + h = LoadLibraryW((WCHAR*)zConverted);
1.1452 + }else{
1.1453 + h = LoadLibraryA((char*)zConverted);
1.1454 + }
1.1455 + free(zConverted);
1.1456 + return (void*)h;
1.1457 +}
1.1458 +static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
1.1459 + getLastErrorMsg(nBuf, zBufOut);
1.1460 +}
1.1461 +void *winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
1.1462 +#if SQLITE_OS_WINCE
1.1463 + /* The GetProcAddressA() routine is only available on wince. */
1.1464 + return GetProcAddressA((HANDLE)pHandle, zSymbol);
1.1465 +#else
1.1466 + /* All other windows platforms expect GetProcAddress() to take
1.1467 + ** an Ansi string regardless of the _UNICODE setting */
1.1468 + return GetProcAddress((HANDLE)pHandle, zSymbol);
1.1469 +#endif
1.1470 +}
1.1471 +void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
1.1472 + FreeLibrary((HANDLE)pHandle);
1.1473 +}
1.1474 +#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
1.1475 + #define winDlOpen 0
1.1476 + #define winDlError 0
1.1477 + #define winDlSym 0
1.1478 + #define winDlClose 0
1.1479 +#endif
1.1480 +
1.1481 +
1.1482 +/*
1.1483 +** Write up to nBuf bytes of randomness into zBuf.
1.1484 +*/
1.1485 +static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
1.1486 + int n = 0;
1.1487 + if( sizeof(SYSTEMTIME)<=nBuf-n ){
1.1488 + SYSTEMTIME x;
1.1489 + GetSystemTime(&x);
1.1490 + memcpy(&zBuf[n], &x, sizeof(x));
1.1491 + n += sizeof(x);
1.1492 + }
1.1493 + if( sizeof(DWORD)<=nBuf-n ){
1.1494 + DWORD pid = GetCurrentProcessId();
1.1495 + memcpy(&zBuf[n], &pid, sizeof(pid));
1.1496 + n += sizeof(pid);
1.1497 + }
1.1498 + if( sizeof(DWORD)<=nBuf-n ){
1.1499 + DWORD cnt = GetTickCount();
1.1500 + memcpy(&zBuf[n], &cnt, sizeof(cnt));
1.1501 + n += sizeof(cnt);
1.1502 + }
1.1503 + if( sizeof(LARGE_INTEGER)<=nBuf-n ){
1.1504 + LARGE_INTEGER i;
1.1505 + QueryPerformanceCounter(&i);
1.1506 + memcpy(&zBuf[n], &i, sizeof(i));
1.1507 + n += sizeof(i);
1.1508 + }
1.1509 + return n;
1.1510 +}
1.1511 +
1.1512 +
1.1513 +/*
1.1514 +** Sleep for a little while. Return the amount of time slept.
1.1515 +*/
1.1516 +static int winSleep(sqlite3_vfs *pVfs, int microsec){
1.1517 + Sleep((microsec+999)/1000);
1.1518 + return ((microsec+999)/1000)*1000;
1.1519 +}
1.1520 +
1.1521 +/*
1.1522 +** The following variable, if set to a non-zero value, becomes the result
1.1523 +** returned from sqlite3OsCurrentTime(). This is used for testing.
1.1524 +*/
1.1525 +#ifdef SQLITE_TEST
1.1526 +int sqlite3_current_time = 0;
1.1527 +#endif
1.1528 +
1.1529 +/*
1.1530 +** Find the current time (in Universal Coordinated Time). Write the
1.1531 +** current time and date as a Julian Day number into *prNow and
1.1532 +** return 0. Return 1 if the time and date cannot be found.
1.1533 +*/
1.1534 +int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
1.1535 + FILETIME ft;
1.1536 + /* FILETIME structure is a 64-bit value representing the number of
1.1537 + 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
1.1538 + */
1.1539 + double now;
1.1540 +#if SQLITE_OS_WINCE
1.1541 + SYSTEMTIME time;
1.1542 + GetSystemTime(&time);
1.1543 + /* if SystemTimeToFileTime() fails, it returns zero. */
1.1544 + if (!SystemTimeToFileTime(&time,&ft)){
1.1545 + return 1;
1.1546 + }
1.1547 +#else
1.1548 + GetSystemTimeAsFileTime( &ft );
1.1549 +#endif
1.1550 + now = ((double)ft.dwHighDateTime) * 4294967296.0;
1.1551 + *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
1.1552 +#ifdef SQLITE_TEST
1.1553 + if( sqlite3_current_time ){
1.1554 + *prNow = sqlite3_current_time/86400.0 + 2440587.5;
1.1555 + }
1.1556 +#endif
1.1557 + return 0;
1.1558 +}
1.1559 +
1.1560 +/*
1.1561 +** The idea is that this function works like a combination of
1.1562 +** GetLastError() and FormatMessage() on windows (or errno and
1.1563 +** strerror_r() on unix). After an error is returned by an OS
1.1564 +** function, SQLite calls this function with zBuf pointing to
1.1565 +** a buffer of nBuf bytes. The OS layer should populate the
1.1566 +** buffer with a nul-terminated UTF-8 encoded error message
1.1567 +** describing the last IO error to have occured within the calling
1.1568 +** thread.
1.1569 +**
1.1570 +** If the error message is too large for the supplied buffer,
1.1571 +** it should be truncated. The return value of xGetLastError
1.1572 +** is zero if the error message fits in the buffer, or non-zero
1.1573 +** otherwise (if the message was truncated). If non-zero is returned,
1.1574 +** then it is not necessary to include the nul-terminator character
1.1575 +** in the output buffer.
1.1576 +**
1.1577 +** Not supplying an error message will have no adverse effect
1.1578 +** on SQLite. It is fine to have an implementation that never
1.1579 +** returns an error message:
1.1580 +**
1.1581 +** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
1.1582 +** assert(zBuf[0]=='\0');
1.1583 +** return 0;
1.1584 +** }
1.1585 +**
1.1586 +** However if an error message is supplied, it will be incorporated
1.1587 +** by sqlite into the error message available to the user using
1.1588 +** sqlite3_errmsg(), possibly making IO errors easier to debug.
1.1589 +*/
1.1590 +static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
1.1591 + return getLastErrorMsg(nBuf, zBuf);
1.1592 +}
1.1593 +
1.1594 +/*
1.1595 +** Initialize and deinitialize the operating system interface.
1.1596 +*/
1.1597 +int sqlite3_os_init(void){
1.1598 + static sqlite3_vfs winVfs = {
1.1599 + 1, /* iVersion */
1.1600 + sizeof(winFile), /* szOsFile */
1.1601 + MAX_PATH, /* mxPathname */
1.1602 + 0, /* pNext */
1.1603 + "win32", /* zName */
1.1604 + 0, /* pAppData */
1.1605 +
1.1606 + winOpen, /* xOpen */
1.1607 + winDelete, /* xDelete */
1.1608 + winAccess, /* xAccess */
1.1609 + winFullPathname, /* xFullPathname */
1.1610 + winDlOpen, /* xDlOpen */
1.1611 + winDlError, /* xDlError */
1.1612 + winDlSym, /* xDlSym */
1.1613 + winDlClose, /* xDlClose */
1.1614 + winRandomness, /* xRandomness */
1.1615 + winSleep, /* xSleep */
1.1616 + winCurrentTime, /* xCurrentTime */
1.1617 + winGetLastError /* xGetLastError */
1.1618 + };
1.1619 + sqlite3_vfs_register(&winVfs, 1);
1.1620 + return SQLITE_OK;
1.1621 +}
1.1622 +int sqlite3_os_end(void){
1.1623 + return SQLITE_OK;
1.1624 +}
1.1625 +
1.1626 +#endif /* SQLITE_OS_WIN */