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