| OLD | NEW | 
 | (Empty) | 
|     1 /* |  | 
|     2 ** 2004 May 22 |  | 
|     3 ** |  | 
|     4 ** The author disclaims copyright to this source code.  In place of |  | 
|     5 ** a legal notice, here is a blessing: |  | 
|     6 ** |  | 
|     7 **    May you do good and not evil. |  | 
|     8 **    May you find forgiveness for yourself and forgive others. |  | 
|     9 **    May you share freely, never taking more than you give. |  | 
|    10 ** |  | 
|    11 ****************************************************************************** |  | 
|    12 ** |  | 
|    13 ** This file contains code that is specific to windows. |  | 
|    14 */ |  | 
|    15 #include "sqliteInt.h" |  | 
|    16 #if SQLITE_OS_WIN               /* This file is used for windows only */ |  | 
|    17  |  | 
|    18  |  | 
|    19 /* |  | 
|    20 ** A Note About Memory Allocation: |  | 
|    21 ** |  | 
|    22 ** This driver uses malloc()/free() directly rather than going through |  | 
|    23 ** the SQLite-wrappers sqlite3_malloc()/sqlite3_free().  Those wrappers |  | 
|    24 ** are designed for use on embedded systems where memory is scarce and |  | 
|    25 ** malloc failures happen frequently.  Win32 does not typically run on |  | 
|    26 ** embedded systems, and when it does the developers normally have bigger |  | 
|    27 ** problems to worry about than running out of memory.  So there is not |  | 
|    28 ** a compelling need to use the wrappers. |  | 
|    29 ** |  | 
|    30 ** But there is a good reason to not use the wrappers.  If we use the |  | 
|    31 ** wrappers then we will get simulated malloc() failures within this |  | 
|    32 ** driver.  And that causes all kinds of problems for our tests.  We |  | 
|    33 ** could enhance SQLite to deal with simulated malloc failures within |  | 
|    34 ** the OS driver, but the code to deal with those failure would not |  | 
|    35 ** be exercised on Linux (which does not need to malloc() in the driver) |  | 
|    36 ** and so we would have difficulty writing coverage tests for that |  | 
|    37 ** code.  Better to leave the code out, we think. |  | 
|    38 ** |  | 
|    39 ** The point of this discussion is as follows:  When creating a new |  | 
|    40 ** OS layer for an embedded system, if you use this file as an example, |  | 
|    41 ** avoid the use of malloc()/free().  Those routines work ok on windows |  | 
|    42 ** desktops but not so well in embedded systems. |  | 
|    43 */ |  | 
|    44  |  | 
|    45 #include <winbase.h> |  | 
|    46  |  | 
|    47 #ifdef __CYGWIN__ |  | 
|    48 # include <sys/cygwin.h> |  | 
|    49 #endif |  | 
|    50  |  | 
|    51 /* |  | 
|    52 ** Macros used to determine whether or not to use threads. |  | 
|    53 */ |  | 
|    54 #if defined(THREADSAFE) && THREADSAFE |  | 
|    55 # define SQLITE_W32_THREADS 1 |  | 
|    56 #endif |  | 
|    57  |  | 
|    58 /* |  | 
|    59 ** Include code that is common to all os_*.c files |  | 
|    60 */ |  | 
|    61 #include "os_common.h" |  | 
|    62  |  | 
|    63 /* |  | 
|    64 ** Some microsoft compilers lack this definition. |  | 
|    65 */ |  | 
|    66 #ifndef INVALID_FILE_ATTRIBUTES |  | 
|    67 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)  |  | 
|    68 #endif |  | 
|    69  |  | 
|    70 /* |  | 
|    71 ** Determine if we are dealing with WindowsCE - which has a much |  | 
|    72 ** reduced API. |  | 
|    73 */ |  | 
|    74 #if SQLITE_OS_WINCE |  | 
|    75 # define AreFileApisANSI() 1 |  | 
|    76 # define GetDiskFreeSpaceW() 0 |  | 
|    77 #endif |  | 
|    78  |  | 
|    79 /* |  | 
|    80 ** WinCE lacks native support for file locking so we have to fake it |  | 
|    81 ** with some code of our own. |  | 
|    82 */ |  | 
|    83 #if SQLITE_OS_WINCE |  | 
|    84 typedef struct winceLock { |  | 
|    85   int nReaders;       /* Number of reader locks obtained */ |  | 
|    86   BOOL bPending;      /* Indicates a pending lock has been obtained */ |  | 
|    87   BOOL bReserved;     /* Indicates a reserved lock has been obtained */ |  | 
|    88   BOOL bExclusive;    /* Indicates an exclusive lock has been obtained */ |  | 
|    89 } winceLock; |  | 
|    90 #endif |  | 
|    91  |  | 
|    92 /* |  | 
|    93 ** The winFile structure is a subclass of sqlite3_file* specific to the win32 |  | 
|    94 ** portability layer. |  | 
|    95 */ |  | 
|    96 typedef struct winFile winFile; |  | 
|    97 struct winFile { |  | 
|    98   const sqlite3_io_methods *pMethod;/* Must be first */ |  | 
|    99   HANDLE h;               /* Handle for accessing the file */ |  | 
|   100   unsigned char locktype; /* Type of lock currently held on this file */ |  | 
|   101   short sharedLockByte;   /* Randomly chosen byte used as a shared lock */ |  | 
|   102   DWORD lastErrno;        /* The Windows errno from the last I/O error */ |  | 
|   103   DWORD sectorSize;       /* Sector size of the device file is on */ |  | 
|   104 #if SQLITE_OS_WINCE |  | 
|   105   WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */ |  | 
|   106   HANDLE hMutex;          /* Mutex used to control access to shared lock */   |  | 
|   107   HANDLE hShared;         /* Shared memory segment used for locking */ |  | 
|   108   winceLock local;        /* Locks obtained by this instance of winFile */ |  | 
|   109   winceLock *shared;      /* Global shared lock memory for the file  */ |  | 
|   110 #endif |  | 
|   111 }; |  | 
|   112  |  | 
|   113 /* |  | 
|   114 ** Forward prototypes. |  | 
|   115 */ |  | 
|   116 static int getSectorSize( |  | 
|   117     sqlite3_vfs *pVfs, |  | 
|   118     const char *zRelative     /* UTF-8 file name */ |  | 
|   119 ); |  | 
|   120  |  | 
|   121 /* |  | 
|   122 ** The following variable is (normally) set once and never changes |  | 
|   123 ** thereafter.  It records whether the operating system is Win95 |  | 
|   124 ** or WinNT. |  | 
|   125 ** |  | 
|   126 ** 0:   Operating system unknown. |  | 
|   127 ** 1:   Operating system is Win95. |  | 
|   128 ** 2:   Operating system is WinNT. |  | 
|   129 ** |  | 
|   130 ** In order to facilitate testing on a WinNT system, the test fixture |  | 
|   131 ** can manually set this value to 1 to emulate Win98 behavior. |  | 
|   132 */ |  | 
|   133 #ifdef SQLITE_TEST |  | 
|   134 int sqlite3_os_type = 0; |  | 
|   135 #else |  | 
|   136 static int sqlite3_os_type = 0; |  | 
|   137 #endif |  | 
|   138  |  | 
|   139 /* |  | 
|   140 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, |  | 
|   141 ** or WinCE.  Return false (zero) for Win95, Win98, or WinME. |  | 
|   142 ** |  | 
|   143 ** Here is an interesting observation:  Win95, Win98, and WinME lack |  | 
|   144 ** the LockFileEx() API.  But we can still statically link against that |  | 
|   145 ** API as long as we don't call it when running Win95/98/ME.  A call to |  | 
|   146 ** this routine is used to determine if the host is Win95/98/ME or |  | 
|   147 ** WinNT/2K/XP so that we will know whether or not we can safely call |  | 
|   148 ** the LockFileEx() API. |  | 
|   149 */ |  | 
|   150 #if SQLITE_OS_WINCE |  | 
|   151 # define isNT()  (1) |  | 
|   152 #else |  | 
|   153   static int isNT(void){ |  | 
|   154     if( sqlite3_os_type==0 ){ |  | 
|   155       OSVERSIONINFO sInfo; |  | 
|   156       sInfo.dwOSVersionInfoSize = sizeof(sInfo); |  | 
|   157       GetVersionEx(&sInfo); |  | 
|   158       sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; |  | 
|   159     } |  | 
|   160     return sqlite3_os_type==2; |  | 
|   161   } |  | 
|   162 #endif /* SQLITE_OS_WINCE */ |  | 
|   163  |  | 
|   164 /* |  | 
|   165 ** Convert a UTF-8 string to microsoft unicode (UTF-16?).  |  | 
|   166 ** |  | 
|   167 ** Space to hold the returned string is obtained from malloc. |  | 
|   168 */ |  | 
|   169 static WCHAR *utf8ToUnicode(const char *zFilename){ |  | 
|   170   int nChar; |  | 
|   171   WCHAR *zWideFilename; |  | 
|   172  |  | 
|   173   nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); |  | 
|   174   zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) ); |  | 
|   175   if( zWideFilename==0 ){ |  | 
|   176     return 0; |  | 
|   177   } |  | 
|   178   nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar); |  | 
|   179   if( nChar==0 ){ |  | 
|   180     free(zWideFilename); |  | 
|   181     zWideFilename = 0; |  | 
|   182   } |  | 
|   183   return zWideFilename; |  | 
|   184 } |  | 
|   185  |  | 
|   186 /* |  | 
|   187 ** Convert microsoft unicode to UTF-8.  Space to hold the returned string is |  | 
|   188 ** obtained from malloc(). |  | 
|   189 */ |  | 
|   190 static char *unicodeToUtf8(const WCHAR *zWideFilename){ |  | 
|   191   int nByte; |  | 
|   192   char *zFilename; |  | 
|   193  |  | 
|   194   nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); |  | 
|   195   zFilename = malloc( nByte ); |  | 
|   196   if( zFilename==0 ){ |  | 
|   197     return 0; |  | 
|   198   } |  | 
|   199   nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, |  | 
|   200                               0, 0); |  | 
|   201   if( nByte == 0 ){ |  | 
|   202     free(zFilename); |  | 
|   203     zFilename = 0; |  | 
|   204   } |  | 
|   205   return zFilename; |  | 
|   206 } |  | 
|   207  |  | 
|   208 /* |  | 
|   209 ** Convert an ansi string to microsoft unicode, based on the |  | 
|   210 ** current codepage settings for file apis. |  | 
|   211 **  |  | 
|   212 ** Space to hold the returned string is obtained |  | 
|   213 ** from malloc. |  | 
|   214 */ |  | 
|   215 static WCHAR *mbcsToUnicode(const char *zFilename){ |  | 
|   216   int nByte; |  | 
|   217   WCHAR *zMbcsFilename; |  | 
|   218   int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; |  | 
|   219  |  | 
|   220   nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*sizeof(WCHAR); |  | 
|   221   zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) ); |  | 
|   222   if( zMbcsFilename==0 ){ |  | 
|   223     return 0; |  | 
|   224   } |  | 
|   225   nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte); |  | 
|   226   if( nByte==0 ){ |  | 
|   227     free(zMbcsFilename); |  | 
|   228     zMbcsFilename = 0; |  | 
|   229   } |  | 
|   230   return zMbcsFilename; |  | 
|   231 } |  | 
|   232  |  | 
|   233 /* |  | 
|   234 ** Convert microsoft unicode to multibyte character string, based on the |  | 
|   235 ** user's Ansi codepage. |  | 
|   236 ** |  | 
|   237 ** Space to hold the returned string is obtained from |  | 
|   238 ** malloc(). |  | 
|   239 */ |  | 
|   240 static char *unicodeToMbcs(const WCHAR *zWideFilename){ |  | 
|   241   int nByte; |  | 
|   242   char *zFilename; |  | 
|   243   int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP; |  | 
|   244  |  | 
|   245   nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); |  | 
|   246   zFilename = malloc( nByte ); |  | 
|   247   if( zFilename==0 ){ |  | 
|   248     return 0; |  | 
|   249   } |  | 
|   250   nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte, |  | 
|   251                               0, 0); |  | 
|   252   if( nByte == 0 ){ |  | 
|   253     free(zFilename); |  | 
|   254     zFilename = 0; |  | 
|   255   } |  | 
|   256   return zFilename; |  | 
|   257 } |  | 
|   258  |  | 
|   259 /* |  | 
|   260 ** Convert multibyte character string to UTF-8.  Space to hold the |  | 
|   261 ** returned string is obtained from malloc(). |  | 
|   262 */ |  | 
|   263 char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ |  | 
|   264   char *zFilenameUtf8; |  | 
|   265   WCHAR *zTmpWide; |  | 
|   266  |  | 
|   267   zTmpWide = mbcsToUnicode(zFilename); |  | 
|   268   if( zTmpWide==0 ){ |  | 
|   269     return 0; |  | 
|   270   } |  | 
|   271   zFilenameUtf8 = unicodeToUtf8(zTmpWide); |  | 
|   272   free(zTmpWide); |  | 
|   273   return zFilenameUtf8; |  | 
|   274 } |  | 
|   275  |  | 
|   276 /* |  | 
|   277 ** Convert UTF-8 to multibyte character string.  Space to hold the  |  | 
|   278 ** returned string is obtained from malloc(). |  | 
|   279 */ |  | 
|   280 static char *utf8ToMbcs(const char *zFilename){ |  | 
|   281   char *zFilenameMbcs; |  | 
|   282   WCHAR *zTmpWide; |  | 
|   283  |  | 
|   284   zTmpWide = utf8ToUnicode(zFilename); |  | 
|   285   if( zTmpWide==0 ){ |  | 
|   286     return 0; |  | 
|   287   } |  | 
|   288   zFilenameMbcs = unicodeToMbcs(zTmpWide); |  | 
|   289   free(zTmpWide); |  | 
|   290   return zFilenameMbcs; |  | 
|   291 } |  | 
|   292  |  | 
|   293 #if SQLITE_OS_WINCE |  | 
|   294 /************************************************************************* |  | 
|   295 ** This section contains code for WinCE only. |  | 
|   296 */ |  | 
|   297 /* |  | 
|   298 ** WindowsCE does not have a localtime() function.  So create a |  | 
|   299 ** substitute. |  | 
|   300 */ |  | 
|   301 #include <time.h> |  | 
|   302 struct tm *__cdecl localtime(const time_t *t) |  | 
|   303 { |  | 
|   304   static struct tm y; |  | 
|   305   FILETIME uTm, lTm; |  | 
|   306   SYSTEMTIME pTm; |  | 
|   307   sqlite3_int64 t64; |  | 
|   308   t64 = *t; |  | 
|   309   t64 = (t64 + 11644473600)*10000000; |  | 
|   310   uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); |  | 
|   311   uTm.dwHighDateTime= (DWORD)(t64 >> 32); |  | 
|   312   FileTimeToLocalFileTime(&uTm,&lTm); |  | 
|   313   FileTimeToSystemTime(&lTm,&pTm); |  | 
|   314   y.tm_year = pTm.wYear - 1900; |  | 
|   315   y.tm_mon = pTm.wMonth - 1; |  | 
|   316   y.tm_wday = pTm.wDayOfWeek; |  | 
|   317   y.tm_mday = pTm.wDay; |  | 
|   318   y.tm_hour = pTm.wHour; |  | 
|   319   y.tm_min = pTm.wMinute; |  | 
|   320   y.tm_sec = pTm.wSecond; |  | 
|   321   return &y; |  | 
|   322 } |  | 
|   323  |  | 
|   324 /* This will never be called, but defined to make the code compile */ |  | 
|   325 #define GetTempPathA(a,b) |  | 
|   326  |  | 
|   327 #define LockFile(a,b,c,d,e)       winceLockFile(&a, b, c, d, e) |  | 
|   328 #define UnlockFile(a,b,c,d,e)     winceUnlockFile(&a, b, c, d, e) |  | 
|   329 #define LockFileEx(a,b,c,d,e,f)   winceLockFileEx(&a, b, c, d, e, f) |  | 
|   330  |  | 
|   331 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] |  | 
|   332  |  | 
|   333 /* |  | 
|   334 ** Acquire a lock on the handle h |  | 
|   335 */ |  | 
|   336 static void winceMutexAcquire(HANDLE h){ |  | 
|   337    DWORD dwErr; |  | 
|   338    do { |  | 
|   339      dwErr = WaitForSingleObject(h, INFINITE); |  | 
|   340    } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); |  | 
|   341 } |  | 
|   342 /* |  | 
|   343 ** Release a lock acquired by winceMutexAcquire() |  | 
|   344 */ |  | 
|   345 #define winceMutexRelease(h) ReleaseMutex(h) |  | 
|   346  |  | 
|   347 /* |  | 
|   348 ** Create the mutex and shared memory used for locking in the file |  | 
|   349 ** descriptor pFile |  | 
|   350 */ |  | 
|   351 static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ |  | 
|   352   WCHAR *zTok; |  | 
|   353   WCHAR *zName = utf8ToUnicode(zFilename); |  | 
|   354   BOOL bInit = TRUE; |  | 
|   355  |  | 
|   356   /* Initialize the local lockdata */ |  | 
|   357   ZeroMemory(&pFile->local, sizeof(pFile->local)); |  | 
|   358  |  | 
|   359   /* Replace the backslashes from the filename and lowercase it |  | 
|   360   ** to derive a mutex name. */ |  | 
|   361   zTok = CharLowerW(zName); |  | 
|   362   for (;*zTok;zTok++){ |  | 
|   363     if (*zTok == '\\') *zTok = '_'; |  | 
|   364   } |  | 
|   365  |  | 
|   366   /* Create/open the named mutex */ |  | 
|   367   pFile->hMutex = CreateMutexW(NULL, FALSE, zName); |  | 
|   368   if (!pFile->hMutex){ |  | 
|   369     pFile->lastErrno = GetLastError(); |  | 
|   370     free(zName); |  | 
|   371     return FALSE; |  | 
|   372   } |  | 
|   373  |  | 
|   374   /* Acquire the mutex before continuing */ |  | 
|   375   winceMutexAcquire(pFile->hMutex); |  | 
|   376    |  | 
|   377   /* Since the names of named mutexes, semaphores, file mappings etc are  |  | 
|   378   ** case-sensitive, take advantage of that by uppercasing the mutex name |  | 
|   379   ** and using that as the shared filemapping name. |  | 
|   380   */ |  | 
|   381   CharUpperW(zName); |  | 
|   382   pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, |  | 
|   383                                        PAGE_READWRITE, 0, sizeof(winceLock), |  | 
|   384                                        zName);   |  | 
|   385  |  | 
|   386   /* Set a flag that indicates we're the first to create the memory so it  |  | 
|   387   ** must be zero-initialized */ |  | 
|   388   if (GetLastError() == ERROR_ALREADY_EXISTS){ |  | 
|   389     bInit = FALSE; |  | 
|   390   } |  | 
|   391  |  | 
|   392   free(zName); |  | 
|   393  |  | 
|   394   /* If we succeeded in making the shared memory handle, map it. */ |  | 
|   395   if (pFile->hShared){ |  | 
|   396     pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,  |  | 
|   397              FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); |  | 
|   398     /* If mapping failed, close the shared memory handle and erase it */ |  | 
|   399     if (!pFile->shared){ |  | 
|   400       pFile->lastErrno = GetLastError(); |  | 
|   401       CloseHandle(pFile->hShared); |  | 
|   402       pFile->hShared = NULL; |  | 
|   403     } |  | 
|   404   } |  | 
|   405  |  | 
|   406   /* If shared memory could not be created, then close the mutex and fail */ |  | 
|   407   if (pFile->hShared == NULL){ |  | 
|   408     winceMutexRelease(pFile->hMutex); |  | 
|   409     CloseHandle(pFile->hMutex); |  | 
|   410     pFile->hMutex = NULL; |  | 
|   411     return FALSE; |  | 
|   412   } |  | 
|   413    |  | 
|   414   /* Initialize the shared memory if we're supposed to */ |  | 
|   415   if (bInit) { |  | 
|   416     ZeroMemory(pFile->shared, sizeof(winceLock)); |  | 
|   417   } |  | 
|   418  |  | 
|   419   winceMutexRelease(pFile->hMutex); |  | 
|   420   return TRUE; |  | 
|   421 } |  | 
|   422  |  | 
|   423 /* |  | 
|   424 ** Destroy the part of winFile that deals with wince locks |  | 
|   425 */ |  | 
|   426 static void winceDestroyLock(winFile *pFile){ |  | 
|   427   if (pFile->hMutex){ |  | 
|   428     /* Acquire the mutex */ |  | 
|   429     winceMutexAcquire(pFile->hMutex); |  | 
|   430  |  | 
|   431     /* The following blocks should probably assert in debug mode, but they |  | 
|   432        are to cleanup in case any locks remained open */ |  | 
|   433     if (pFile->local.nReaders){ |  | 
|   434       pFile->shared->nReaders --; |  | 
|   435     } |  | 
|   436     if (pFile->local.bReserved){ |  | 
|   437       pFile->shared->bReserved = FALSE; |  | 
|   438     } |  | 
|   439     if (pFile->local.bPending){ |  | 
|   440       pFile->shared->bPending = FALSE; |  | 
|   441     } |  | 
|   442     if (pFile->local.bExclusive){ |  | 
|   443       pFile->shared->bExclusive = FALSE; |  | 
|   444     } |  | 
|   445  |  | 
|   446     /* De-reference and close our copy of the shared memory handle */ |  | 
|   447     UnmapViewOfFile(pFile->shared); |  | 
|   448     CloseHandle(pFile->hShared); |  | 
|   449  |  | 
|   450     /* Done with the mutex */ |  | 
|   451     winceMutexRelease(pFile->hMutex);     |  | 
|   452     CloseHandle(pFile->hMutex); |  | 
|   453     pFile->hMutex = NULL; |  | 
|   454   } |  | 
|   455 } |  | 
|   456  |  | 
|   457 /*  |  | 
|   458 ** An implementation of the LockFile() API of windows for wince |  | 
|   459 */ |  | 
|   460 static BOOL winceLockFile( |  | 
|   461   HANDLE *phFile, |  | 
|   462   DWORD dwFileOffsetLow, |  | 
|   463   DWORD dwFileOffsetHigh, |  | 
|   464   DWORD nNumberOfBytesToLockLow, |  | 
|   465   DWORD nNumberOfBytesToLockHigh |  | 
|   466 ){ |  | 
|   467   winFile *pFile = HANDLE_TO_WINFILE(phFile); |  | 
|   468   BOOL bReturn = FALSE; |  | 
|   469  |  | 
|   470   UNUSED_PARAMETER(dwFileOffsetHigh); |  | 
|   471   UNUSED_PARAMETER(nNumberOfBytesToLockHigh); |  | 
|   472  |  | 
|   473   if (!pFile->hMutex) return TRUE; |  | 
|   474   winceMutexAcquire(pFile->hMutex); |  | 
|   475  |  | 
|   476   /* Wanting an exclusive lock? */ |  | 
|   477   if (dwFileOffsetLow == (DWORD)SHARED_FIRST |  | 
|   478        && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ |  | 
|   479     if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ |  | 
|   480        pFile->shared->bExclusive = TRUE; |  | 
|   481        pFile->local.bExclusive = TRUE; |  | 
|   482        bReturn = TRUE; |  | 
|   483     } |  | 
|   484   } |  | 
|   485  |  | 
|   486   /* Want a read-only lock? */ |  | 
|   487   else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && |  | 
|   488            nNumberOfBytesToLockLow == 1){ |  | 
|   489     if (pFile->shared->bExclusive == 0){ |  | 
|   490       pFile->local.nReaders ++; |  | 
|   491       if (pFile->local.nReaders == 1){ |  | 
|   492         pFile->shared->nReaders ++; |  | 
|   493       } |  | 
|   494       bReturn = TRUE; |  | 
|   495     } |  | 
|   496   } |  | 
|   497  |  | 
|   498   /* Want a pending lock? */ |  | 
|   499   else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 
      1){ |  | 
|   500     /* If no pending lock has been acquired, then acquire it */ |  | 
|   501     if (pFile->shared->bPending == 0) { |  | 
|   502       pFile->shared->bPending = TRUE; |  | 
|   503       pFile->local.bPending = TRUE; |  | 
|   504       bReturn = TRUE; |  | 
|   505     } |  | 
|   506   } |  | 
|   507  |  | 
|   508   /* Want a reserved lock? */ |  | 
|   509   else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow ==
       1){ |  | 
|   510     if (pFile->shared->bReserved == 0) { |  | 
|   511       pFile->shared->bReserved = TRUE; |  | 
|   512       pFile->local.bReserved = TRUE; |  | 
|   513       bReturn = TRUE; |  | 
|   514     } |  | 
|   515   } |  | 
|   516  |  | 
|   517   winceMutexRelease(pFile->hMutex); |  | 
|   518   return bReturn; |  | 
|   519 } |  | 
|   520  |  | 
|   521 /* |  | 
|   522 ** An implementation of the UnlockFile API of windows for wince |  | 
|   523 */ |  | 
|   524 static BOOL winceUnlockFile( |  | 
|   525   HANDLE *phFile, |  | 
|   526   DWORD dwFileOffsetLow, |  | 
|   527   DWORD dwFileOffsetHigh, |  | 
|   528   DWORD nNumberOfBytesToUnlockLow, |  | 
|   529   DWORD nNumberOfBytesToUnlockHigh |  | 
|   530 ){ |  | 
|   531   winFile *pFile = HANDLE_TO_WINFILE(phFile); |  | 
|   532   BOOL bReturn = FALSE; |  | 
|   533  |  | 
|   534   UNUSED_PARAMETER(dwFileOffsetHigh); |  | 
|   535   UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); |  | 
|   536  |  | 
|   537   if (!pFile->hMutex) return TRUE; |  | 
|   538   winceMutexAcquire(pFile->hMutex); |  | 
|   539  |  | 
|   540   /* Releasing a reader lock or an exclusive lock */ |  | 
|   541   if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ |  | 
|   542     /* Did we have an exclusive lock? */ |  | 
|   543     if (pFile->local.bExclusive){ |  | 
|   544       assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); |  | 
|   545       pFile->local.bExclusive = FALSE; |  | 
|   546       pFile->shared->bExclusive = FALSE; |  | 
|   547       bReturn = TRUE; |  | 
|   548     } |  | 
|   549  |  | 
|   550     /* Did we just have a reader lock? */ |  | 
|   551     else if (pFile->local.nReaders){ |  | 
|   552       assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesTo
      UnlockLow == 1); |  | 
|   553       pFile->local.nReaders --; |  | 
|   554       if (pFile->local.nReaders == 0) |  | 
|   555       { |  | 
|   556         pFile->shared->nReaders --; |  | 
|   557       } |  | 
|   558       bReturn = TRUE; |  | 
|   559     } |  | 
|   560   } |  | 
|   561  |  | 
|   562   /* Releasing a pending lock */ |  | 
|   563   else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow =
      = 1){ |  | 
|   564     if (pFile->local.bPending){ |  | 
|   565       pFile->local.bPending = FALSE; |  | 
|   566       pFile->shared->bPending = FALSE; |  | 
|   567       bReturn = TRUE; |  | 
|   568     } |  | 
|   569   } |  | 
|   570   /* Releasing a reserved lock */ |  | 
|   571   else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow 
      == 1){ |  | 
|   572     if (pFile->local.bReserved) { |  | 
|   573       pFile->local.bReserved = FALSE; |  | 
|   574       pFile->shared->bReserved = FALSE; |  | 
|   575       bReturn = TRUE; |  | 
|   576     } |  | 
|   577   } |  | 
|   578  |  | 
|   579   winceMutexRelease(pFile->hMutex); |  | 
|   580   return bReturn; |  | 
|   581 } |  | 
|   582  |  | 
|   583 /* |  | 
|   584 ** An implementation of the LockFileEx() API of windows for wince |  | 
|   585 */ |  | 
|   586 static BOOL winceLockFileEx( |  | 
|   587   HANDLE *phFile, |  | 
|   588   DWORD dwFlags, |  | 
|   589   DWORD dwReserved, |  | 
|   590   DWORD nNumberOfBytesToLockLow, |  | 
|   591   DWORD nNumberOfBytesToLockHigh, |  | 
|   592   LPOVERLAPPED lpOverlapped |  | 
|   593 ){ |  | 
|   594   UNUSED_PARAMETER(dwReserved); |  | 
|   595   UNUSED_PARAMETER(nNumberOfBytesToLockHigh); |  | 
|   596  |  | 
|   597   /* If the caller wants a shared read lock, forward this call |  | 
|   598   ** to winceLockFile */ |  | 
|   599   if (lpOverlapped->Offset == (DWORD)SHARED_FIRST && |  | 
|   600       dwFlags == 1 && |  | 
|   601       nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ |  | 
|   602     return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0); |  | 
|   603   } |  | 
|   604   return FALSE; |  | 
|   605 } |  | 
|   606 /* |  | 
|   607 ** End of the special code for wince |  | 
|   608 *****************************************************************************/ |  | 
|   609 #endif /* SQLITE_OS_WINCE */ |  | 
|   610  |  | 
|   611 /***************************************************************************** |  | 
|   612 ** The next group of routines implement the I/O methods specified |  | 
|   613 ** by the sqlite3_io_methods object. |  | 
|   614 ******************************************************************************/ |  | 
|   615  |  | 
|   616 /* |  | 
|   617 ** Close a file. |  | 
|   618 ** |  | 
|   619 ** It is reported that an attempt to close a handle might sometimes |  | 
|   620 ** fail.  This is a very unreasonable result, but windows is notorious |  | 
|   621 ** for being unreasonable so I do not doubt that it might happen.  If |  | 
|   622 ** the close fails, we pause for 100 milliseconds and try again.  As |  | 
|   623 ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before |  | 
|   624 ** giving up and returning an error. |  | 
|   625 */ |  | 
|   626 #define MX_CLOSE_ATTEMPT 3 |  | 
|   627 static int winClose(sqlite3_file *id){ |  | 
|   628   int rc, cnt = 0; |  | 
|   629   winFile *pFile = (winFile*)id; |  | 
|   630  |  | 
|   631   assert( id!=0 ); |  | 
|   632   OSTRACE2("CLOSE %d\n", pFile->h); |  | 
|   633   do{ |  | 
|   634     rc = CloseHandle(pFile->h); |  | 
|   635   }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (Sleep(100), 1) ); |  | 
|   636 #if SQLITE_OS_WINCE |  | 
|   637 #define WINCE_DELETION_ATTEMPTS 3 |  | 
|   638   winceDestroyLock(pFile); |  | 
|   639   if( pFile->zDeleteOnClose ){ |  | 
|   640     int cnt = 0; |  | 
|   641     while( |  | 
|   642            DeleteFileW(pFile->zDeleteOnClose)==0 |  | 
|   643         && GetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff  |  | 
|   644         && cnt++ < WINCE_DELETION_ATTEMPTS |  | 
|   645     ){ |  | 
|   646        Sleep(100);  /* Wait a little before trying again */ |  | 
|   647     } |  | 
|   648     free(pFile->zDeleteOnClose); |  | 
|   649   } |  | 
|   650 #endif |  | 
|   651   OpenCounter(-1); |  | 
|   652   return rc ? SQLITE_OK : SQLITE_IOERR; |  | 
|   653 } |  | 
|   654  |  | 
|   655 /* |  | 
|   656 ** Some microsoft compilers lack this definition. |  | 
|   657 */ |  | 
|   658 #ifndef INVALID_SET_FILE_POINTER |  | 
|   659 # define INVALID_SET_FILE_POINTER ((DWORD)-1) |  | 
|   660 #endif |  | 
|   661  |  | 
|   662 /* |  | 
|   663 ** Read data from a file into a buffer.  Return SQLITE_OK if all |  | 
|   664 ** bytes were read successfully and SQLITE_IOERR if anything goes |  | 
|   665 ** wrong. |  | 
|   666 */ |  | 
|   667 static int winRead( |  | 
|   668   sqlite3_file *id,          /* File to read from */ |  | 
|   669   void *pBuf,                /* Write content into this buffer */ |  | 
|   670   int amt,                   /* Number of bytes to read */ |  | 
|   671   sqlite3_int64 offset       /* Begin reading at this offset */ |  | 
|   672 ){ |  | 
|   673   LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); |  | 
|   674   LONG lowerBits = (LONG)(offset & 0xffffffff); |  | 
|   675   DWORD rc; |  | 
|   676   winFile *pFile = (winFile*)id; |  | 
|   677   DWORD error; |  | 
|   678   DWORD got; |  | 
|   679  |  | 
|   680   assert( id!=0 ); |  | 
|   681   SimulateIOError(return SQLITE_IOERR_READ); |  | 
|   682   OSTRACE3("READ %d lock=%d\n", pFile->h, pFile->locktype); |  | 
|   683   rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |  | 
|   684   if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ |  | 
|   685     pFile->lastErrno = error; |  | 
|   686     return SQLITE_FULL; |  | 
|   687   } |  | 
|   688   if( !ReadFile(pFile->h, pBuf, amt, &got, 0) ){ |  | 
|   689     pFile->lastErrno = GetLastError(); |  | 
|   690     return SQLITE_IOERR_READ; |  | 
|   691   } |  | 
|   692   if( got==(DWORD)amt ){ |  | 
|   693     return SQLITE_OK; |  | 
|   694   }else{ |  | 
|   695     /* Unread parts of the buffer must be zero-filled */ |  | 
|   696     memset(&((char*)pBuf)[got], 0, amt-got); |  | 
|   697     return SQLITE_IOERR_SHORT_READ; |  | 
|   698   } |  | 
|   699 } |  | 
|   700  |  | 
|   701 /* |  | 
|   702 ** Write data from a buffer into a file.  Return SQLITE_OK on success |  | 
|   703 ** or some other error code on failure. |  | 
|   704 */ |  | 
|   705 static int winWrite( |  | 
|   706   sqlite3_file *id,         /* File to write into */ |  | 
|   707   const void *pBuf,         /* The bytes to be written */ |  | 
|   708   int amt,                  /* Number of bytes to write */ |  | 
|   709   sqlite3_int64 offset      /* Offset into the file to begin writing at */ |  | 
|   710 ){ |  | 
|   711   LONG upperBits = (LONG)((offset>>32) & 0x7fffffff); |  | 
|   712   LONG lowerBits = (LONG)(offset & 0xffffffff); |  | 
|   713   DWORD rc; |  | 
|   714   winFile *pFile = (winFile*)id; |  | 
|   715   DWORD error; |  | 
|   716   DWORD wrote = 0; |  | 
|   717  |  | 
|   718   assert( id!=0 ); |  | 
|   719   SimulateIOError(return SQLITE_IOERR_WRITE); |  | 
|   720   SimulateDiskfullError(return SQLITE_FULL); |  | 
|   721   OSTRACE3("WRITE %d lock=%d\n", pFile->h, pFile->locktype); |  | 
|   722   rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |  | 
|   723   if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ |  | 
|   724     pFile->lastErrno = error; |  | 
|   725     return SQLITE_FULL; |  | 
|   726   } |  | 
|   727   assert( amt>0 ); |  | 
|   728   while( |  | 
|   729      amt>0 |  | 
|   730      && (rc = WriteFile(pFile->h, pBuf, amt, &wrote, 0))!=0 |  | 
|   731      && wrote>0 |  | 
|   732   ){ |  | 
|   733     amt -= wrote; |  | 
|   734     pBuf = &((char*)pBuf)[wrote]; |  | 
|   735   } |  | 
|   736   if( !rc || amt>(int)wrote ){ |  | 
|   737     pFile->lastErrno = GetLastError(); |  | 
|   738     return SQLITE_FULL; |  | 
|   739   } |  | 
|   740   return SQLITE_OK; |  | 
|   741 } |  | 
|   742  |  | 
|   743 /* |  | 
|   744 ** Truncate an open file to a specified size |  | 
|   745 */ |  | 
|   746 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ |  | 
|   747   LONG upperBits = (LONG)((nByte>>32) & 0x7fffffff); |  | 
|   748   LONG lowerBits = (LONG)(nByte & 0xffffffff); |  | 
|   749   DWORD rc; |  | 
|   750   winFile *pFile = (winFile*)id; |  | 
|   751   DWORD error; |  | 
|   752  |  | 
|   753   assert( id!=0 ); |  | 
|   754   OSTRACE3("TRUNCATE %d %lld\n", pFile->h, nByte); |  | 
|   755   SimulateIOError(return SQLITE_IOERR_TRUNCATE); |  | 
|   756   rc = SetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); |  | 
|   757   if( rc==INVALID_SET_FILE_POINTER && (error=GetLastError())!=NO_ERROR ){ |  | 
|   758     pFile->lastErrno = error; |  | 
|   759     return SQLITE_IOERR_TRUNCATE; |  | 
|   760   } |  | 
|   761   /* SetEndOfFile will fail if nByte is negative */ |  | 
|   762   if( !SetEndOfFile(pFile->h) ){ |  | 
|   763     pFile->lastErrno = GetLastError(); |  | 
|   764     return SQLITE_IOERR_TRUNCATE; |  | 
|   765   } |  | 
|   766   return SQLITE_OK; |  | 
|   767 } |  | 
|   768  |  | 
|   769 #ifdef SQLITE_TEST |  | 
|   770 /* |  | 
|   771 ** Count the number of fullsyncs and normal syncs.  This is used to test |  | 
|   772 ** that syncs and fullsyncs are occuring at the right times. |  | 
|   773 */ |  | 
|   774 int sqlite3_sync_count = 0; |  | 
|   775 int sqlite3_fullsync_count = 0; |  | 
|   776 #endif |  | 
|   777  |  | 
|   778 /* |  | 
|   779 ** Make sure all writes to a particular file are committed to disk. |  | 
|   780 */ |  | 
|   781 static int winSync(sqlite3_file *id, int flags){ |  | 
|   782 #ifndef SQLITE_NO_SYNC |  | 
|   783   winFile *pFile = (winFile*)id; |  | 
|   784  |  | 
|   785   assert( id!=0 ); |  | 
|   786   OSTRACE3("SYNC %d lock=%d\n", pFile->h, pFile->locktype); |  | 
|   787 #else |  | 
|   788   UNUSED_PARAMETER(id); |  | 
|   789 #endif |  | 
|   790 #ifndef SQLITE_TEST |  | 
|   791   UNUSED_PARAMETER(flags); |  | 
|   792 #else |  | 
|   793   if( flags & SQLITE_SYNC_FULL ){ |  | 
|   794     sqlite3_fullsync_count++; |  | 
|   795   } |  | 
|   796   sqlite3_sync_count++; |  | 
|   797 #endif |  | 
|   798   /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a |  | 
|   799   ** no-op |  | 
|   800   */ |  | 
|   801 #ifdef SQLITE_NO_SYNC |  | 
|   802     return SQLITE_OK; |  | 
|   803 #else |  | 
|   804   if( FlushFileBuffers(pFile->h) ){ |  | 
|   805     return SQLITE_OK; |  | 
|   806   }else{ |  | 
|   807     pFile->lastErrno = GetLastError(); |  | 
|   808     return SQLITE_IOERR; |  | 
|   809   } |  | 
|   810 #endif |  | 
|   811 } |  | 
|   812  |  | 
|   813 /* |  | 
|   814 ** Determine the current size of a file in bytes |  | 
|   815 */ |  | 
|   816 static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ |  | 
|   817   DWORD upperBits; |  | 
|   818   DWORD lowerBits; |  | 
|   819   winFile *pFile = (winFile*)id; |  | 
|   820   DWORD error; |  | 
|   821  |  | 
|   822   assert( id!=0 ); |  | 
|   823   SimulateIOError(return SQLITE_IOERR_FSTAT); |  | 
|   824   lowerBits = GetFileSize(pFile->h, &upperBits); |  | 
|   825   if(   (lowerBits == INVALID_FILE_SIZE) |  | 
|   826      && ((error = GetLastError()) != NO_ERROR) ) |  | 
|   827   { |  | 
|   828     pFile->lastErrno = error; |  | 
|   829     return SQLITE_IOERR_FSTAT; |  | 
|   830   } |  | 
|   831   *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; |  | 
|   832   return SQLITE_OK; |  | 
|   833 } |  | 
|   834  |  | 
|   835 /* |  | 
|   836 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. |  | 
|   837 */ |  | 
|   838 #ifndef LOCKFILE_FAIL_IMMEDIATELY |  | 
|   839 # define LOCKFILE_FAIL_IMMEDIATELY 1 |  | 
|   840 #endif |  | 
|   841  |  | 
|   842 /* |  | 
|   843 ** Acquire a reader lock. |  | 
|   844 ** Different API routines are called depending on whether or not this |  | 
|   845 ** is Win95 or WinNT. |  | 
|   846 */ |  | 
|   847 static int getReadLock(winFile *pFile){ |  | 
|   848   int res; |  | 
|   849   if( isNT() ){ |  | 
|   850     OVERLAPPED ovlp; |  | 
|   851     ovlp.Offset = SHARED_FIRST; |  | 
|   852     ovlp.OffsetHigh = 0; |  | 
|   853     ovlp.hEvent = 0; |  | 
|   854     res = LockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY, |  | 
|   855                      0, SHARED_SIZE, 0, &ovlp); |  | 
|   856 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|   857 */ |  | 
|   858 #if SQLITE_OS_WINCE==0 |  | 
|   859   }else{ |  | 
|   860     int lk; |  | 
|   861     sqlite3_randomness(sizeof(lk), &lk); |  | 
|   862     pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); |  | 
|   863     res = LockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); |  | 
|   864 #endif |  | 
|   865   } |  | 
|   866   if( res == 0 ){ |  | 
|   867     pFile->lastErrno = GetLastError(); |  | 
|   868   } |  | 
|   869   return res; |  | 
|   870 } |  | 
|   871  |  | 
|   872 /* |  | 
|   873 ** Undo a readlock |  | 
|   874 */ |  | 
|   875 static int unlockReadLock(winFile *pFile){ |  | 
|   876   int res; |  | 
|   877   if( isNT() ){ |  | 
|   878     res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |  | 
|   879 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|   880 */ |  | 
|   881 #if SQLITE_OS_WINCE==0 |  | 
|   882   }else{ |  | 
|   883     res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0); |  | 
|   884 #endif |  | 
|   885   } |  | 
|   886   if( res == 0 ){ |  | 
|   887     pFile->lastErrno = GetLastError(); |  | 
|   888   } |  | 
|   889   return res; |  | 
|   890 } |  | 
|   891  |  | 
|   892 /* |  | 
|   893 ** Lock the file with the lock specified by parameter locktype - one |  | 
|   894 ** of the following: |  | 
|   895 ** |  | 
|   896 **     (1) SHARED_LOCK |  | 
|   897 **     (2) RESERVED_LOCK |  | 
|   898 **     (3) PENDING_LOCK |  | 
|   899 **     (4) EXCLUSIVE_LOCK |  | 
|   900 ** |  | 
|   901 ** Sometimes when requesting one lock state, additional lock states |  | 
|   902 ** are inserted in between.  The locking might fail on one of the later |  | 
|   903 ** transitions leaving the lock state different from what it started but |  | 
|   904 ** still short of its goal.  The following chart shows the allowed |  | 
|   905 ** transitions and the inserted intermediate states: |  | 
|   906 ** |  | 
|   907 **    UNLOCKED -> SHARED |  | 
|   908 **    SHARED -> RESERVED |  | 
|   909 **    SHARED -> (PENDING) -> EXCLUSIVE |  | 
|   910 **    RESERVED -> (PENDING) -> EXCLUSIVE |  | 
|   911 **    PENDING -> EXCLUSIVE |  | 
|   912 ** |  | 
|   913 ** This routine will only increase a lock.  The winUnlock() routine |  | 
|   914 ** erases all locks at once and returns us immediately to locking level 0. |  | 
|   915 ** It is not possible to lower the locking level one step at a time.  You |  | 
|   916 ** must go straight to locking level 0. |  | 
|   917 */ |  | 
|   918 static int winLock(sqlite3_file *id, int locktype){ |  | 
|   919   int rc = SQLITE_OK;    /* Return code from subroutines */ |  | 
|   920   int res = 1;           /* Result of a windows lock call */ |  | 
|   921   int newLocktype;       /* Set pFile->locktype to this value before exiting */ |  | 
|   922   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ |  | 
|   923   winFile *pFile = (winFile*)id; |  | 
|   924   DWORD error = NO_ERROR; |  | 
|   925  |  | 
|   926   assert( id!=0 ); |  | 
|   927   OSTRACE5("LOCK %d %d was %d(%d)\n", |  | 
|   928           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte); |  | 
|   929  |  | 
|   930   /* If there is already a lock of this type or more restrictive on the |  | 
|   931   ** OsFile, do nothing. Don't use the end_lock: exit path, as |  | 
|   932   ** sqlite3OsEnterMutex() hasn't been called yet. |  | 
|   933   */ |  | 
|   934   if( pFile->locktype>=locktype ){ |  | 
|   935     return SQLITE_OK; |  | 
|   936   } |  | 
|   937  |  | 
|   938   /* Make sure the locking sequence is correct |  | 
|   939   */ |  | 
|   940   assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); |  | 
|   941   assert( locktype!=PENDING_LOCK ); |  | 
|   942   assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); |  | 
|   943  |  | 
|   944   /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or |  | 
|   945   ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of |  | 
|   946   ** the PENDING_LOCK byte is temporary. |  | 
|   947   */ |  | 
|   948   newLocktype = pFile->locktype; |  | 
|   949   if(   (pFile->locktype==NO_LOCK) |  | 
|   950      || (   (locktype==EXCLUSIVE_LOCK) |  | 
|   951          && (pFile->locktype==RESERVED_LOCK)) |  | 
|   952   ){ |  | 
|   953     int cnt = 3; |  | 
|   954     while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){ |  | 
|   955       /* Try 3 times to get the pending lock.  The pending lock might be |  | 
|   956       ** held by another reader process who will release it momentarily. |  | 
|   957       */ |  | 
|   958       OSTRACE2("could not get a PENDING lock. cnt=%d\n", cnt); |  | 
|   959       Sleep(1); |  | 
|   960     } |  | 
|   961     gotPendingLock = res; |  | 
|   962     if( !res ){ |  | 
|   963       error = GetLastError(); |  | 
|   964     } |  | 
|   965   } |  | 
|   966  |  | 
|   967   /* Acquire a shared lock |  | 
|   968   */ |  | 
|   969   if( locktype==SHARED_LOCK && res ){ |  | 
|   970     assert( pFile->locktype==NO_LOCK ); |  | 
|   971     res = getReadLock(pFile); |  | 
|   972     if( res ){ |  | 
|   973       newLocktype = SHARED_LOCK; |  | 
|   974     }else{ |  | 
|   975       error = GetLastError(); |  | 
|   976     } |  | 
|   977   } |  | 
|   978  |  | 
|   979   /* Acquire a RESERVED lock |  | 
|   980   */ |  | 
|   981   if( locktype==RESERVED_LOCK && res ){ |  | 
|   982     assert( pFile->locktype==SHARED_LOCK ); |  | 
|   983     res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |  | 
|   984     if( res ){ |  | 
|   985       newLocktype = RESERVED_LOCK; |  | 
|   986     }else{ |  | 
|   987       error = GetLastError(); |  | 
|   988     } |  | 
|   989   } |  | 
|   990  |  | 
|   991   /* Acquire a PENDING lock |  | 
|   992   */ |  | 
|   993   if( locktype==EXCLUSIVE_LOCK && res ){ |  | 
|   994     newLocktype = PENDING_LOCK; |  | 
|   995     gotPendingLock = 0; |  | 
|   996   } |  | 
|   997  |  | 
|   998   /* Acquire an EXCLUSIVE lock |  | 
|   999   */ |  | 
|  1000   if( locktype==EXCLUSIVE_LOCK && res ){ |  | 
|  1001     assert( pFile->locktype>=SHARED_LOCK ); |  | 
|  1002     res = unlockReadLock(pFile); |  | 
|  1003     OSTRACE2("unreadlock = %d\n", res); |  | 
|  1004     res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |  | 
|  1005     if( res ){ |  | 
|  1006       newLocktype = EXCLUSIVE_LOCK; |  | 
|  1007     }else{ |  | 
|  1008       error = GetLastError(); |  | 
|  1009       OSTRACE2("error-code = %d\n", error); |  | 
|  1010       getReadLock(pFile); |  | 
|  1011     } |  | 
|  1012   } |  | 
|  1013  |  | 
|  1014   /* If we are holding a PENDING lock that ought to be released, then |  | 
|  1015   ** release it now. |  | 
|  1016   */ |  | 
|  1017   if( gotPendingLock && locktype==SHARED_LOCK ){ |  | 
|  1018     UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); |  | 
|  1019   } |  | 
|  1020  |  | 
|  1021   /* Update the state of the lock has held in the file descriptor then |  | 
|  1022   ** return the appropriate result code. |  | 
|  1023   */ |  | 
|  1024   if( res ){ |  | 
|  1025     rc = SQLITE_OK; |  | 
|  1026   }else{ |  | 
|  1027     OSTRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h, |  | 
|  1028            locktype, newLocktype); |  | 
|  1029     pFile->lastErrno = error; |  | 
|  1030     rc = SQLITE_BUSY; |  | 
|  1031   } |  | 
|  1032   pFile->locktype = (u8)newLocktype; |  | 
|  1033   return rc; |  | 
|  1034 } |  | 
|  1035  |  | 
|  1036 /* |  | 
|  1037 ** This routine checks if there is a RESERVED lock held on the specified |  | 
|  1038 ** file by this or any other process. If such a lock is held, return |  | 
|  1039 ** non-zero, otherwise zero. |  | 
|  1040 */ |  | 
|  1041 static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ |  | 
|  1042   int rc; |  | 
|  1043   winFile *pFile = (winFile*)id; |  | 
|  1044  |  | 
|  1045   assert( id!=0 ); |  | 
|  1046   if( pFile->locktype>=RESERVED_LOCK ){ |  | 
|  1047     rc = 1; |  | 
|  1048     OSTRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc); |  | 
|  1049   }else{ |  | 
|  1050     rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |  | 
|  1051     if( rc ){ |  | 
|  1052       UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |  | 
|  1053     } |  | 
|  1054     rc = !rc; |  | 
|  1055     OSTRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc); |  | 
|  1056   } |  | 
|  1057   *pResOut = rc; |  | 
|  1058   return SQLITE_OK; |  | 
|  1059 } |  | 
|  1060  |  | 
|  1061 /* |  | 
|  1062 ** Lower the locking level on file descriptor id to locktype.  locktype |  | 
|  1063 ** must be either NO_LOCK or SHARED_LOCK. |  | 
|  1064 ** |  | 
|  1065 ** If the locking level of the file descriptor is already at or below |  | 
|  1066 ** the requested locking level, this routine is a no-op. |  | 
|  1067 ** |  | 
|  1068 ** It is not possible for this routine to fail if the second argument |  | 
|  1069 ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine |  | 
|  1070 ** might return SQLITE_IOERR; |  | 
|  1071 */ |  | 
|  1072 static int winUnlock(sqlite3_file *id, int locktype){ |  | 
|  1073   int type; |  | 
|  1074   winFile *pFile = (winFile*)id; |  | 
|  1075   int rc = SQLITE_OK; |  | 
|  1076   assert( pFile!=0 ); |  | 
|  1077   assert( locktype<=SHARED_LOCK ); |  | 
|  1078   OSTRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype, |  | 
|  1079           pFile->locktype, pFile->sharedLockByte); |  | 
|  1080   type = pFile->locktype; |  | 
|  1081   if( type>=EXCLUSIVE_LOCK ){ |  | 
|  1082     UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); |  | 
|  1083     if( locktype==SHARED_LOCK && !getReadLock(pFile) ){ |  | 
|  1084       /* This should never happen.  We should always be able to |  | 
|  1085       ** reacquire the read lock */ |  | 
|  1086       rc = SQLITE_IOERR_UNLOCK; |  | 
|  1087     } |  | 
|  1088   } |  | 
|  1089   if( type>=RESERVED_LOCK ){ |  | 
|  1090     UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0); |  | 
|  1091   } |  | 
|  1092   if( locktype==NO_LOCK && type>=SHARED_LOCK ){ |  | 
|  1093     unlockReadLock(pFile); |  | 
|  1094   } |  | 
|  1095   if( type>=PENDING_LOCK ){ |  | 
|  1096     UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0); |  | 
|  1097   } |  | 
|  1098   pFile->locktype = (u8)locktype; |  | 
|  1099   return rc; |  | 
|  1100 } |  | 
|  1101  |  | 
|  1102 /* |  | 
|  1103 ** Control and query of the open file handle. |  | 
|  1104 */ |  | 
|  1105 static int winFileControl(sqlite3_file *id, int op, void *pArg){ |  | 
|  1106   switch( op ){ |  | 
|  1107     case SQLITE_FCNTL_LOCKSTATE: { |  | 
|  1108       *(int*)pArg = ((winFile*)id)->locktype; |  | 
|  1109       return SQLITE_OK; |  | 
|  1110     } |  | 
|  1111     case SQLITE_LAST_ERRNO: { |  | 
|  1112       *(int*)pArg = (int)((winFile*)id)->lastErrno; |  | 
|  1113       return SQLITE_OK; |  | 
|  1114     } |  | 
|  1115   } |  | 
|  1116   return SQLITE_ERROR; |  | 
|  1117 } |  | 
|  1118  |  | 
|  1119 /* |  | 
|  1120 ** Return the sector size in bytes of the underlying block device for |  | 
|  1121 ** the specified file. This is almost always 512 bytes, but may be |  | 
|  1122 ** larger for some devices. |  | 
|  1123 ** |  | 
|  1124 ** SQLite code assumes this function cannot fail. It also assumes that |  | 
|  1125 ** if two files are created in the same file-system directory (i.e. |  | 
|  1126 ** a database and its journal file) that the sector size will be the |  | 
|  1127 ** same for both. |  | 
|  1128 */ |  | 
|  1129 static int winSectorSize(sqlite3_file *id){ |  | 
|  1130   assert( id!=0 ); |  | 
|  1131   return (int)(((winFile*)id)->sectorSize); |  | 
|  1132 } |  | 
|  1133  |  | 
|  1134 /* |  | 
|  1135 ** Return a vector of device characteristics. |  | 
|  1136 */ |  | 
|  1137 static int winDeviceCharacteristics(sqlite3_file *id){ |  | 
|  1138   UNUSED_PARAMETER(id); |  | 
|  1139   return 0; |  | 
|  1140 } |  | 
|  1141  |  | 
|  1142 /* |  | 
|  1143 ** This vector defines all the methods that can operate on an |  | 
|  1144 ** sqlite3_file for win32. |  | 
|  1145 */ |  | 
|  1146 static const sqlite3_io_methods winIoMethod = { |  | 
|  1147   1,                        /* iVersion */ |  | 
|  1148   winClose, |  | 
|  1149   winRead, |  | 
|  1150   winWrite, |  | 
|  1151   winTruncate, |  | 
|  1152   winSync, |  | 
|  1153   winFileSize, |  | 
|  1154   winLock, |  | 
|  1155   winUnlock, |  | 
|  1156   winCheckReservedLock, |  | 
|  1157   winFileControl, |  | 
|  1158   winSectorSize, |  | 
|  1159   winDeviceCharacteristics |  | 
|  1160 }; |  | 
|  1161  |  | 
|  1162 /*************************************************************************** |  | 
|  1163 ** Here ends the I/O methods that form the sqlite3_io_methods object. |  | 
|  1164 ** |  | 
|  1165 ** The next block of code implements the VFS methods. |  | 
|  1166 ****************************************************************************/ |  | 
|  1167  |  | 
|  1168 /* |  | 
|  1169 ** Convert a UTF-8 filename into whatever form the underlying |  | 
|  1170 ** operating system wants filenames in.  Space to hold the result |  | 
|  1171 ** is obtained from malloc and must be freed by the calling |  | 
|  1172 ** function. |  | 
|  1173 */ |  | 
|  1174 static void *convertUtf8Filename(const char *zFilename){ |  | 
|  1175   void *zConverted = 0; |  | 
|  1176   if( isNT() ){ |  | 
|  1177     zConverted = utf8ToUnicode(zFilename); |  | 
|  1178 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1179 */ |  | 
|  1180 #if SQLITE_OS_WINCE==0 |  | 
|  1181   }else{ |  | 
|  1182     zConverted = utf8ToMbcs(zFilename); |  | 
|  1183 #endif |  | 
|  1184   } |  | 
|  1185   /* caller will handle out of memory */ |  | 
|  1186   return zConverted; |  | 
|  1187 } |  | 
|  1188  |  | 
|  1189 /* |  | 
|  1190 ** Create a temporary file name in zBuf.  zBuf must be big enough to |  | 
|  1191 ** hold at pVfs->mxPathname characters. |  | 
|  1192 */ |  | 
|  1193 static int getTempname(int nBuf, char *zBuf){ |  | 
|  1194   static char zChars[] = |  | 
|  1195     "abcdefghijklmnopqrstuvwxyz" |  | 
|  1196     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" |  | 
|  1197     "0123456789"; |  | 
|  1198   size_t i, j; |  | 
|  1199   char zTempPath[MAX_PATH+1]; |  | 
|  1200   if( sqlite3_temp_directory ){ |  | 
|  1201     sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory); |  | 
|  1202   }else if( isNT() ){ |  | 
|  1203     char *zMulti; |  | 
|  1204     WCHAR zWidePath[MAX_PATH]; |  | 
|  1205     GetTempPathW(MAX_PATH-30, zWidePath); |  | 
|  1206     zMulti = unicodeToUtf8(zWidePath); |  | 
|  1207     if( zMulti ){ |  | 
|  1208       sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti); |  | 
|  1209       free(zMulti); |  | 
|  1210     }else{ |  | 
|  1211       return SQLITE_NOMEM; |  | 
|  1212     } |  | 
|  1213 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1214 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1215 ** it's important to not reference them for WINCE builds. |  | 
|  1216 */ |  | 
|  1217 #if SQLITE_OS_WINCE==0 |  | 
|  1218   }else{ |  | 
|  1219     char *zUtf8; |  | 
|  1220     char zMbcsPath[MAX_PATH]; |  | 
|  1221     GetTempPathA(MAX_PATH-30, zMbcsPath); |  | 
|  1222     zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); |  | 
|  1223     if( zUtf8 ){ |  | 
|  1224       sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8); |  | 
|  1225       free(zUtf8); |  | 
|  1226     }else{ |  | 
|  1227       return SQLITE_NOMEM; |  | 
|  1228     } |  | 
|  1229 #endif |  | 
|  1230   } |  | 
|  1231   for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} |  | 
|  1232   zTempPath[i] = 0; |  | 
|  1233   sqlite3_snprintf(nBuf-30, zBuf, |  | 
|  1234                    "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath); |  | 
|  1235   j = sqlite3Strlen30(zBuf); |  | 
|  1236   sqlite3_randomness(20, &zBuf[j]); |  | 
|  1237   for(i=0; i<20; i++, j++){ |  | 
|  1238     zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; |  | 
|  1239   } |  | 
|  1240   zBuf[j] = 0; |  | 
|  1241   OSTRACE2("TEMP FILENAME: %s\n", zBuf); |  | 
|  1242   return SQLITE_OK;  |  | 
|  1243 } |  | 
|  1244  |  | 
|  1245 /* |  | 
|  1246 ** The return value of getLastErrorMsg |  | 
|  1247 ** is zero if the error message fits in the buffer, or non-zero |  | 
|  1248 ** otherwise (if the message was truncated). |  | 
|  1249 */ |  | 
|  1250 static int getLastErrorMsg(int nBuf, char *zBuf){ |  | 
|  1251   DWORD error = GetLastError(); |  | 
|  1252  |  | 
|  1253 #if SQLITE_OS_WINCE |  | 
|  1254   sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); |  | 
|  1255 #else |  | 
|  1256   /* FormatMessage returns 0 on failure.  Otherwise it |  | 
|  1257   ** returns the number of TCHARs written to the output |  | 
|  1258   ** buffer, excluding the terminating null char. |  | 
|  1259   */ |  | 
|  1260   if (!FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, |  | 
|  1261                       NULL, |  | 
|  1262                       error, |  | 
|  1263                       0, |  | 
|  1264                       zBuf, |  | 
|  1265                       nBuf-1, |  | 
|  1266                       0)) |  | 
|  1267   { |  | 
|  1268     sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error); |  | 
|  1269   } |  | 
|  1270 #endif |  | 
|  1271  |  | 
|  1272   return 0; |  | 
|  1273 } |  | 
|  1274  |  | 
|  1275 /* |  | 
|  1276 ** Open a file. |  | 
|  1277 */ |  | 
|  1278 static int winOpen( |  | 
|  1279   sqlite3_vfs *pVfs,        /* Not used */ |  | 
|  1280   const char *zName,        /* Name of the file (UTF-8) */ |  | 
|  1281   sqlite3_file *id,         /* Write the SQLite file handle here */ |  | 
|  1282   int flags,                /* Open mode flags */ |  | 
|  1283   int *pOutFlags            /* Status return flags */ |  | 
|  1284 ){ |  | 
|  1285   HANDLE h; |  | 
|  1286   DWORD dwDesiredAccess; |  | 
|  1287   DWORD dwShareMode; |  | 
|  1288   DWORD dwCreationDisposition; |  | 
|  1289   DWORD dwFlagsAndAttributes = 0; |  | 
|  1290 #if SQLITE_OS_WINCE |  | 
|  1291   int isTemp = 0; |  | 
|  1292 #endif |  | 
|  1293   winFile *pFile = (winFile*)id; |  | 
|  1294   void *zConverted;                 /* Filename in OS encoding */ |  | 
|  1295   const char *zUtf8Name = zName;    /* Filename in UTF-8 encoding */ |  | 
|  1296   char zTmpname[MAX_PATH+1];        /* Buffer used to create temp filename */ |  | 
|  1297  |  | 
|  1298   assert( id!=0 ); |  | 
|  1299   UNUSED_PARAMETER(pVfs); |  | 
|  1300  |  | 
|  1301   /* If the second argument to this function is NULL, generate a  |  | 
|  1302   ** temporary file name to use  |  | 
|  1303   */ |  | 
|  1304   if( !zUtf8Name ){ |  | 
|  1305     int rc = getTempname(MAX_PATH+1, zTmpname); |  | 
|  1306     if( rc!=SQLITE_OK ){ |  | 
|  1307       return rc; |  | 
|  1308     } |  | 
|  1309     zUtf8Name = zTmpname; |  | 
|  1310   } |  | 
|  1311  |  | 
|  1312   /* Convert the filename to the system encoding. */ |  | 
|  1313   zConverted = convertUtf8Filename(zUtf8Name); |  | 
|  1314   if( zConverted==0 ){ |  | 
|  1315     return SQLITE_NOMEM; |  | 
|  1316   } |  | 
|  1317  |  | 
|  1318   if( flags & SQLITE_OPEN_READWRITE ){ |  | 
|  1319     dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; |  | 
|  1320   }else{ |  | 
|  1321     dwDesiredAccess = GENERIC_READ; |  | 
|  1322   } |  | 
|  1323   /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is  |  | 
|  1324   ** created. SQLite doesn't use it to indicate "exclusive access"  |  | 
|  1325   ** as it is usually understood. |  | 
|  1326   */ |  | 
|  1327   assert(!(flags & SQLITE_OPEN_EXCLUSIVE) || (flags & SQLITE_OPEN_CREATE)); |  | 
|  1328   if( flags & SQLITE_OPEN_EXCLUSIVE ){ |  | 
|  1329     /* Creates a new file, only if it does not already exist. */ |  | 
|  1330     /* If the file exists, it fails. */ |  | 
|  1331     dwCreationDisposition = CREATE_NEW; |  | 
|  1332   }else if( flags & SQLITE_OPEN_CREATE ){ |  | 
|  1333     /* Open existing file, or create if it doesn't exist */ |  | 
|  1334     dwCreationDisposition = OPEN_ALWAYS; |  | 
|  1335   }else{ |  | 
|  1336     /* Opens a file, only if it exists. */ |  | 
|  1337     dwCreationDisposition = OPEN_EXISTING; |  | 
|  1338   } |  | 
|  1339   dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; |  | 
|  1340   if( flags & SQLITE_OPEN_DELETEONCLOSE ){ |  | 
|  1341 #if SQLITE_OS_WINCE |  | 
|  1342     dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; |  | 
|  1343     isTemp = 1; |  | 
|  1344 #else |  | 
|  1345     dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY |  | 
|  1346                                | FILE_ATTRIBUTE_HIDDEN |  | 
|  1347                                | FILE_FLAG_DELETE_ON_CLOSE; |  | 
|  1348 #endif |  | 
|  1349   }else{ |  | 
|  1350     dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; |  | 
|  1351   } |  | 
|  1352   /* Reports from the internet are that performance is always |  | 
|  1353   ** better if FILE_FLAG_RANDOM_ACCESS is used.  Ticket #2699. */ |  | 
|  1354 #if SQLITE_OS_WINCE |  | 
|  1355   dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; |  | 
|  1356 #endif |  | 
|  1357   if( isNT() ){ |  | 
|  1358     h = CreateFileW((WCHAR*)zConverted, |  | 
|  1359        dwDesiredAccess, |  | 
|  1360        dwShareMode, |  | 
|  1361        NULL, |  | 
|  1362        dwCreationDisposition, |  | 
|  1363        dwFlagsAndAttributes, |  | 
|  1364        NULL |  | 
|  1365     ); |  | 
|  1366 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1367 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1368 ** it's important to not reference them for WINCE builds. |  | 
|  1369 */ |  | 
|  1370 #if SQLITE_OS_WINCE==0 |  | 
|  1371   }else{ |  | 
|  1372     h = CreateFileA((char*)zConverted, |  | 
|  1373        dwDesiredAccess, |  | 
|  1374        dwShareMode, |  | 
|  1375        NULL, |  | 
|  1376        dwCreationDisposition, |  | 
|  1377        dwFlagsAndAttributes, |  | 
|  1378        NULL |  | 
|  1379     ); |  | 
|  1380 #endif |  | 
|  1381   } |  | 
|  1382   if( h==INVALID_HANDLE_VALUE ){ |  | 
|  1383     free(zConverted); |  | 
|  1384     if( flags & SQLITE_OPEN_READWRITE ){ |  | 
|  1385       return winOpen(pVfs, zName, id,  |  | 
|  1386              ((flags|SQLITE_OPEN_READONLY)&~SQLITE_OPEN_READWRITE), pOutFlags); |  | 
|  1387     }else{ |  | 
|  1388       return SQLITE_CANTOPEN; |  | 
|  1389     } |  | 
|  1390   } |  | 
|  1391   if( pOutFlags ){ |  | 
|  1392     if( flags & SQLITE_OPEN_READWRITE ){ |  | 
|  1393       *pOutFlags = SQLITE_OPEN_READWRITE; |  | 
|  1394     }else{ |  | 
|  1395       *pOutFlags = SQLITE_OPEN_READONLY; |  | 
|  1396     } |  | 
|  1397   } |  | 
|  1398   memset(pFile, 0, sizeof(*pFile)); |  | 
|  1399   pFile->pMethod = &winIoMethod; |  | 
|  1400   pFile->h = h; |  | 
|  1401   pFile->lastErrno = NO_ERROR; |  | 
|  1402   pFile->sectorSize = getSectorSize(pVfs, zUtf8Name); |  | 
|  1403 #if SQLITE_OS_WINCE |  | 
|  1404   if( (flags & (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB)) == |  | 
|  1405                (SQLITE_OPEN_READWRITE|SQLITE_OPEN_MAIN_DB) |  | 
|  1406        && !winceCreateLock(zName, pFile) |  | 
|  1407   ){ |  | 
|  1408     CloseHandle(h); |  | 
|  1409     free(zConverted); |  | 
|  1410     return SQLITE_CANTOPEN; |  | 
|  1411   } |  | 
|  1412   if( isTemp ){ |  | 
|  1413     pFile->zDeleteOnClose = zConverted; |  | 
|  1414   }else |  | 
|  1415 #endif |  | 
|  1416   { |  | 
|  1417     free(zConverted); |  | 
|  1418   } |  | 
|  1419   OpenCounter(+1); |  | 
|  1420   return SQLITE_OK; |  | 
|  1421 } |  | 
|  1422  |  | 
|  1423 /* |  | 
|  1424 ** Delete the named file. |  | 
|  1425 ** |  | 
|  1426 ** Note that windows does not allow a file to be deleted if some other |  | 
|  1427 ** process has it open.  Sometimes a virus scanner or indexing program |  | 
|  1428 ** will open a journal file shortly after it is created in order to do |  | 
|  1429 ** whatever it does.  While this other process is holding the |  | 
|  1430 ** file open, we will be unable to delete it.  To work around this |  | 
|  1431 ** problem, we delay 100 milliseconds and try to delete again.  Up |  | 
|  1432 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving |  | 
|  1433 ** up and returning an error. |  | 
|  1434 */ |  | 
|  1435 #define MX_DELETION_ATTEMPTS 5 |  | 
|  1436 static int winDelete( |  | 
|  1437   sqlite3_vfs *pVfs,          /* Not used on win32 */ |  | 
|  1438   const char *zFilename,      /* Name of file to delete */ |  | 
|  1439   int syncDir                 /* Not used on win32 */ |  | 
|  1440 ){ |  | 
|  1441   int cnt = 0; |  | 
|  1442   DWORD rc; |  | 
|  1443   DWORD error = 0; |  | 
|  1444   void *zConverted = convertUtf8Filename(zFilename); |  | 
|  1445   UNUSED_PARAMETER(pVfs); |  | 
|  1446   UNUSED_PARAMETER(syncDir); |  | 
|  1447   if( zConverted==0 ){ |  | 
|  1448     return SQLITE_NOMEM; |  | 
|  1449   } |  | 
|  1450   SimulateIOError(return SQLITE_IOERR_DELETE); |  | 
|  1451   if( isNT() ){ |  | 
|  1452     do{ |  | 
|  1453       DeleteFileW(zConverted); |  | 
|  1454     }while(   (   ((rc = GetFileAttributesW(zConverted)) != INVALID_FILE_ATTRIBU
      TES) |  | 
|  1455                || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) |  | 
|  1456            && (++cnt < MX_DELETION_ATTEMPTS) |  | 
|  1457            && (Sleep(100), 1) ); |  | 
|  1458 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1459 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1460 ** it's important to not reference them for WINCE builds. |  | 
|  1461 */ |  | 
|  1462 #if SQLITE_OS_WINCE==0 |  | 
|  1463   }else{ |  | 
|  1464     do{ |  | 
|  1465       DeleteFileA(zConverted); |  | 
|  1466     }while(   (   ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBU
      TES) |  | 
|  1467                || ((error = GetLastError()) == ERROR_ACCESS_DENIED)) |  | 
|  1468            && (++cnt < MX_DELETION_ATTEMPTS) |  | 
|  1469            && (Sleep(100), 1) ); |  | 
|  1470 #endif |  | 
|  1471   } |  | 
|  1472   free(zConverted); |  | 
|  1473   OSTRACE2("DELETE \"%s\"\n", zFilename); |  | 
|  1474   return (   (rc == INVALID_FILE_ATTRIBUTES)  |  | 
|  1475           && (error == ERROR_FILE_NOT_FOUND)) ? SQLITE_OK : SQLITE_IOERR_DELETE; |  | 
|  1476 } |  | 
|  1477  |  | 
|  1478 /* |  | 
|  1479 ** Check the existance and status of a file. |  | 
|  1480 */ |  | 
|  1481 static int winAccess( |  | 
|  1482   sqlite3_vfs *pVfs,         /* Not used on win32 */ |  | 
|  1483   const char *zFilename,     /* Name of file to check */ |  | 
|  1484   int flags,                 /* Type of test to make on this file */ |  | 
|  1485   int *pResOut               /* OUT: Result */ |  | 
|  1486 ){ |  | 
|  1487   DWORD attr; |  | 
|  1488   int rc = 0; |  | 
|  1489   void *zConverted = convertUtf8Filename(zFilename); |  | 
|  1490   UNUSED_PARAMETER(pVfs); |  | 
|  1491   if( zConverted==0 ){ |  | 
|  1492     return SQLITE_NOMEM; |  | 
|  1493   } |  | 
|  1494   if( isNT() ){ |  | 
|  1495     attr = GetFileAttributesW((WCHAR*)zConverted); |  | 
|  1496 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1497 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1498 ** it's important to not reference them for WINCE builds. |  | 
|  1499 */ |  | 
|  1500 #if SQLITE_OS_WINCE==0 |  | 
|  1501   }else{ |  | 
|  1502     attr = GetFileAttributesA((char*)zConverted); |  | 
|  1503 #endif |  | 
|  1504   } |  | 
|  1505   free(zConverted); |  | 
|  1506   switch( flags ){ |  | 
|  1507     case SQLITE_ACCESS_READ: |  | 
|  1508     case SQLITE_ACCESS_EXISTS: |  | 
|  1509       rc = attr!=INVALID_FILE_ATTRIBUTES; |  | 
|  1510       break; |  | 
|  1511     case SQLITE_ACCESS_READWRITE: |  | 
|  1512       rc = (attr & FILE_ATTRIBUTE_READONLY)==0; |  | 
|  1513       break; |  | 
|  1514     default: |  | 
|  1515       assert(!"Invalid flags argument"); |  | 
|  1516   } |  | 
|  1517   *pResOut = rc; |  | 
|  1518   return SQLITE_OK; |  | 
|  1519 } |  | 
|  1520  |  | 
|  1521  |  | 
|  1522 /* |  | 
|  1523 ** Turn a relative pathname into a full pathname.  Write the full |  | 
|  1524 ** pathname into zOut[].  zOut[] will be at least pVfs->mxPathname |  | 
|  1525 ** bytes in size. |  | 
|  1526 */ |  | 
|  1527 static int winFullPathname( |  | 
|  1528   sqlite3_vfs *pVfs,            /* Pointer to vfs object */ |  | 
|  1529   const char *zRelative,        /* Possibly relative input path */ |  | 
|  1530   int nFull,                    /* Size of output buffer in bytes */ |  | 
|  1531   char *zFull                   /* Output buffer */ |  | 
|  1532 ){ |  | 
|  1533    |  | 
|  1534 #if defined(__CYGWIN__) |  | 
|  1535   UNUSED_PARAMETER(nFull); |  | 
|  1536   cygwin_conv_to_full_win32_path(zRelative, zFull); |  | 
|  1537   return SQLITE_OK; |  | 
|  1538 #endif |  | 
|  1539  |  | 
|  1540 #if SQLITE_OS_WINCE |  | 
|  1541   UNUSED_PARAMETER(nFull); |  | 
|  1542   /* WinCE has no concept of a relative pathname, or so I am told. */ |  | 
|  1543   sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative); |  | 
|  1544   return SQLITE_OK; |  | 
|  1545 #endif |  | 
|  1546  |  | 
|  1547 #if !SQLITE_OS_WINCE && !defined(__CYGWIN__) |  | 
|  1548   int nByte; |  | 
|  1549   void *zConverted; |  | 
|  1550   char *zOut; |  | 
|  1551   UNUSED_PARAMETER(nFull); |  | 
|  1552   zConverted = convertUtf8Filename(zRelative); |  | 
|  1553   if( isNT() ){ |  | 
|  1554     WCHAR *zTemp; |  | 
|  1555     nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, 0) + 3; |  | 
|  1556     zTemp = malloc( nByte*sizeof(zTemp[0]) ); |  | 
|  1557     if( zTemp==0 ){ |  | 
|  1558       free(zConverted); |  | 
|  1559       return SQLITE_NOMEM; |  | 
|  1560     } |  | 
|  1561     GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, 0); |  | 
|  1562     free(zConverted); |  | 
|  1563     zOut = unicodeToUtf8(zTemp); |  | 
|  1564     free(zTemp); |  | 
|  1565 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1566 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1567 ** it's important to not reference them for WINCE builds. |  | 
|  1568 */ |  | 
|  1569 #if SQLITE_OS_WINCE==0 |  | 
|  1570   }else{ |  | 
|  1571     char *zTemp; |  | 
|  1572     nByte = GetFullPathNameA((char*)zConverted, 0, 0, 0) + 3; |  | 
|  1573     zTemp = malloc( nByte*sizeof(zTemp[0]) ); |  | 
|  1574     if( zTemp==0 ){ |  | 
|  1575       free(zConverted); |  | 
|  1576       return SQLITE_NOMEM; |  | 
|  1577     } |  | 
|  1578     GetFullPathNameA((char*)zConverted, nByte, zTemp, 0); |  | 
|  1579     free(zConverted); |  | 
|  1580     zOut = sqlite3_win32_mbcs_to_utf8(zTemp); |  | 
|  1581     free(zTemp); |  | 
|  1582 #endif |  | 
|  1583   } |  | 
|  1584   if( zOut ){ |  | 
|  1585     sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut); |  | 
|  1586     free(zOut); |  | 
|  1587     return SQLITE_OK; |  | 
|  1588   }else{ |  | 
|  1589     return SQLITE_NOMEM; |  | 
|  1590   } |  | 
|  1591 #endif |  | 
|  1592 } |  | 
|  1593  |  | 
|  1594 /* |  | 
|  1595 ** Get the sector size of the device used to store |  | 
|  1596 ** file. |  | 
|  1597 */ |  | 
|  1598 static int getSectorSize( |  | 
|  1599     sqlite3_vfs *pVfs, |  | 
|  1600     const char *zRelative     /* UTF-8 file name */ |  | 
|  1601 ){ |  | 
|  1602   DWORD bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; |  | 
|  1603   /* GetDiskFreeSpace is not supported under WINCE */ |  | 
|  1604 #if SQLITE_OS_WINCE |  | 
|  1605   UNUSED_PARAMETER(pVfs); |  | 
|  1606   UNUSED_PARAMETER(zRelative); |  | 
|  1607 #else |  | 
|  1608   char zFullpath[MAX_PATH+1]; |  | 
|  1609   int rc; |  | 
|  1610   DWORD dwRet = 0; |  | 
|  1611   DWORD dwDummy; |  | 
|  1612  |  | 
|  1613   /* |  | 
|  1614   ** We need to get the full path name of the file |  | 
|  1615   ** to get the drive letter to look up the sector |  | 
|  1616   ** size. |  | 
|  1617   */ |  | 
|  1618   rc = winFullPathname(pVfs, zRelative, MAX_PATH, zFullpath); |  | 
|  1619   if( rc == SQLITE_OK ) |  | 
|  1620   { |  | 
|  1621     void *zConverted = convertUtf8Filename(zFullpath); |  | 
|  1622     if( zConverted ){ |  | 
|  1623       if( isNT() ){ |  | 
|  1624         /* trim path to just drive reference */ |  | 
|  1625         WCHAR *p = zConverted; |  | 
|  1626         for(;*p;p++){ |  | 
|  1627           if( *p == '\\' ){ |  | 
|  1628             *p = '\0'; |  | 
|  1629             break; |  | 
|  1630           } |  | 
|  1631         } |  | 
|  1632         dwRet = GetDiskFreeSpaceW((WCHAR*)zConverted, |  | 
|  1633                                   &dwDummy, |  | 
|  1634                                   &bytesPerSector, |  | 
|  1635                                   &dwDummy, |  | 
|  1636                                   &dwDummy); |  | 
|  1637       }else{ |  | 
|  1638         /* trim path to just drive reference */ |  | 
|  1639         CHAR *p = (CHAR *)zConverted; |  | 
|  1640         for(;*p;p++){ |  | 
|  1641           if( *p == '\\' ){ |  | 
|  1642             *p = '\0'; |  | 
|  1643             break; |  | 
|  1644           } |  | 
|  1645         } |  | 
|  1646         dwRet = GetDiskFreeSpaceA((CHAR*)zConverted, |  | 
|  1647                                   &dwDummy, |  | 
|  1648                                   &bytesPerSector, |  | 
|  1649                                   &dwDummy, |  | 
|  1650                                   &dwDummy); |  | 
|  1651       } |  | 
|  1652       free(zConverted); |  | 
|  1653     } |  | 
|  1654     if( !dwRet ){ |  | 
|  1655       bytesPerSector = SQLITE_DEFAULT_SECTOR_SIZE; |  | 
|  1656     } |  | 
|  1657   } |  | 
|  1658 #endif |  | 
|  1659   return (int) bytesPerSector;  |  | 
|  1660 } |  | 
|  1661  |  | 
|  1662 #ifndef SQLITE_OMIT_LOAD_EXTENSION |  | 
|  1663 /* |  | 
|  1664 ** Interfaces for opening a shared library, finding entry points |  | 
|  1665 ** within the shared library, and closing the shared library. |  | 
|  1666 */ |  | 
|  1667 /* |  | 
|  1668 ** Interfaces for opening a shared library, finding entry points |  | 
|  1669 ** within the shared library, and closing the shared library. |  | 
|  1670 */ |  | 
|  1671 static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ |  | 
|  1672   HANDLE h; |  | 
|  1673   void *zConverted = convertUtf8Filename(zFilename); |  | 
|  1674   UNUSED_PARAMETER(pVfs); |  | 
|  1675   if( zConverted==0 ){ |  | 
|  1676     return 0; |  | 
|  1677   } |  | 
|  1678   if( isNT() ){ |  | 
|  1679     h = LoadLibraryW((WCHAR*)zConverted); |  | 
|  1680 /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.  |  | 
|  1681 ** Since the ASCII version of these Windows API do not exist for WINCE, |  | 
|  1682 ** it's important to not reference them for WINCE builds. |  | 
|  1683 */ |  | 
|  1684 #if SQLITE_OS_WINCE==0 |  | 
|  1685   }else{ |  | 
|  1686     h = LoadLibraryA((char*)zConverted); |  | 
|  1687 #endif |  | 
|  1688   } |  | 
|  1689   free(zConverted); |  | 
|  1690   return (void*)h; |  | 
|  1691 } |  | 
|  1692 static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ |  | 
|  1693   UNUSED_PARAMETER(pVfs); |  | 
|  1694   getLastErrorMsg(nBuf, zBufOut); |  | 
|  1695 } |  | 
|  1696 void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){ |  | 
|  1697   UNUSED_PARAMETER(pVfs); |  | 
|  1698 #if SQLITE_OS_WINCE |  | 
|  1699   /* The GetProcAddressA() routine is only available on wince. */ |  | 
|  1700   return (void(*)(void))GetProcAddressA((HANDLE)pHandle, zSymbol); |  | 
|  1701 #else |  | 
|  1702   /* All other windows platforms expect GetProcAddress() to take |  | 
|  1703   ** an Ansi string regardless of the _UNICODE setting */ |  | 
|  1704   return (void(*)(void))GetProcAddress((HANDLE)pHandle, zSymbol); |  | 
|  1705 #endif |  | 
|  1706 } |  | 
|  1707 void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ |  | 
|  1708   UNUSED_PARAMETER(pVfs); |  | 
|  1709   FreeLibrary((HANDLE)pHandle); |  | 
|  1710 } |  | 
|  1711 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ |  | 
|  1712   #define winDlOpen  0 |  | 
|  1713   #define winDlError 0 |  | 
|  1714   #define winDlSym   0 |  | 
|  1715   #define winDlClose 0 |  | 
|  1716 #endif |  | 
|  1717  |  | 
|  1718  |  | 
|  1719 /* |  | 
|  1720 ** Write up to nBuf bytes of randomness into zBuf. |  | 
|  1721 */ |  | 
|  1722 static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |  | 
|  1723   int n = 0; |  | 
|  1724   UNUSED_PARAMETER(pVfs); |  | 
|  1725 #if defined(SQLITE_TEST) |  | 
|  1726   n = nBuf; |  | 
|  1727   memset(zBuf, 0, nBuf); |  | 
|  1728 #else |  | 
|  1729   if( sizeof(SYSTEMTIME)<=nBuf-n ){ |  | 
|  1730     SYSTEMTIME x; |  | 
|  1731     GetSystemTime(&x); |  | 
|  1732     memcpy(&zBuf[n], &x, sizeof(x)); |  | 
|  1733     n += sizeof(x); |  | 
|  1734   } |  | 
|  1735   if( sizeof(DWORD)<=nBuf-n ){ |  | 
|  1736     DWORD pid = GetCurrentProcessId(); |  | 
|  1737     memcpy(&zBuf[n], &pid, sizeof(pid)); |  | 
|  1738     n += sizeof(pid); |  | 
|  1739   } |  | 
|  1740   if( sizeof(DWORD)<=nBuf-n ){ |  | 
|  1741     DWORD cnt = GetTickCount(); |  | 
|  1742     memcpy(&zBuf[n], &cnt, sizeof(cnt)); |  | 
|  1743     n += sizeof(cnt); |  | 
|  1744   } |  | 
|  1745   if( sizeof(LARGE_INTEGER)<=nBuf-n ){ |  | 
|  1746     LARGE_INTEGER i; |  | 
|  1747     QueryPerformanceCounter(&i); |  | 
|  1748     memcpy(&zBuf[n], &i, sizeof(i)); |  | 
|  1749     n += sizeof(i); |  | 
|  1750   } |  | 
|  1751 #endif |  | 
|  1752   return n; |  | 
|  1753 } |  | 
|  1754  |  | 
|  1755  |  | 
|  1756 /* |  | 
|  1757 ** Sleep for a little while.  Return the amount of time slept. |  | 
|  1758 */ |  | 
|  1759 static int winSleep(sqlite3_vfs *pVfs, int microsec){ |  | 
|  1760   Sleep((microsec+999)/1000); |  | 
|  1761   UNUSED_PARAMETER(pVfs); |  | 
|  1762   return ((microsec+999)/1000)*1000; |  | 
|  1763 } |  | 
|  1764  |  | 
|  1765 /* |  | 
|  1766 ** The following variable, if set to a non-zero value, becomes the result |  | 
|  1767 ** returned from sqlite3OsCurrentTime().  This is used for testing. |  | 
|  1768 */ |  | 
|  1769 #ifdef SQLITE_TEST |  | 
|  1770 int sqlite3_current_time = 0; |  | 
|  1771 #endif |  | 
|  1772  |  | 
|  1773 /* |  | 
|  1774 ** Find the current time (in Universal Coordinated Time).  Write the |  | 
|  1775 ** current time and date as a Julian Day number into *prNow and |  | 
|  1776 ** return 0.  Return 1 if the time and date cannot be found. |  | 
|  1777 */ |  | 
|  1778 int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ |  | 
|  1779   FILETIME ft; |  | 
|  1780   /* FILETIME structure is a 64-bit value representing the number of  |  | 
|  1781      100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).  |  | 
|  1782   */ |  | 
|  1783   sqlite3_int64 timeW;   /* Whole days */ |  | 
|  1784   sqlite3_int64 timeF;   /* Fractional Days */ |  | 
|  1785  |  | 
|  1786   /* Number of 100-nanosecond intervals in a single day */ |  | 
|  1787   static const sqlite3_int64 ntuPerDay =  |  | 
|  1788       10000000*(sqlite3_int64)86400; |  | 
|  1789  |  | 
|  1790   /* Number of 100-nanosecond intervals in half of a day */ |  | 
|  1791   static const sqlite3_int64 ntuPerHalfDay =  |  | 
|  1792       10000000*(sqlite3_int64)43200; |  | 
|  1793  |  | 
|  1794   /* 2^32 - to avoid use of LL and warnings in gcc */ |  | 
|  1795   static const sqlite3_int64 max32BitValue =  |  | 
|  1796       (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294
      967296; |  | 
|  1797  |  | 
|  1798 #if SQLITE_OS_WINCE |  | 
|  1799   SYSTEMTIME time; |  | 
|  1800   GetSystemTime(&time); |  | 
|  1801   /* if SystemTimeToFileTime() fails, it returns zero. */ |  | 
|  1802   if (!SystemTimeToFileTime(&time,&ft)){ |  | 
|  1803     return 1; |  | 
|  1804   } |  | 
|  1805 #else |  | 
|  1806   GetSystemTimeAsFileTime( &ft ); |  | 
|  1807 #endif |  | 
|  1808   UNUSED_PARAMETER(pVfs); |  | 
|  1809   timeW = (((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + (sqlite3_int64)ft
      .dwLowDateTime; |  | 
|  1810   timeF = timeW % ntuPerDay;          /* fractional days (100-nanoseconds) */ |  | 
|  1811   timeW = timeW / ntuPerDay;          /* whole days */ |  | 
|  1812   timeW = timeW + 2305813;            /* add whole days (from 2305813.5) */ |  | 
|  1813   timeF = timeF + ntuPerHalfDay;      /* add half a day (from 2305813.5) */ |  | 
|  1814   timeW = timeW + (timeF/ntuPerDay);  /* add whole day if half day made one */ |  | 
|  1815   timeF = timeF % ntuPerDay;          /* compute new fractional days */ |  | 
|  1816   *prNow = (double)timeW + ((double)timeF / (double)ntuPerDay); |  | 
|  1817 #ifdef SQLITE_TEST |  | 
|  1818   if( sqlite3_current_time ){ |  | 
|  1819     *prNow = ((double)sqlite3_current_time + (double)43200) / (double)86400 + (d
      ouble)2440587; |  | 
|  1820   } |  | 
|  1821 #endif |  | 
|  1822   return 0; |  | 
|  1823 } |  | 
|  1824  |  | 
|  1825 /* |  | 
|  1826 ** The idea is that this function works like a combination of |  | 
|  1827 ** GetLastError() and FormatMessage() on windows (or errno and |  | 
|  1828 ** strerror_r() on unix). After an error is returned by an OS |  | 
|  1829 ** function, SQLite calls this function with zBuf pointing to |  | 
|  1830 ** a buffer of nBuf bytes. The OS layer should populate the |  | 
|  1831 ** buffer with a nul-terminated UTF-8 encoded error message |  | 
|  1832 ** describing the last IO error to have occurred within the calling |  | 
|  1833 ** thread. |  | 
|  1834 ** |  | 
|  1835 ** If the error message is too large for the supplied buffer, |  | 
|  1836 ** it should be truncated. The return value of xGetLastError |  | 
|  1837 ** is zero if the error message fits in the buffer, or non-zero |  | 
|  1838 ** otherwise (if the message was truncated). If non-zero is returned, |  | 
|  1839 ** then it is not necessary to include the nul-terminator character |  | 
|  1840 ** in the output buffer. |  | 
|  1841 ** |  | 
|  1842 ** Not supplying an error message will have no adverse effect |  | 
|  1843 ** on SQLite. It is fine to have an implementation that never |  | 
|  1844 ** returns an error message: |  | 
|  1845 ** |  | 
|  1846 **   int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |  | 
|  1847 **     assert(zBuf[0]=='\0'); |  | 
|  1848 **     return 0; |  | 
|  1849 **   } |  | 
|  1850 ** |  | 
|  1851 ** However if an error message is supplied, it will be incorporated |  | 
|  1852 ** by sqlite into the error message available to the user using |  | 
|  1853 ** sqlite3_errmsg(), possibly making IO errors easier to debug. |  | 
|  1854 */ |  | 
|  1855 static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ |  | 
|  1856   UNUSED_PARAMETER(pVfs); |  | 
|  1857   return getLastErrorMsg(nBuf, zBuf); |  | 
|  1858 } |  | 
|  1859  |  | 
|  1860 /* |  | 
|  1861 ** Initialize and deinitialize the operating system interface. |  | 
|  1862 */ |  | 
|  1863 int sqlite3_os_init(void){ |  | 
|  1864   static sqlite3_vfs winVfs = { |  | 
|  1865     1,                 /* iVersion */ |  | 
|  1866     sizeof(winFile),   /* szOsFile */ |  | 
|  1867     MAX_PATH,          /* mxPathname */ |  | 
|  1868     0,                 /* pNext */ |  | 
|  1869     "win32",           /* zName */ |  | 
|  1870     0,                 /* pAppData */ |  | 
|  1871   |  | 
|  1872     winOpen,           /* xOpen */ |  | 
|  1873     winDelete,         /* xDelete */ |  | 
|  1874     winAccess,         /* xAccess */ |  | 
|  1875     winFullPathname,   /* xFullPathname */ |  | 
|  1876     winDlOpen,         /* xDlOpen */ |  | 
|  1877     winDlError,        /* xDlError */ |  | 
|  1878     winDlSym,          /* xDlSym */ |  | 
|  1879     winDlClose,        /* xDlClose */ |  | 
|  1880     winRandomness,     /* xRandomness */ |  | 
|  1881     winSleep,          /* xSleep */ |  | 
|  1882     winCurrentTime,    /* xCurrentTime */ |  | 
|  1883     winGetLastError    /* xGetLastError */ |  | 
|  1884   }; |  | 
|  1885  |  | 
|  1886   sqlite3_vfs_register(&winVfs, 1); |  | 
|  1887   return SQLITE_OK;  |  | 
|  1888 } |  | 
|  1889 int sqlite3_os_end(void){  |  | 
|  1890   return SQLITE_OK; |  | 
|  1891 } |  | 
|  1892  |  | 
|  1893 void chromium_sqlite3_initialize_win_sqlite3_file(sqlite3_file* file, HANDLE han
      dle) { |  | 
|  1894   winFile* winSQLite3File = (winFile*)file; |  | 
|  1895   memset(file, 0, sizeof(*file)); |  | 
|  1896   winSQLite3File->pMethod = &winIoMethod; |  | 
|  1897   winSQLite3File->h = handle; |  | 
|  1898 } |  | 
|  1899  |  | 
|  1900 #endif /* SQLITE_OS_WIN */ |  | 
| OLD | NEW |