15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2004 May 22
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The author disclaims copyright to this source code.  In place of
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a legal notice, here is a blessing:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you do good and not evil.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you find forgiveness for yourself and forgive others.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    May you share freely, never taking more than you give.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This file contains code that is specific to windows.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sqliteInt.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WIN               /* This file is used for windows only */
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A Note About Memory Allocation:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This driver uses malloc()/free() directly rather than going through
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are designed for use on embedded systems where memory is scarce and
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** malloc failures happen frequently.  Win32 does not typically run on
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** embedded systems, and when it does the developers normally have bigger
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** problems to worry about than running out of memory.  So there is not
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a compelling need to use the wrappers.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** But there is a good reason to not use the wrappers.  If we use the
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** wrappers then we will get simulated malloc() failures within this
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** driver.  And that causes all kinds of problems for our tests.  We
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** could enhance SQLite to deal with simulated malloc failures within
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the OS driver, but the code to deal with those failure would not
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** be exercised on Linux (which does not need to malloc() in the driver)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** and so we would have difficulty writing coverage tests for that
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** code.  Better to leave the code out, we think.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The point of this discussion is as follows:  When creating a new
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** OS layer for an embedded system, if you use this file as an example,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** avoid the use of malloc()/free().  Those routines work ok on windows
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** desktops but not so well in embedded systems.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winbase.h>
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __CYGWIN__
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# include <sys/cygwin.h>
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Macros used to determine whether or not to use threads.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(THREADSAFE) && THREADSAFE
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define SQLITE_W32_THREADS 1
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Include code that is common to all os_*.c files
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "os_common.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Some microsoft compilers lack this definition.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef INVALID_FILE_ATTRIBUTES
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Determine if we are dealing with WindowsCE - which has a much
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** reduced API.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define AreFileApisANSI() 1
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define FormatMessageW(a,b,c,d,e,f,g) 0
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward references */
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winShm winShm;           /* A connection to shared-memory */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winShmNode winShmNode;   /* A region of shared-memory */
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WinCE lacks native support for file locking so we have to fake it
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** with some code of our own.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winceLock {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nReaders;       /* Number of reader locks obtained */
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bPending;      /* Indicates a pending lock has been obtained */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bReserved;     /* Indicates a reserved lock has been obtained */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bExclusive;    /* Indicates an exclusive lock has been obtained */
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} winceLock;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The winFile structure is a subclass of sqlite3_file* specific to the win32
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** portability layer.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct winFile winFile;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winFile {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const sqlite3_io_methods *pMethod; /*** Must be first ***/
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs;      /* The VFS used to open this file */
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE h;               /* Handle for accessing the file */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char locktype; /* Type of lock currently held on this file */
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD lastErrno;        /* The Windows errno from the last I/O error */
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD sectorSize;       /* Sector size of the device file is on */
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *pShm;           /* Instance of shared memory on this file */
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zPath;      /* Full pathname of this file */
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szChunk;            /* Chunk size configured by FCNTL_CHUNK_SIZE */
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE hMutex;          /* Mutex used to control access to shared lock */
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE hShared;         /* Shared memory segment used for locking */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceLock local;        /* Locks obtained by this instance of winFile */
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceLock *shared;      /* Global shared lock memory for the file  */
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Forward prototypes.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getSectorSize(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_vfs *pVfs,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *zRelative     /* UTF-8 file name */
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following variable is (normally) set once and never changes
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** thereafter.  It records whether the operating system is Win95
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or WinNT.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 0:   Operating system unknown.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 1:   Operating system is Win95.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** 2:   Operating system is WinNT.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** In order to facilitate testing on a WinNT system, the test fixture
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** can manually set this value to 1 to emulate Win98 behavior.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_type = 0;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int sqlite3_os_type = 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here is an interesting observation:  Win95, Win98, and WinME lack
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the LockFileEx() API.  But we can still statically link against that
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** API as long as we don't call it when running Win95/98/ME.  A call to
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this routine is used to determine if the host is Win95/98/ME or
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WinNT/2K/XP so that we will know whether or not we can safely call
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the LockFileEx() API.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define isNT()  (1)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int isNT(void){
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( sqlite3_os_type==0 ){
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSVERSIONINFO sInfo;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sInfo.dwOSVersionInfoSize = sizeof(sInfo);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetVersionEx(&sInfo);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return sqlite3_os_type==2;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WINCE */
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert a UTF-8 string to microsoft unicode (UTF-16?).
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained from malloc.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WCHAR *utf8ToUnicode(const char *zFilename){
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nChar;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zWideFilename;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) );
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zWideFilename==0 ){
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nChar==0 ){
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zWideFilename);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zWideFilename = 0;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zWideFilename;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert microsoft unicode to UTF-8.  Space to hold the returned string is
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** obtained from malloc().
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *unicodeToUtf8(const WCHAR *zWideFilename){
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilename;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFilename = malloc( nByte );
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zFilename==0 ){
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0, 0);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nByte == 0 ){
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zFilename);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zFilename = 0;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zFilename;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert an ansi string to microsoft unicode, based on the
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current codepage settings for file apis.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** from malloc.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static WCHAR *mbcsToUnicode(const char *zFilename){
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zMbcsFilename;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) );
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zMbcsFilename==0 ){
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nByte==0 ){
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zMbcsFilename);
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zMbcsFilename = 0;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zMbcsFilename;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert microsoft unicode to multibyte character string, based on the
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** user's Ansi codepage.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Space to hold the returned string is obtained from
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** malloc().
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *unicodeToMbcs(const WCHAR *zWideFilename){
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilename;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFilename = malloc( nByte );
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zFilename==0 ){
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte,
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0, 0);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nByte == 0 ){
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zFilename);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zFilename = 0;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zFilename;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert multibyte character string to UTF-8.  Space to hold the
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned string is obtained from malloc().
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilenameUtf8;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zTmpWide;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zTmpWide = mbcsToUnicode(zFilename);
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zTmpWide==0 ){
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFilenameUtf8 = unicodeToUtf8(zTmpWide);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zTmpWide);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zFilenameUtf8;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert UTF-8 to multibyte character string.  Space to hold the
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returned string is obtained from malloc().
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static char *utf8ToMbcs(const char *zFilename){
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilenameMbcs;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zTmpWide;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zTmpWide = utf8ToUnicode(zFilename);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zTmpWide==0 ){
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zFilenameMbcs = unicodeToMbcs(zTmpWide);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zTmpWide);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zFilenameMbcs;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*************************************************************************
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This section contains code for WinCE only.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** WindowsCE does not have a localtime() function.  So create a
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** substitute.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h>
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct tm *__cdecl localtime(const time_t *t)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static struct tm y;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILETIME uTm, lTm;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SYSTEMTIME pTm;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 t64;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t64 = *t;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t64 = (t64 + 11644473600)*10000000;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uTm.dwHighDateTime= (DWORD)(t64 >> 32);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileTimeToLocalFileTime(&uTm,&lTm);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileTimeToSystemTime(&lTm,&pTm);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_year = pTm.wYear - 1900;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_mon = pTm.wMonth - 1;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_wday = pTm.wDayOfWeek;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_mday = pTm.wDay;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_hour = pTm.wHour;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_min = pTm.wMinute;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  y.tm_sec = pTm.wSecond;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return &y;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This will never be called, but defined to make the code compile */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetTempPathA(a,b)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LockFile(a,b,c,d,e)       winceLockFile(&a, b, c, d, e)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define UnlockFile(a,b,c,d,e)     winceUnlockFile(&a, b, c, d, e)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LockFileEx(a,b,c,d,e,f)   winceLockFileEx(&a, b, c, d, e, f)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Acquire a lock on the handle h
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winceMutexAcquire(HANDLE h){
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   DWORD dwErr;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   do {
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     dwErr = WaitForSingleObject(h, INFINITE);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Release a lock acquired by winceMutexAcquire()
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define winceMutexRelease(h) ReleaseMutex(h)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create the mutex and shared memory used for locking in the file
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** descriptor pFile
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zTok;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WCHAR *zName = utf8ToUnicode(zFilename);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bInit = TRUE;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the local lockdata */
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ZeroMemory(&pFile->local, sizeof(pFile->local));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Replace the backslashes from the filename and lowercase it
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to derive a mutex name. */
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zTok = CharLowerW(zName);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;*zTok;zTok++){
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*zTok == '\\') *zTok = '_';
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create/open the named mutex */
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pFile->hMutex){
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zName);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Acquire the mutex before continuing */
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexAcquire(pFile->hMutex);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Since the names of named mutexes, semaphores, file mappings etc are
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** case-sensitive, take advantage of that by uppercasing the mutex name
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** and using that as the shared filemapping name.
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CharUpperW(zName);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       PAGE_READWRITE, 0, sizeof(winceLock),
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       zName);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Set a flag that indicates we're the first to create the memory so it
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** must be zero-initialized */
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetLastError() == ERROR_ALREADY_EXISTS){
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bInit = FALSE;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zName);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we succeeded in making the shared memory handle, map it. */
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pFile->hShared){
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If mapping failed, close the shared memory handle and erase it */
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pFile->shared){
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = GetLastError();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CloseHandle(pFile->hShared);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->hShared = NULL;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If shared memory could not be created, then close the mutex and fail */
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pFile->hShared == NULL){
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winceMutexRelease(pFile->hMutex);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(pFile->hMutex);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->hMutex = NULL;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return FALSE;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the shared memory if we're supposed to */
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bInit) {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ZeroMemory(pFile->shared, sizeof(winceLock));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexRelease(pFile->hMutex);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TRUE;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Destroy the part of winFile that deals with wince locks
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winceDestroyLock(winFile *pFile){
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pFile->hMutex){
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Acquire the mutex */
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winceMutexAcquire(pFile->hMutex);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The following blocks should probably assert in debug mode, but they
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       are to cleanup in case any locks remained open */
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.nReaders){
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->nReaders --;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bReserved){
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bReserved = FALSE;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bPending){
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bPending = FALSE;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bExclusive){
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bExclusive = FALSE;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* De-reference and close our copy of the shared memory handle */
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnmapViewOfFile(pFile->shared);
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(pFile->hShared);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Done with the mutex */
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winceMutexRelease(pFile->hMutex);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(pFile->hMutex);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->hMutex = NULL;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the LockFile() API of windows for wince
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceLockFile(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE *phFile,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFileOffsetLow,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFileOffsetHigh,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToLockLow,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToLockHigh
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = HANDLE_TO_WINFILE(phFile);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bReturn = FALSE;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dwFileOffsetHigh);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pFile->hMutex) return TRUE;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexAcquire(pFile->hMutex);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Wanting an exclusive lock? */
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dwFileOffsetLow == (DWORD)SHARED_FIRST
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pFile->shared->bExclusive = TRUE;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       pFile->local.bExclusive = TRUE;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       bReturn = TRUE;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Want a read-only lock? */
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           nNumberOfBytesToLockLow == 1){
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->shared->bExclusive == 0){
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.nReaders ++;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pFile->local.nReaders == 1){
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->shared->nReaders ++;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Want a pending lock? */
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If no pending lock has been acquired, then acquire it */
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->shared->bPending == 0) {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bPending = TRUE;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.bPending = TRUE;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Want a reserved lock? */
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->shared->bReserved == 0) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bReserved = TRUE;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.bReserved = TRUE;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexRelease(pFile->hMutex);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bReturn;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the UnlockFile API of windows for wince
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceUnlockFile(
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE *phFile,
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFileOffsetLow,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFileOffsetHigh,
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToUnlockLow,
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToUnlockHigh
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = HANDLE_TO_WINFILE(phFile);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bReturn = FALSE;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dwFileOffsetHigh);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!pFile->hMutex) return TRUE;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexAcquire(pFile->hMutex);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Releasing a reader lock or an exclusive lock */
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Did we have an exclusive lock? */
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bExclusive){
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.bExclusive = FALSE;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bExclusive = FALSE;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Did we just have a reader lock? */
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else if (pFile->local.nReaders){
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.nReaders --;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (pFile->local.nReaders == 0)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pFile->shared->nReaders --;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Releasing a pending lock */
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bPending){
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.bPending = FALSE;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bPending = FALSE;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Releasing a reserved lock */
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pFile->local.bReserved) {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->local.bReserved = FALSE;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->shared->bReserved = FALSE;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bReturn = TRUE;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceMutexRelease(pFile->hMutex);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return bReturn;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** An implementation of the LockFileEx() API of windows for wince
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static BOOL winceLockFileEx(
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE *phFile,
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFlags,
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwReserved,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToLockLow,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nNumberOfBytesToLockHigh,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LPOVERLAPPED lpOverlapped
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(dwReserved);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the caller wants a shared read lock, forward this call
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to winceLockFile */
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lpOverlapped->Offset == (DWORD)SHARED_FIRST &&
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dwFlags == 1 &&
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FALSE;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** End of the special code for wince
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*****************************************************************************/
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WINCE */
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*****************************************************************************
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The next group of routines implement the I/O methods specified
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by the sqlite3_io_methods object.
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Some microsoft compilers lack this definition.
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef INVALID_SET_FILE_POINTER
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define INVALID_SET_FILE_POINTER ((DWORD)-1)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Move the current position of the file handle passed as the first
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** argument to offset iOffset within the file. If successful, return 0.
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, set pFile->lastErrno and return non-zero.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG upperBits;                 /* Most sig. 32 bits of new offset */
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LONG lowerBits;                 /* Least sig. 32 bits of new offset */
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwRet;                    /* Value returned by SetFilePointer() */
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lowerBits = (LONG)(iOffset & 0xffffffff);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* API oddity: If successful, SetFilePointer() returns a dword
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** containing the lower 32-bits of the new file-offset. Or, if it fails,
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** whether an error has actually occured, it is also necessary to call
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** GetLastError().
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dwRet = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a file.
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is reported that an attempt to close a handle might sometimes
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** fail.  This is a very unreasonable result, but windows is notorious
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** for being unreasonable so I do not doubt that it might happen.  If
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the close fails, we pause for 100 milliseconds and try again.  As
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** giving up and returning an error.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MX_CLOSE_ATTEMPT 3
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winClose(sqlite3_file *id){
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc, cnt = 0;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->pShm==0 );
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("CLOSE %d\n", pFile->h));
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do{
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = CloseHandle(pFile->h);
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) );
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WINCE_DELETION_ATTEMPTS 3
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winceDestroyLock(pFile);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->zDeleteOnClose ){
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int cnt = 0;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while(
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           DeleteFileW(pFile->zDeleteOnClose)==0
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        && cnt++ < WINCE_DELETION_ATTEMPTS
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ){
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       Sleep(100);  /* Wait a little before trying again */
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(pFile->zDeleteOnClose);
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenCounter(-1);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc ? SQLITE_OK : SQLITE_IOERR;
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Read data from a file into a buffer.  Return SQLITE_OK if all
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes were read successfully and SQLITE_IOERR if anything goes
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** wrong.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winRead(
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *id,          /* File to read from */
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *pBuf,                /* Write content into this buffer */
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amt,                   /* Number of bytes to read */
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 offset       /* Begin reading at this offset */
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;  /* file handle */
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD nRead;                    /* Number of bytes actually read from file */
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_READ);
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( seekWinFile(pFile, offset) ){
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_FULL;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_READ;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( nRead<(DWORD)amt ){
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Unread parts of the buffer must be zero-filled */
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&((char*)pBuf)[nRead], 0, amt-nRead);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_SHORT_READ;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write data from a buffer into a file.  Return SQLITE_OK on success
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** or some other error code on failure.
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winWrite(
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *id,               /* File to write into */
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const void *pBuf,               /* The bytes to be written */
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int amt,                        /* Number of bytes to write */
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 offset            /* Offset into the file to begin writing at */
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                         /* True if error has occured, else false */
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;  /* File handle */
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( amt>0 );
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_WRITE);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateDiskfullError(return SQLITE_FULL);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = seekWinFile(pFile, offset);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc==0 ){
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nRem = amt;               /* Number of bytes yet to be written */
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD nWrite;                 /* Bytes written by each WriteFile() call */
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      aRem += nWrite;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nRem -= nWrite;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( nRem>0 ){
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pFile->lastErrno = GetLastError();
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = 1;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc ){
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ){
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_FULL;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_WRITE;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Truncate an open file to a specified size
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;  /* File handle object */
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;             /* Return code for this function */
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_TRUNCATE);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the user has configured a chunk-size for this file, truncate the
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** file so that it consists of an integer number of chunks (i.e. the
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** actual file size after the operation may be larger than the requested
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** size).
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->szChunk ){
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( seekWinFile(pFile, nByte) ){
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR_TRUNCATE;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( 0==SetEndOfFile(pFile->h) ){
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_IOERR_TRUNCATE;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Count the number of fullsyncs and normal syncs.  This is used to test
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** that syncs and fullsyncs are occuring at the right times.
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_sync_count = 0;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_fullsync_count = 0;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Make sure all writes to a particular file are committed to disk.
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSync(sqlite3_file *id, int flags){
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || defined(SQLITE_DEBUG)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(id);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile );
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert((flags&0x0F)==SQLITE_SYNC_NORMAL
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      || (flags&0x0F)==SQLITE_SYNC_FULL
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_TEST
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(flags);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags & SQLITE_SYNC_FULL ){
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_fullsync_count++;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_sync_count++;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Unix cannot, but some systems may return SQLITE_FULL from here. This
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** line is to test that doing so does not cause any problems.
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateDiskfullError( return SQLITE_FULL );
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR; );
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** no-op
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_NO_SYNC
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( FlushFileBuffers(pFile->h) ){
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Determine the current size of a file in bytes
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD upperBits;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD lowerBits;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD error;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_FSTAT);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lowerBits = GetFileSize(pFile->h, &upperBits);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if(   (lowerBits == INVALID_FILE_SIZE)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     && ((error = GetLastError()) != NO_ERROR) )
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = error;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_IOERR_FSTAT;
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LOCKFILE_FAIL_IMMEDIATELY
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define LOCKFILE_FAIL_IMMEDIATELY 1
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Acquire a reader lock.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Different API routines are called depending on whether or not this
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is Win95 or WinNT.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getReadLock(winFile *pFile){
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int res;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OVERLAPPED ovlp;
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ovlp.Offset = SHARED_FIRST;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ovlp.OffsetHigh = 0;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ovlp.hEvent = 0;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     0, SHARED_SIZE, 0, &ovlp);
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int lk;
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_randomness(sizeof(lk), &lk);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( res == 0 ){
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Undo a readlock
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int unlockReadLock(winFile *pFile){
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int res;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( res == 0 ){
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return res;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lock the file with the lock specified by parameter locktype - one
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** of the following:
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (1) SHARED_LOCK
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (2) RESERVED_LOCK
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (3) PENDING_LOCK
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     (4) EXCLUSIVE_LOCK
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sometimes when requesting one lock state, additional lock states
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are inserted in between.  The locking might fail on one of the later
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions leaving the lock state different from what it started but
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** still short of its goal.  The following chart shows the allowed
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** transitions and the inserted intermediate states:
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    UNLOCKED -> SHARED
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> RESERVED
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    SHARED -> (PENDING) -> EXCLUSIVE
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    RESERVED -> (PENDING) -> EXCLUSIVE
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    PENDING -> EXCLUSIVE
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine will only increase a lock.  The winUnlock() routine
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** erases all locks at once and returns us immediately to locking level 0.
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is not possible to lower the locking level one step at a time.  You
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must go straight to locking level 0.
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winLock(sqlite3_file *id, int locktype){
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;    /* Return code from subroutines */
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int res = 1;           /* Result of a windows lock call */
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int newLocktype;       /* Set pFile->locktype to this value before exiting */
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD error = NO_ERROR;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("LOCK %d %d was %d(%d)\n",
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If there is already a lock of this type or more restrictive on the
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** OsFile, do nothing. Don't use the end_lock: exit path, as
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** sqlite3OsEnterMutex() hasn't been called yet.
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->locktype>=locktype ){
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Make sure the locking sequence is correct
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( locktype!=PENDING_LOCK );
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the PENDING_LOCK byte is temporary.
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  newLocktype = pFile->locktype;
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if(   (pFile->locktype==NO_LOCK)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || (   (locktype==EXCLUSIVE_LOCK)
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         && (pFile->locktype==RESERVED_LOCK))
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int cnt = 3;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Try 3 times to get the pending lock.  The pending lock might be
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** held by another reader process who will release it momentarily.
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Sleep(1);
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gotPendingLock = res;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !res ){
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error = GetLastError();
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Acquire a shared lock
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( locktype==SHARED_LOCK && res ){
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->locktype==NO_LOCK );
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = getReadLock(pFile);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( res ){
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      newLocktype = SHARED_LOCK;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error = GetLastError();
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Acquire a RESERVED lock
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( locktype==RESERVED_LOCK && res ){
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->locktype==SHARED_LOCK );
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( res ){
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      newLocktype = RESERVED_LOCK;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error = GetLastError();
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Acquire a PENDING lock
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( locktype==EXCLUSIVE_LOCK && res ){
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    newLocktype = PENDING_LOCK;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gotPendingLock = 0;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Acquire an EXCLUSIVE lock
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( locktype==EXCLUSIVE_LOCK && res ){
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert( pFile->locktype>=SHARED_LOCK );
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = unlockReadLock(pFile);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("unreadlock = %d\n", res));
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( res ){
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      newLocktype = EXCLUSIVE_LOCK;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error = GetLastError();
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("error-code = %d\n", error));
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      getReadLock(pFile);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If we are holding a PENDING lock that ought to be released, then
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** release it now.
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( gotPendingLock && locktype==SHARED_LOCK ){
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Update the state of the lock has held in the file descriptor then
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** return the appropriate result code.
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( res ){
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           locktype, newLocktype));
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = error;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->locktype = (u8)newLocktype;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This routine checks if there is a RESERVED lock held on the specified
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file by this or any other process. If such a lock is held, return
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** non-zero, otherwise zero.
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pFile->locktype>=RESERVED_LOCK ){
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = 1;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc ){
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = !rc;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = rc;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Lower the locking level on file descriptor id to locktype.  locktype
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** must be either NO_LOCK or SHARED_LOCK.
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the locking level of the file descriptor is already at or below
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the requested locking level, this routine is a no-op.
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** It is not possible for this routine to fail if the second argument
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** might return SQLITE_IOERR;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winUnlock(sqlite3_file *id, int locktype){
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int type;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pFile!=0 );
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( locktype<=SHARED_LOCK );
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          pFile->locktype, pFile->sharedLockByte));
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  type = pFile->locktype;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( type>=EXCLUSIVE_LOCK ){
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* This should never happen.  We should always be able to
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** reacquire the read lock */
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_UNLOCK;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( type>=RESERVED_LOCK ){
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( locktype==NO_LOCK && type>=SHARED_LOCK ){
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unlockReadLock(pFile);
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( type>=PENDING_LOCK ){
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->locktype = (u8)locktype;
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Control and query of the open file handle.
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFileControl(sqlite3_file *id, int op, void *pArg){
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( op ){
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_LOCKSTATE: {
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *(int*)pArg = ((winFile*)id)->locktype;
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_LAST_ERRNO: {
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *(int*)pArg = (int)((winFile*)id)->lastErrno;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_CHUNK_SIZE: {
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ((winFile*)id)->szChunk = *(int *)pArg;
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_SIZE_HINT: {
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_int64 sz = *(sqlite3_int64*)pArg;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(1);
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      winTruncate(id, sz);
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SimulateIOErrorBenign(0);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_FCNTL_SYNC_OMITTED: {
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_OK;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_NOTFOUND;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return the sector size in bytes of the underlying block device for
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the specified file. This is almost always 512 bytes, but may be
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** larger for some devices.
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** SQLite code assumes this function cannot fail. It also assumes that
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** if two files are created in the same file-system directory (i.e.
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a database and its journal file) that the sector size will be the
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** same for both.
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSectorSize(sqlite3_file *id){
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (int)(((winFile*)id)->sectorSize);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Return a vector of device characteristics.
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDeviceCharacteristics(sqlite3_file *id){
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(id);
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Windows will only let you create file view mappings
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on allocation size granularity boundaries.
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** During sqlite3_os_init() we do a GetSystemInfo()
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to get the granularity size.
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SYSTEM_INFO winSysInfo;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Helper functions to obtain and relinquish the global mutex. The
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** global mutex is used to protect the winLockInfo objects used by
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this file, all of which may be shared by multiple threads.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Function winShmMutexHeld() is used to assert() that the global mutex
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is held when required. This function is only used as part of assert()
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** statements. e.g.
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   winShmEnterMutex()
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     assert( winShmMutexHeld() );
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   winShmLeaveMutex()
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmEnterMutex(void){
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmLeaveMutex(void){
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmMutexHeld(void) {
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Object used to represent a single file opened and mmapped to provide
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared memory.  When multiple threads all reference the same
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** log-summary, each thread has its own winFile object, but they all
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** point to a single instance of this object.  In other words, each
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** log-summary is opened only once per process.
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmMutexHeld() must be true when creating or destroying
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this object or while reading or writing the following fields:
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      nRef
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      pNext
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are read-only after the object is created:
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      fid
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**      zFilename
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** winShmMutexHeld() is true when reading or writing any other field
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in this structure.
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winShmNode {
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex *mutex;      /* Mutex to access this object */
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFilename;           /* Name of the file */
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile hFile;             /* File handle from winOpen */
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szRegion;              /* Size of shared-memory regions */
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRegion;               /* Size of array apRegion */
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ShmRegion {
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE hMap;             /* File handle from CreateFileMapping */
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *pMap;
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } *aRegion;
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD lastErrno;           /* The Windows errno from the last I/O error */
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nRef;                  /* Number of winShm objects pointing to this */
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *pFirst;            /* All winShm objects pointing to this */
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pNext;         /* Next in list of all winShmNode objects */
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 nextShmId;              /* Next available winShm.id value */
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** A global array of all winShmNode objects.
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The winShmMutexHeld() must be true while reading or writing this list.
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static winShmNode *winShmNodeList = 0;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Structure used internally by this VFS to record the state of an
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** open shared memory connection.
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following fields are initialized when this object is created and
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are read-only thereafter:
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    winShm.pShmNode
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**    winShm.id
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All other fields are read/write.  The winShm.pShmNode->mutex must be held
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** while accessing any read/write fields.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct winShm {
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pShmNode;      /* The underlying winShmNode object */
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *pNext;             /* Next winShm with the same winShmNode */
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 hasMutex;               /* True if holding the winShmNode mutex */
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 sharedMask;            /* Mask of shared locks held */
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 exclMask;              /* Mask of exclusive locks held */
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u8 id;                     /* Id of this connection with its winShmNode */
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Constants used for locking
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_SHM_BASE   ((22+SQLITE_SHM_NLOCK)*4)        /* first lock byte */
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WIN_SHM_DMS    (WIN_SHM_BASE+SQLITE_SHM_NLOCK)  /* deadman switch */
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Apply advisory locks for all n bytes beginning at ofst.
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_UNLCK  1
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_RDLCK  2
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _SHM_WRLCK  3
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmSystemLock(
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pFile,    /* Apply locks to this open shared-memory segment */
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int lockType,         /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ofst,             /* Offset to first byte to be locked/unlocked */
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte             /* Number of bytes to lock or unlock */
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OVERLAPPED ovlp;
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFlags;
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = 0;           /* Result code form Lock/UnlockFileEx() */
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Access to the winShmNode object is serialized by the caller */
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Initialize the locking parameters */
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&ovlp, 0, sizeof(OVERLAPPED));
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ovlp.Offset = ofst;
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Release/Acquire the system-level lock */
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( lockType==_SHM_UNLCK ){
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = UnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = LockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc!= 0 ){
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_OK;
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno =  GetLastError();
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = SQLITE_BUSY;
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n",
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pFile->hFile.h,
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           rc==SQLITE_OK ? "ok" : "failed",
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           pFile->lastErrno));
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Forward references to VFS methods */
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDelete(sqlite3_vfs *,const char*,int);
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This is not a VFS shared-memory method; it is a utility function called
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by VFS shared-memory methods.
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode **pp;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *p;
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL bRc;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( winShmMutexHeld() );
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pp = &winShmNodeList;
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while( (p = *pp)!=0 ){
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( p->nRef==0 ){
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int i;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( p->mutex ) sqlite3_mutex_free(p->mutex);
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for(i=0; i<p->nRegion; i++){
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRc = UnmapViewOfFile(p->aRegion[i].pMap);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (int)GetCurrentProcessId(), i,
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 bRc ? "ok" : "failed"));
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bRc = CloseHandle(p->aRegion[i].hMap);
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (int)GetCurrentProcessId(), i,
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 bRc ? "ok" : "failed"));
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( p->hFile.h != INVALID_HANDLE_VALUE ){
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SimulateIOErrorBenign(1);
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        winClose((sqlite3_file *)&p->hFile);
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SimulateIOErrorBenign(0);
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( deleteFlag ){
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SimulateIOErrorBenign(1);
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        winDelete(pVfs, p->zFilename, 0);
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SimulateIOErrorBenign(0);
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pp = p->pNext;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(p->aRegion);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_free(p);
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pp = &p->pNext;
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open the shared-memory area associated with database file pDbFd.
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** When opening a new shared-memory file, if no other instances of that
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file are currently open, in this process or in other processes, then
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the file must be truncated to zero length or have its header cleared.
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpenSharedMemory(winFile *pDbFd){
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct winShm *p;                  /* The connection to be opened */
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct winShmNode *pShmNode = 0;   /* The underlying mmapped file */
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;                            /* Result code */
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct winShmNode *pNew;           /* Newly allocated winShmNode */
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nName;                         /* Size of zName in bytes */
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pDbFd->pShm==0 );    /* Not previously opened */
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Allocate space for the new sqlite3_shm object.  Also speculatively
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** allocate space for a new winShmNode and filename.
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = sqlite3_malloc( sizeof(*p) );
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return SQLITE_NOMEM;
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, sizeof(*p));
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nName = sqlite3Strlen30(pDbFd->zPath);
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 15 );
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pNew==0 ){
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(p);
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pNew, 0, sizeof(*pNew));
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pNew->zFilename = (char*)&pNew[1];
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Look to see if there is an existing winShmNode that can be used.
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** If no matching winShmNode currently exists, create a new one.
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmEnterMutex();
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TBD need to come up with better match here.  Perhaps
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** use FILE_ID_BOTH_DIR_INFO Structure.
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode ){
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_free(pNew);
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode = pNew;
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pNew = 0;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->pNext = winShmNodeList;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winShmNodeList = pShmNode;
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( pShmNode->mutex==0 ){
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_NOMEM;
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shm_open_err;
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = winOpen(pDbFd->pVfs,
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 pShmNode->zFilename,             /* Name of the file (UTF-8) */
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 0);
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( SQLITE_OK!=rc ){
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_CANTOPEN_BKPT;
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shm_open_err;
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Check to see if another process is holding the dead-man switch.
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** If not, truncate the file to zero length.
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR_SHMOPEN;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc ) goto shm_open_err;
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Make the new connection a child of the winShmNode */
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pShmNode = pShmNode;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_DEBUG
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->id = pShmNode->nextShmId++;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->nRef++;
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd->pShm = p;
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmLeaveMutex();
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The reference count on pShmNode has already been incremented under
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** the cover of the winShmEnterMutex() mutex and the pointer from the
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** new (struct winShm) object to the pShmNode has been set. All that is
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** left to do is to link the new object into the linked list starting
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** mutex.
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->pNext = pShmNode->pFirst;
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->pFirst = p;
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Jump here on any error */
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shm_open_err:
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmPurge(pDbFd->pVfs, 0);      /* This call frees pShmNode if required */
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(pNew);
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmLeaveMutex();
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Close a connection to shared-memory.  Delete the underlying
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** storage if deleteFlag is true.
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmUnmap(
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,          /* Database holding shared memory */
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int deleteFlag             /* Delete after closing if true */
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pDbFd;       /* Database holding shared-memory */
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *p;            /* The connection to be closed */
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pShmNode; /* The underlying shared-memory file */
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm **pp;          /* For looping over sibling connections */
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd = (winFile*)fd;
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p = pDbFd->pShm;
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( p==0 ) return SQLITE_OK;
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode = p->pShmNode;
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Remove connection p from the set of connections associated
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** with pShmNode */
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pp = p->pNext;
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Free the connection p */
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_free(p);
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pDbFd->pShm = 0;
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If pShmNode->nRef has reached 0, then close the underlying
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** shared-memory file, too */
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmEnterMutex();
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( pShmNode->nRef>0 );
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode->nRef--;
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRef==0 ){
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winShmPurge(pDbFd->pVfs, deleteFlag);
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmLeaveMutex();
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Change the lock state for a shared-memory segment.
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmLock(
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,          /* Database file holding the shared memory */
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ofst,                  /* First lock to acquire or release */
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n,                     /* Number of locks to acquire or release */
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags                  /* What to do with the lock */
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pDbFd = (winFile*)fd;        /* Connection holding shared memory */
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *p = pDbFd->pShm;              /* The shared memory being locked */
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *pX;                           /* For looping over all siblings */
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pShmNode = p->pShmNode;
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;                   /* Result code */
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  u16 mask;                             /* Mask of locks to take or release */
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n>=1 );
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( n>1 || mask==(1<<ofst) );
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( flags & SQLITE_SHM_UNLOCK ){
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u16 allMask = 0; /* Mask of locks held by siblings */
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* See if any siblings hold this same lock */
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( pX==p ) continue;
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allMask |= pX->sharedMask;
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Unlock the system-level locks */
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( (mask & allMask)==0 ){
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_OK;
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Undo the local locks */
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->exclMask &= ~mask;
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->sharedMask &= ~mask;
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( flags & SQLITE_SHM_SHARED ){
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u16 allShared = 0;  /* Union of locks held by connections other than "p" */
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Find out which shared locks are already held by sibling connections.
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** If any sibling already holds an exclusive lock, go ahead and return
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** SQLITE_BUSY.
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (pX->exclMask & mask)!=0 ){
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_BUSY;
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allShared |= pX->sharedMask;
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get shared locks at the system level, if necessary */
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (allShared & mask)==0 ){
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_OK;
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the local shared locks */
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->sharedMask |= mask;
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Make sure no sibling connections hold locks that will block this
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** lock.  If any do, return SQLITE_BUSY right away.
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_BUSY;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the exclusive locks at the system level.  Then if successful
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** also mark the local connection as being locked.
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc==SQLITE_OK ){
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc==SQLITE_OK ){
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert( (p->sharedMask & mask)==0 );
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        p->exclMask |= mask;
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           p->id, (int)GetCurrentProcessId(), p->sharedMask, p->exclMask,
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           rc ? "failed" : "ok"));
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Implement a memory barrier or memory fence on shared memory.
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** All loads and stores begun before the barrier must complete before
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** any load or store begun after the barrier.
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winShmBarrier(
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd          /* Database holding the shared memory */
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(fd);
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* MemoryBarrier(); // does not work -- do not know why not */
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmEnterMutex();
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmLeaveMutex();
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This function is called to obtain a pointer to region iRegion of the
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** shared-memory associated with the database file fd. Shared-memory regions
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** are numbered starting from zero. Each shared-memory region is szRegion
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes in size.
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If an error occurs, an error code is returned and *pp is set to NULL.
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** region has not been allocated (by any client, including one running in a
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** separate process), then *pp is set to NULL and SQLITE_OK returned. If
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** isWrite is non-zero and the requested shared-memory region has not yet
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** been allocated, it is allocated by this function.
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the shared-memory region has already been allocated or is allocated by
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** this call as described above, then it is mapped into this processes
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** address space (if it is not already), *pp is set to point to the mapped
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** memory and SQLITE_OK returned.
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winShmMap(
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *fd,               /* Handle open on database file */
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int iRegion,                    /* Region to retrieve */
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int szRegion,                   /* Size of regions */
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isWrite,                    /* True to extend file if necessary */
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void volatile **pp              /* OUT: Mapped memory */
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pDbFd = (winFile*)fd;
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShm *p = pDbFd->pShm;
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmNode *pShmNode;
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !p ){
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = winOpenSharedMemory(pDbFd);
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ) return rc;
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    p = pDbFd->pShm;
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pShmNode = p->pShmNode;
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_enter(pShmNode->mutex);
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRegion<=iRegion ){
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    struct ShmRegion *apNew;           /* New aRegion[] array */
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_int64 sz;                  /* Current size of wal-index file */
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->szRegion = szRegion;
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The requested region is not mapped into this processes address space.
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** Check to see if it has been allocated (i.e. if the wal-index file is
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ** large enough to contain the requested region).
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_SHMSIZE;
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shmpage_out;
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( sz<nByte ){
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* The requested memory region does not exist. If isWrite is set to
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      **
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** the requested memory region.
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !isWrite ) goto shmpage_out;
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( rc!=SQLITE_OK ){
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR_SHMSIZE;
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto shmpage_out;
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Map the requested memory region into this processes address space. */
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    apNew = (struct ShmRegion *)sqlite3_realloc(
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !apNew ){
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = SQLITE_IOERR_NOMEM;
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto shmpage_out;
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pShmNode->aRegion = apNew;
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while( pShmNode->nRegion<=iRegion ){
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HANDLE hMap;                /* file-mapping handle */
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void *pMap = 0;             /* Mapped memory region */
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hMap = CreateFileMapping(pShmNode->hFile.h,
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NULL, PAGE_READWRITE, 0, nByte, NULL
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      );
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (int)GetCurrentProcessId(), pShmNode->nRegion, nByte,
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               hMap ? "ok" : "failed"));
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( hMap ){
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iOffset = pShmNode->nRegion*szRegion;
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pMap = MapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            0, iOffset - iOffsetShift, szRegion + iOffsetShift
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        );
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 (int)GetCurrentProcessId(), pShmNode->nRegion, iOffset, szRegion,
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 pMap ? "ok" : "failed"));
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( !pMap ){
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pShmNode->lastErrno = GetLastError();
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rc = SQLITE_IOERR;
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if( hMap ) CloseHandle(hMap);
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto shmpage_out;
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pShmNode->nRegion++;
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)shmpage_out:
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pShmNode->nRegion>iRegion ){
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iOffset = iRegion*szRegion;
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *p = (char *)pShmNode->aRegion[iRegion].pMap;
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = (void *)&p[iOffsetShift];
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *pp = 0;
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_mutex_leave(pShmNode->mutex);
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmMap     0
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmLock    0
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmBarrier 0
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define winShmUnmap   0
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* #ifndef SQLITE_OMIT_WAL */
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Here ends the implementation of all sqlite3_file methods.
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)********************** End sqlite3_file Methods *******************************
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)******************************************************************************/
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This vector defines all the methods that can operate on an
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_file for win32.
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const sqlite3_io_methods winIoMethod = {
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2,                              /* iVersion */
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winClose,                       /* xClose */
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winRead,                        /* xRead */
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winWrite,                       /* xWrite */
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winTruncate,                    /* xTruncate */
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winSync,                        /* xSync */
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFileSize,                    /* xFileSize */
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winLock,                        /* xLock */
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winUnlock,                      /* xUnlock */
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winCheckReservedLock,           /* xCheckReservedLock */
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFileControl,                 /* xFileControl */
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winSectorSize,                  /* xSectorSize */
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winDeviceCharacteristics,       /* xDeviceCharacteristics */
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmMap,                      /* xShmMap */
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmLock,                     /* xShmLock */
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmBarrier,                  /* xShmBarrier */
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winShmUnmap                     /* xShmUnmap */
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/****************************************************************************
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**************************** sqlite3_vfs methods ****************************
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** This division contains the implementation of methods on the
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_vfs object.
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Convert a UTF-8 filename into whatever form the underlying
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** operating system wants filenames in.  Space to hold the result
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is obtained from malloc and must be freed by the calling
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function.
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *convertUtf8Filename(const char *zFilename){
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted = 0;
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zConverted = utf8ToUnicode(zFilename);
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zConverted = utf8ToMbcs(zFilename);
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* caller will handle out of memory */
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return zConverted;
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Create a temporary file name in zBuf.  zBuf must be big enough to
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** hold at pVfs->mxPathname characters.
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getTempname(int nBuf, char *zBuf){
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static char zChars[] =
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "abcdefghijklmnopqrstuvwxyz"
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "0123456789";
19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i, j;
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zTempPath[MAX_PATH+1];
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* It's odd to simulate an io-error here, but really this is just
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** using the io-error infrastructure to test that SQLite handles this
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** function failing.
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR );
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_temp_directory ){
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( isNT() ){
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zMulti;
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WCHAR zWidePath[MAX_PATH];
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetTempPathW(MAX_PATH-30, zWidePath);
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zMulti = unicodeToUtf8(zWidePath);
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zMulti ){
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(zMulti);
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zUtf8;
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char zMbcsPath[MAX_PATH];
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetTempPathA(MAX_PATH-30, zMbcsPath);
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zUtf8 ){
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(zUtf8);
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check that the output buffer is large enough for the temporary file
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** name. If it is not, return SQLITE_ERROR.
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 17) >= nBuf ){
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_ERROR;
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zTempPath[i] = 0;
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(nBuf-17, zBuf,
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  j = sqlite3Strlen30(zBuf);
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_randomness(15, &zBuf[j]);
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for(i=0; i<15; i++, j++){
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zBuf[j] = 0;
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("TEMP FILENAME: %s\n", zBuf));
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The return value of getLastErrorMsg
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is zero if the error message fits in the buffer, or non-zero
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** otherwise (if the message was truncated).
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getLastErrorMsg(int nBuf, char *zBuf){
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* FormatMessage returns 0 on failure.  Otherwise it
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** returns the number of TCHARs written to the output
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** buffer, excluding the terminating null char.
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD error = GetLastError();
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwLen = 0;
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut = 0;
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WCHAR *zTempWide = NULL;
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NULL,
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           error,
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           (LPWSTR) &zTempWide,
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0);
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( dwLen > 0 ){
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* allocate a buffer and convert to UTF8 */
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zOut = unicodeToUtf8(zTempWide);
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* free the system buffer allocated by FormatMessage */
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LocalFree(zTempWide);
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zTemp = NULL;
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NULL,
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           error,
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           (LPSTR) &zTemp,
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0);
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( dwLen > 0 ){
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* allocate a buffer and convert to UTF8 */
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* free the system buffer allocated by FormatMessage */
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LocalFree(zTemp);
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( 0 == dwLen ){
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* copy a maximum of nBuf chars to output buffer */
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* free the UTF8 buffer */
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zOut);
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Open a file.
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winOpen(
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,        /* Not used */
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zName,        /* Name of the file (UTF-8) */
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_file *id,         /* Write the SQLite file handle here */
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,                /* Open mode flags */
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pOutFlags            /* Status return flags */
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE h;
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwDesiredAccess;
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwShareMode;
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwCreationDisposition;
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwFlagsAndAttributes = 0;
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isTemp = 0;
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile *pFile = (winFile*)id;
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted;              /* Filename in OS encoding */
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If argument zPath is a NULL pointer, this function is required to open
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** a temporary file. Use this buffer to store the file name in.
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zTmpname[MAX_PATH+1];     /* Buffer used to create temp filename */
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = SQLITE_OK;            /* Function Return Code */
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(NDEBUG) || SQLITE_OS_WINCE
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int eType = flags&0xFFFFFF00;  /* Type of file to open */
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isCreate     = (flags & SQLITE_OPEN_CREATE);
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int isOpenJournal = (isCreate && (
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        eType==SQLITE_OPEN_MASTER_JOURNAL
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || eType==SQLITE_OPEN_MAIN_JOURNAL
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     || eType==SQLITE_OPEN_WAL
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ));
20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Check the following statements are true:
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **
20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (b) if CREATE is set, then READWRITE must also be set, and
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isCreate==0 || isReadWrite);
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isExclusive==0 || isCreate);
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(isDelete==0 || isCreate);
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The main DB, main journal, WAL file and master journal are never
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** automatically deleted. Nor are they ever temporary files.  */
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Assert that the upper layer has set one of the "file-type" flags. */
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  );
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert( id!=0 );
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->h = INVALID_HANDLE_VALUE;
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* If the second argument to this function is NULL, generate a
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** temporary file name to use
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !zUtf8Name ){
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(isDelete && !isOpenJournal);
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rc = getTempname(MAX_PATH+1, zTmpname);
21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( rc!=SQLITE_OK ){
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rc;
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zUtf8Name = zTmpname;
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Convert the filename to the system encoding. */
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zConverted = convertUtf8Filename(zUtf8Name);
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zConverted==0 ){
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isReadWrite ){
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwDesiredAccess = GENERIC_READ;
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** created. SQLite doesn't use it to indicate "exclusive access"
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** as it is usually understood.
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isExclusive ){
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Creates a new file, only if it does not already exist. */
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If the file exists, it fails. */
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwCreationDisposition = CREATE_NEW;
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else if( isCreate ){
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Open existing file, or create if it doesn't exist */
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwCreationDisposition = OPEN_ALWAYS;
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Opens a file, only if it exists. */
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwCreationDisposition = OPEN_EXISTING;
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isDelete ){
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    isTemp = 1;
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               | FILE_ATTRIBUTE_HIDDEN
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               | FILE_FLAG_DELETE_ON_CLOSE;
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Reports from the internet are that performance is always
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    h = CreateFileW((WCHAR*)zConverted,
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwDesiredAccess,
21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwShareMode,
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NULL,
21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwCreationDisposition,
21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwFlagsAndAttributes,
21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NULL
21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    h = CreateFileA((char*)zConverted,
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwDesiredAccess,
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwShareMode,
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NULL,
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwCreationDisposition,
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       dwFlagsAndAttributes,
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       NULL
21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    );
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("OPEN %d %s 0x%lx %s\n",
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           h, zName, dwDesiredAccess,
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( h==INVALID_HANDLE_VALUE ){
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->lastErrno = GetLastError();
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zConverted);
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( isReadWrite ){
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return winOpen(pVfs, zName, id,
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_CANTOPEN_BKPT;
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( pOutFlags ){
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( isReadWrite ){
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pOutFlags = SQLITE_OPEN_READWRITE;
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *pOutFlags = SQLITE_OPEN_READONLY;
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(pFile, 0, sizeof(*pFile));
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->pMethod = &winIoMethod;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->h = h;
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->lastErrno = NO_ERROR;
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->pVfs = pVfs;
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->pShm = 0;
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->zPath = zName;
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pFile->sectorSize = getSectorSize(pVfs, zUtf8Name);
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       && !winceCreateLock(zName, pFile)
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ){
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloseHandle(h);
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zConverted);
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_CANTOPEN_BKPT;
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isTemp ){
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pFile->zDeleteOnClose = zConverted;
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zConverted);
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenCounter(+1);
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Delete the named file.
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Note that windows does not allow a file to be deleted if some other
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** process has it open.  Sometimes a virus scanner or indexing program
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** will open a journal file shortly after it is created in order to do
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** whatever it does.  While this other process is holding the
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file open, we will be unable to delete it.  To work around this
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** problem, we delay 100 milliseconds and try to delete again.  Up
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** up and returning an error.
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MX_DELETION_ATTEMPTS 5
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winDelete(
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,          /* Not used on win32 */
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zFilename,      /* Name of file to delete */
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int syncDir                 /* Not used on win32 */
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int cnt = 0;
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD rc;
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD error = 0;
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted;
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(syncDir);
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError(return SQLITE_IOERR_DELETE);
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zConverted = convertUtf8Filename(zFilename);
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zConverted==0 ){
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do{
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeleteFileW(zConverted);
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }while(   (   ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBUTES)
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           && (++cnt < MX_DELETION_ATTEMPTS)
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           && (Sleep(100), 1) );
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do{
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeleteFileA(zConverted);
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }while(   (   ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           && (++cnt < MX_DELETION_ATTEMPTS)
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           && (Sleep(100), 1) );
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zConverted);
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OSTRACE(("DELETE \"%s\" %s\n", zFilename,
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ( (rc==INVALID_FILE_ATTRIBUTES) && (error==ERROR_FILE_NOT_FOUND)) ?
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         "ok" : "failed" ));
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (   (rc == INVALID_FILE_ATTRIBUTES)
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE;
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Check the existance and status of a file.
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winAccess(
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,         /* Not used on win32 */
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zFilename,     /* Name of file to check */
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags,                 /* Type of test to make on this file */
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int *pResOut               /* OUT: Result */
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD attr;
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc = 0;
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted;
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_IOERR_ACCESS; );
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zConverted = convertUtf8Filename(zFilename);
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zConverted==0 ){
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WIN32_FILE_ATTRIBUTE_DATA sAttrData;
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memset(&sAttrData, 0, sizeof(sAttrData));
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( GetFileAttributesExW((WCHAR*)zConverted,
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             GetFileExInfoStandard,
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &sAttrData) ){
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ** as if it does not exist.
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      */
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if(    flags==SQLITE_ACCESS_EXISTS
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          && sAttrData.nFileSizeHigh==0
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          && sAttrData.nFileSizeLow==0 ){
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attr = INVALID_FILE_ATTRIBUTES;
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attr = sAttrData.dwFileAttributes;
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }else{
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( GetLastError()!=ERROR_FILE_NOT_FOUND ){
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        free(zConverted);
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SQLITE_IOERR_ACCESS;
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        attr = INVALID_FILE_ATTRIBUTES;
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    attr = GetFileAttributesA((char*)zConverted);
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zConverted);
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch( flags ){
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_READ:
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_EXISTS:
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = attr!=INVALID_FILE_ATTRIBUTES;
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SQLITE_ACCESS_READWRITE:
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rc = (attr & FILE_ATTRIBUTE_READONLY)==0;
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(!"Invalid flags argument");
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *pResOut = rc;
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Turn a relative pathname into a full pathname.  Write the full
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** bytes in size.
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winFullPathname(
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs *pVfs,            /* Pointer to vfs object */
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char *zRelative,        /* Possibly relative input path */
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nFull,                    /* Size of output buffer in bytes */
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zFull                   /* Output buffer */
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__CYGWIN__)
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_ERROR );
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nFull);
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cygwin_conv_to_full_win32_path(zRelative, zFull);
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_ERROR );
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nFull);
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* WinCE has no concept of a relative pathname, or so I am told. */
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nByte;
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted;
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char *zOut;
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* It's odd to simulate an io-error here, but really this is just
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** using the io-error infrastructure to test that SQLite handles this
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** function failing. This function could fail if, for example, the
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** current working directory has been unlinked.
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOError( return SQLITE_ERROR );
24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(nFull);
24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zConverted = convertUtf8Filename(zRelative);
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WCHAR *zTemp;
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3;
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zTemp = malloc( nByte*sizeof(zTemp[0]) );
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zTemp==0 ){
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(zConverted);
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0);
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zConverted);
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zOut = unicodeToUtf8(zTemp);
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zTemp);
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char *zTemp;
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zTemp = malloc( nByte*sizeof(zTemp[0]) );
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zTemp==0 ){
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(zConverted);
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SQLITE_NOMEM;
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zConverted);
24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zTemp);
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zOut ){
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    free(zOut);
24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_OK;
24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SQLITE_NOMEM;
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Get the sector size of the device used to store
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** file.
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int getSectorSize(
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sqlite3_vfs *pVfs,
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char *zRelative     /* UTF-8 file name */
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)){
24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE;
24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* GetDiskFreeSpace is not supported under WINCE */
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(zRelative);
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char zFullpath[MAX_PATH+1];
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwRet = 0;
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD dwDummy;
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /*
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** We need to get the full path name of the file
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** to get the drive letter to look up the sector
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** size.
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOErrorBenign(1);
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = winFullPathname(pVfs, zRelative, MAX_PATH, zFullpath);
24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimulateIOErrorBenign(0);
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( rc == SQLITE_OK )
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void *zConverted = convertUtf8Filename(zFullpath);
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( zConverted ){
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if( isNT() ){
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* trim path to just drive reference */
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        WCHAR *p = zConverted;
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(;*p;p++){
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( *p == '\\' ){
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *p = '\0';
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted,
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy,
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &bytesPerSector,
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy,
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy);
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }else{
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* trim path to just drive reference */
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        char *p = (char *)zConverted;
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for(;*p;p++){
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if( *p == '\\' ){
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *p = '\0';
25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        dwRet = GetDiskFreeSpaceA((char*)zConverted,
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy,
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &bytesPerSector,
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy,
25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &dwDummy);
25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      free(zConverted);
25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if( !dwRet ){
25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE;
25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (int) bytesPerSector;
25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_LOAD_EXTENSION
25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces for opening a shared library, finding entry points
25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within the shared library, and closing the shared library.
25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Interfaces for opening a shared library, finding entry points
25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** within the shared library, and closing the shared library.
25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HANDLE h;
25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *zConverted = convertUtf8Filename(zFilename);
25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( zConverted==0 ){
25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( isNT() ){
25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    h = LoadLibraryW((WCHAR*)zConverted);
25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Since the ASCII version of these Windows API do not exist for WINCE,
25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it's important to not reference them for WINCE builds.
25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE==0
25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }else{
25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    h = LoadLibraryA((char*)zConverted);
25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(zConverted);
25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (void*)h;
25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getLastErrorMsg(nBuf, zBufOut);
25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* The GetProcAddressA() routine is only available on wince. */
25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol);
25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* All other windows platforms expect GetProcAddress() to take
25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ** an Ansi string regardless of the _UNICODE setting */
25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol);
25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FreeLibrary((HANDLE)pHandle);
25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define winDlOpen  0
25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define winDlError 0
25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define winDlSym   0
25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define winDlClose 0
25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Write up to nBuf bytes of randomness into zBuf.
25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int n = 0;
25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SQLITE_TEST)
25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  n = nBuf;
25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(zBuf, 0, nBuf);
26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sizeof(SYSTEMTIME)<=nBuf-n ){
26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SYSTEMTIME x;
26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetSystemTime(&x);
26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&zBuf[n], &x, sizeof(x));
26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n += sizeof(x);
26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sizeof(DWORD)<=nBuf-n ){
26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD pid = GetCurrentProcessId();
26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&zBuf[n], &pid, sizeof(pid));
26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n += sizeof(pid);
26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sizeof(DWORD)<=nBuf-n ){
26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD cnt = GetTickCount();
26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&zBuf[n], &cnt, sizeof(cnt));
26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n += sizeof(cnt);
26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sizeof(LARGE_INTEGER)<=nBuf-n ){
26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LARGE_INTEGER i;
26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    QueryPerformanceCounter(&i);
26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(&zBuf[n], &i, sizeof(i));
26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    n += sizeof(i);
26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return n;
26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Sleep for a little while.  Return the amount of time slept.
26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winSleep(sqlite3_vfs *pVfs, int microsec){
26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Sleep((microsec+999)/1000);
26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((microsec+999)/1000)*1000;
26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The following variable, if set to a non-zero value, is interpreted as
26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the number of seconds since 1970 and is used to set the result of
26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3OsCurrentTime() during testing.
26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_current_time = 0;  /* Fake system time in seconds since 1970. */
26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time).  Write into *piNow
26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** the current time and date as a Julian Day number times 86_400_000.  In
26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** other words, write into *piNow the number of milliseconds since the Julian
26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** epoch of noon in Greenwich on November 24, 4714 B.C according to the
26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** proleptic Gregorian calendar.
26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** On success, return 0.  Return 1 if the time and date cannot be found.
26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* FILETIME structure is a 64-bit value representing the number of
26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  */
26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FILETIME ft;
26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* 2^32 - to avoid use of LL and warnings in gcc */
26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const sqlite3_int64 max32BitValue =
26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SQLITE_OS_WINCE
26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SYSTEMTIME time;
26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetSystemTime(&time);
26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* if SystemTimeToFileTime() fails, it returns zero. */
26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SystemTimeToFileTime(&time,&ft)){
26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;
26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetSystemTimeAsFileTime( &ft );
26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *piNow = winFiletimeEpoch +
26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef SQLITE_TEST
26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( sqlite3_current_time ){
26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Find the current time (in Universal Coordinated Time).  Write the
26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** current time and date as a Julian Day number into *prNow and
26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** return 0.  Return 1 if the time and date cannot be found.
26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rc;
26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_int64 i;
27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rc = winCurrentTimeInt64(pVfs, &i);
27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if( !rc ){
27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *prNow = i/86400000.0;
27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rc;
27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** The idea is that this function works like a combination of
27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** GetLastError() and FormatMessage() on windows (or errno and
27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** strerror_r() on unix). After an error is returned by an OS
27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** function, SQLite calls this function with zBuf pointing to
27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** a buffer of nBuf bytes. The OS layer should populate the
27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** buffer with a nul-terminated UTF-8 encoded error message
27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** describing the last IO error to have occurred within the calling
27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** thread.
27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** If the error message is too large for the supplied buffer,
27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** it should be truncated. The return value of xGetLastError
27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** is zero if the error message fits in the buffer, or non-zero
27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** otherwise (if the message was truncated). If non-zero is returned,
27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** then it is not necessary to include the nul-terminator character
27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** in the output buffer.
27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Not supplying an error message will have no adverse effect
27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** on SQLite. It is fine to have an implementation that never
27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** returns an error message:
27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     assert(zBuf[0]=='\0');
27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**     return 0;
27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**   }
27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)**
27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** However if an error message is supplied, it will be incorporated
27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** by sqlite into the error message available to the user using
27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** sqlite3_errmsg(), possibly making IO errors easier to debug.
27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UNUSED_PARAMETER(pVfs);
27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return getLastErrorMsg(nBuf, zBuf);
27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)** Initialize and deinitialize the operating system interface.
27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/
27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_init(void){
27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static sqlite3_vfs winVfs = {
27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    3,                   /* iVersion */
27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sizeof(winFile),     /* szOsFile */
27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MAX_PATH,            /* mxPathname */
27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                   /* pNext */
27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "win32",             /* zName */
27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                   /* pAppData */
27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winOpen,             /* xOpen */
27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winDelete,           /* xDelete */
27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winAccess,           /* xAccess */
27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winFullPathname,     /* xFullPathname */
27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winDlOpen,           /* xDlOpen */
27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winDlError,          /* xDlError */
27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winDlSym,            /* xDlSym */
27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winDlClose,          /* xDlClose */
27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winRandomness,       /* xRandomness */
27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winSleep,            /* xSleep */
27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winCurrentTime,      /* xCurrentTime */
27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winGetLastError,     /* xGetLastError */
27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    winCurrentTimeInt64, /* xCurrentTimeInt64 */
27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                   /* xSetSystemCall */
27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                   /* xGetSystemCall */
27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0,                   /* xNextSystemCall */
27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SQLITE_OMIT_WAL
27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* get memory map allocation granularity */
27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetSystemInfo(&winSysInfo);
27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(winSysInfo.dwAllocationGranularity > 0);
27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sqlite3_vfs_register(&winVfs, 1);
27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int sqlite3_os_end(void){
27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SQLITE_OK;
27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE handle) {
27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winFile* winSQLite3File = (winFile*)file;
27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(file, 0, sizeof(*file));
27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winSQLite3File->pMethod = &winIoMethod;
27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  winSQLite3File->h = handle;
27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* SQLITE_OS_WIN */
2795