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