extensions/sqlite/sqlite-source/os_win.c
branchsourcemod-1.1.0
changeset 2283 03a67e41afbc
parent 1951 c7b4237fff50
child 2287 017a725c9d17
     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 */