Back to index

lightning-sunbird  0.9+nobinonly
os_win.c
Go to the documentation of this file.
00001 /*
00002 ** 2004 May 22
00003 **
00004 ** The author disclaims copyright to this source code.  In place of
00005 ** a legal notice, here is a blessing:
00006 **
00007 **    May you do good and not evil.
00008 **    May you find forgiveness for yourself and forgive others.
00009 **    May you share freely, never taking more than you give.
00010 **
00011 ******************************************************************************
00012 **
00013 ** This file contains code that is specific to windows.
00014 */
00015 #include "sqliteInt.h"
00016 #include "os.h"
00017 #if OS_WIN               /* This file is used for windows only */
00018 
00019 #include <winbase.h>
00020 
00021 #ifdef __CYGWIN__
00022 # include <sys/cygwin.h>
00023 #endif
00024 
00025 /*
00026 ** Macros used to determine whether or not to use threads.
00027 */
00028 #if defined(THREADSAFE) && THREADSAFE
00029 # define SQLITE_W32_THREADS 1
00030 #endif
00031 
00032 /*
00033 ** Include code that is common to all os_*.c files
00034 */
00035 #include "os_common.h"
00036 
00037 /*
00038 ** Determine if we are dealing with WindowsCE - which has a much
00039 ** reduced API.
00040 */
00041 #if defined(_WIN32_WCE)
00042 # define OS_WINCE 1
00043 #else
00044 # define OS_WINCE 0
00045 #endif
00046 
00047 /*
00048 ** WinCE lacks native support for file locking so we have to fake it
00049 ** with some code of our own.
00050 */
00051 #if OS_WINCE
00052 typedef struct winceLock {
00053   int nReaders;       /* Number of reader locks obtained */
00054   BOOL bPending;      /* Indicates a pending lock has been obtained */
00055   BOOL bReserved;     /* Indicates a reserved lock has been obtained */
00056   BOOL bExclusive;    /* Indicates an exclusive lock has been obtained */
00057 } winceLock;
00058 #endif
00059 
00060 /*
00061 ** The winFile structure is a subclass of OsFile specific to the win32
00062 ** portability layer.
00063 */
00064 typedef struct winFile winFile;
00065 struct winFile {
00066   IoMethod const *pMethod;/* Must be first */
00067   HANDLE h;               /* Handle for accessing the file */
00068   unsigned char locktype; /* Type of lock currently held on this file */
00069   short sharedLockByte;   /* Randomly chosen byte used as a shared lock */
00070 #if OS_WINCE
00071   WCHAR *zDeleteOnClose;  /* Name of file to delete when closing */
00072   HANDLE hMutex;          /* Mutex used to control access to shared lock */  
00073   HANDLE hShared;         /* Shared memory segment used for locking */
00074   winceLock local;        /* Locks obtained by this instance of winFile */
00075   winceLock *shared;      /* Global shared lock memory for the file  */
00076 #endif
00077 };
00078 
00079 
00080 /*
00081 ** Do not include any of the File I/O interface procedures if the
00082 ** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
00083 ** will be in-memory only)
00084 */
00085 #ifndef SQLITE_OMIT_DISKIO
00086 
00087 /*
00088 ** The following variable is (normally) set once and never changes
00089 ** thereafter.  It records whether the operating system is Win95
00090 ** or WinNT.
00091 **
00092 ** 0:   Operating system unknown.
00093 ** 1:   Operating system is Win95.
00094 ** 2:   Operating system is WinNT.
00095 **
00096 ** In order to facilitate testing on a WinNT system, the test fixture
00097 ** can manually set this value to 1 to emulate Win98 behavior.
00098 */
00099 int sqlite3_os_type = 0;
00100 
00101 /*
00102 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
00103 ** or WinCE.  Return false (zero) for Win95, Win98, or WinME.
00104 **
00105 ** Here is an interesting observation:  Win95, Win98, and WinME lack
00106 ** the LockFileEx() API.  But we can still statically link against that
00107 ** API as long as we don't call it win running Win95/98/ME.  A call to
00108 ** this routine is used to determine if the host is Win95/98/ME or
00109 ** WinNT/2K/XP so that we will know whether or not we can safely call
00110 ** the LockFileEx() API.
00111 */
00112 #if OS_WINCE
00113 # define isNT()  (1)
00114 #else
00115   static int isNT(void){
00116     if( sqlite3_os_type==0 ){
00117       OSVERSIONINFO sInfo;
00118       sInfo.dwOSVersionInfoSize = sizeof(sInfo);
00119       GetVersionEx(&sInfo);
00120       sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
00121     }
00122     return sqlite3_os_type==2;
00123   }
00124 #endif /* OS_WINCE */
00125 
00126 /*
00127 ** Convert a UTF-8 string to UTF-32.  Space to hold the returned string
00128 ** is obtained from sqliteMalloc.
00129 */
00130 static WCHAR *utf8ToUnicode(const char *zFilename){
00131   int nChar;
00132   WCHAR *zWideFilename;
00133 
00134   nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
00135   zWideFilename = sqliteMalloc( nChar*sizeof(zWideFilename[0]) );
00136   if( zWideFilename==0 ){
00137     return 0;
00138   }
00139   nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
00140   if( nChar==0 ){
00141     sqliteFree(zWideFilename);
00142     zWideFilename = 0;
00143   }
00144   return zWideFilename;
00145 }
00146 
00147 /*
00148 ** Convert UTF-32 to UTF-8.  Space to hold the returned string is
00149 ** obtained from sqliteMalloc().
00150 */
00151 static char *unicodeToUtf8(const WCHAR *zWideFilename){
00152   int nByte;
00153   char *zFilename;
00154 
00155   nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
00156   zFilename = sqliteMalloc( nByte );
00157   if( zFilename==0 ){
00158     return 0;
00159   }
00160   nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
00161                               0, 0);
00162   if( nByte == 0 ){
00163     sqliteFree(zFilename);
00164     zFilename = 0;
00165   }
00166   return zFilename;
00167 }
00168 
00169 /*
00170 ** Convert a multibyte character string to UTF-32, based on the current Ansi codepage (CP_ACP).
00171 ** Space to hold the returned string is obtained from sqliteMalloc.
00172 */
00173 static WCHAR *mbcsToUnicode(const char *zFilename){
00174   int nByte;
00175   WCHAR *zMbcsFilename;
00176 
00177   nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
00178   zMbcsFilename = sqliteMalloc( nByte*sizeof(zMbcsFilename[0]) );
00179   if( zMbcsFilename==0 ){
00180     return 0;
00181   }
00182   nByte = MultiByteToWideChar(CP_ACP, 0, zFilename, -1, zMbcsFilename, nByte);
00183   if( nByte==0 ){
00184     sqliteFree(zMbcsFilename);
00185     zMbcsFilename = 0;
00186   }
00187   return zMbcsFilename;
00188 }
00189 
00190 /*
00191 ** Convert UTF-32 to multibyte character string, based on the user's Ansi codepage (CP_ACP).
00192 ** Space to hold the returned string is obtained from sqliteMalloc().
00193 */
00194 static char *unicodeToMbcs(const WCHAR *zWideFilename){
00195   int nByte;
00196   char *zFilename;
00197 
00198   nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, 0, 0, 0, 0);
00199   zFilename = sqliteMalloc( nByte );
00200   if( zFilename==0 ){
00201     return 0;
00202   }
00203   nByte = WideCharToMultiByte(CP_ACP, 0, zWideFilename, -1, zFilename, nByte,
00204                               0, 0);
00205   if( nByte == 0 ){
00206     sqliteFree(zFilename);
00207     zFilename = 0;
00208   }
00209   return zFilename;
00210 }
00211 
00212 /*
00213 ** Convert multibyte character string to UTF-8.  Space to hold the returned string is
00214 ** obtained from sqliteMalloc().
00215 */
00216 static char *mbcsToUtf8(const char *zFilename){
00217   char *zFilenameUtf8;
00218   WCHAR *zTmpWide;
00219 
00220   zTmpWide = mbcsToUnicode(zFilename);
00221   if( zTmpWide==0 ){
00222     return 0;
00223   }
00224   zFilenameUtf8 = unicodeToUtf8(zTmpWide);
00225   sqliteFree(zTmpWide);
00226   return zFilenameUtf8;
00227 }
00228 
00229 /*
00230 ** Convert UTF-8 to multibyte character string.  Space to hold the returned string is
00231 ** obtained from sqliteMalloc().
00232 */
00233 static char *utf8ToMbcs(const char *zFilename){
00234   char *zFilenameMbcs;
00235   WCHAR *zTmpWide;
00236 
00237   zTmpWide = utf8ToUnicode(zFilename);
00238   if( zTmpWide==0 ){
00239     return 0;
00240   }
00241   zFilenameMbcs = unicodeToMbcs(zTmpWide);
00242   sqliteFree(zTmpWide);
00243   return zFilenameMbcs;
00244 }
00245 
00246 #if OS_WINCE
00247 /*************************************************************************
00248 ** This section contains code for WinCE only.
00249 */
00250 /*
00251 ** WindowsCE does not have a localtime() function.  So create a
00252 ** substitute.
00253 */
00254 #include <time.h>
00255 struct tm *__cdecl localtime(const time_t *t)
00256 {
00257   static struct tm y;
00258   FILETIME uTm, lTm;
00259   SYSTEMTIME pTm;
00260   i64 t64;
00261   t64 = *t;
00262   t64 = (t64 + 11644473600)*10000000;
00263   uTm.dwLowDateTime = t64 & 0xFFFFFFFF;
00264   uTm.dwHighDateTime= t64 >> 32;
00265   FileTimeToLocalFileTime(&uTm,&lTm);
00266   FileTimeToSystemTime(&lTm,&pTm);
00267   y.tm_year = pTm.wYear - 1900;
00268   y.tm_mon = pTm.wMonth - 1;
00269   y.tm_wday = pTm.wDayOfWeek;
00270   y.tm_mday = pTm.wDay;
00271   y.tm_hour = pTm.wHour;
00272   y.tm_min = pTm.wMinute;
00273   y.tm_sec = pTm.wSecond;
00274   return &y;
00275 }
00276 
00277 /* This will never be called, but defined to make the code compile */
00278 #define GetTempPathA(a,b)
00279 
00280 #define LockFile(a,b,c,d,e)       winceLockFile(&a, b, c, d, e)
00281 #define UnlockFile(a,b,c,d,e)     winceUnlockFile(&a, b, c, d, e)
00282 #define LockFileEx(a,b,c,d,e,f)   winceLockFileEx(&a, b, c, d, e, f)
00283 
00284 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)]
00285 
00286 /*
00287 ** Acquire a lock on the handle h
00288 */
00289 static void winceMutexAcquire(HANDLE h){
00290    DWORD dwErr;
00291    do {
00292      dwErr = WaitForSingleObject(h, INFINITE);
00293    } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
00294 }
00295 /*
00296 ** Release a lock acquired by winceMutexAcquire()
00297 */
00298 #define winceMutexRelease(h) ReleaseMutex(h)
00299 
00300 /*
00301 ** Create the mutex and shared memory used for locking in the file
00302 ** descriptor pFile
00303 */
00304 static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
00305   WCHAR *zTok;
00306   WCHAR *zName = utf8ToUnicode(zFilename);
00307   BOOL bInit = TRUE;
00308 
00309   /* Initialize the local lockdata */
00310   ZeroMemory(&pFile->local, sizeof(pFile->local));
00311 
00312   /* Replace the backslashes from the filename and lowercase it
00313   ** to derive a mutex name. */
00314   zTok = CharLowerW(zName);
00315   for (;*zTok;zTok++){
00316     if (*zTok == '\\') *zTok = '_';
00317   }
00318 
00319   /* Create/open the named mutex */
00320   pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
00321   if (!pFile->hMutex){
00322     sqliteFree(zName);
00323     return FALSE;
00324   }
00325 
00326   /* Acquire the mutex before continuing */
00327   winceMutexAcquire(pFile->hMutex);
00328   
00329   /* Since the names of named mutexes, semaphores, file mappings etc are 
00330   ** case-sensitive, take advantage of that by uppercasing the mutex name
00331   ** and using that as the shared filemapping name.
00332   */
00333   CharUpperW(zName);
00334   pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
00335                                        PAGE_READWRITE, 0, sizeof(winceLock),
00336                                        zName);  
00337 
00338   /* Set a flag that indicates we're the first to create the memory so it 
00339   ** must be zero-initialized */
00340   if (GetLastError() == ERROR_ALREADY_EXISTS){
00341     bInit = FALSE;
00342   }
00343 
00344   sqliteFree(zName);
00345 
00346   /* If we succeeded in making the shared memory handle, map it. */
00347   if (pFile->hShared){
00348     pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, 
00349              FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
00350     /* If mapping failed, close the shared memory handle and erase it */
00351     if (!pFile->shared){
00352       CloseHandle(pFile->hShared);
00353       pFile->hShared = NULL;
00354     }
00355   }
00356 
00357   /* If shared memory could not be created, then close the mutex and fail */
00358   if (pFile->hShared == NULL){
00359     winceMutexRelease(pFile->hMutex);
00360     CloseHandle(pFile->hMutex);
00361     pFile->hMutex = NULL;
00362     return FALSE;
00363   }
00364   
00365   /* Initialize the shared memory if we're supposed to */
00366   if (bInit) {
00367     ZeroMemory(pFile->shared, sizeof(winceLock));
00368   }
00369 
00370   winceMutexRelease(pFile->hMutex);
00371   return TRUE;
00372 }
00373 
00374 /*
00375 ** Destroy the part of winFile that deals with wince locks
00376 */
00377 static void winceDestroyLock(winFile *pFile){
00378   if (pFile->hMutex){
00379     /* Acquire the mutex */
00380     winceMutexAcquire(pFile->hMutex);
00381 
00382     /* The following blocks should probably assert in debug mode, but they
00383        are to cleanup in case any locks remained open */
00384     if (pFile->local.nReaders){
00385       pFile->shared->nReaders --;
00386     }
00387     if (pFile->local.bReserved){
00388       pFile->shared->bReserved = FALSE;
00389     }
00390     if (pFile->local.bPending){
00391       pFile->shared->bPending = FALSE;
00392     }
00393     if (pFile->local.bExclusive){
00394       pFile->shared->bExclusive = FALSE;
00395     }
00396 
00397     /* De-reference and close our copy of the shared memory handle */
00398     UnmapViewOfFile(pFile->shared);
00399     CloseHandle(pFile->hShared);
00400 
00401     /* Done with the mutex */
00402     winceMutexRelease(pFile->hMutex);    
00403     CloseHandle(pFile->hMutex);
00404     pFile->hMutex = NULL;
00405   }
00406 }
00407 
00408 /* 
00409 ** An implementation of the LockFile() API of windows for wince
00410 */
00411 static BOOL winceLockFile(
00412   HANDLE *phFile,
00413   DWORD dwFileOffsetLow,
00414   DWORD dwFileOffsetHigh,
00415   DWORD nNumberOfBytesToLockLow,
00416   DWORD nNumberOfBytesToLockHigh
00417 ){
00418   winFile *pFile = HANDLE_TO_WINFILE(phFile);
00419   BOOL bReturn = FALSE;
00420 
00421   if (!pFile->hMutex) return TRUE;
00422   winceMutexAcquire(pFile->hMutex);
00423 
00424   /* Wanting an exclusive lock? */
00425   if (dwFileOffsetLow == SHARED_FIRST
00426        && nNumberOfBytesToLockLow == SHARED_SIZE){
00427     if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
00428        pFile->shared->bExclusive = TRUE;
00429        pFile->local.bExclusive = TRUE;
00430        bReturn = TRUE;
00431     }
00432   }
00433 
00434   /* Want a read-only lock? */
00435   else if ((dwFileOffsetLow >= SHARED_FIRST &&
00436             dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) &&
00437             nNumberOfBytesToLockLow == 1){
00438     if (pFile->shared->bExclusive == 0){
00439       pFile->local.nReaders ++;
00440       if (pFile->local.nReaders == 1){
00441         pFile->shared->nReaders ++;
00442       }
00443       bReturn = TRUE;
00444     }
00445   }
00446 
00447   /* Want a pending lock? */
00448   else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){
00449     /* If no pending lock has been acquired, then acquire it */
00450     if (pFile->shared->bPending == 0) {
00451       pFile->shared->bPending = TRUE;
00452       pFile->local.bPending = TRUE;
00453       bReturn = TRUE;
00454     }
00455   }
00456   /* Want a reserved lock? */
00457   else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
00458     if (pFile->shared->bReserved == 0) {
00459       pFile->shared->bReserved = TRUE;
00460       pFile->local.bReserved = TRUE;
00461       bReturn = TRUE;
00462     }
00463   }
00464 
00465   winceMutexRelease(pFile->hMutex);
00466   return bReturn;
00467 }
00468 
00469 /*
00470 ** An implementation of the UnlockFile API of windows for wince
00471 */
00472 static BOOL winceUnlockFile(
00473   HANDLE *phFile,
00474   DWORD dwFileOffsetLow,
00475   DWORD dwFileOffsetHigh,
00476   DWORD nNumberOfBytesToUnlockLow,
00477   DWORD nNumberOfBytesToUnlockHigh
00478 ){
00479   winFile *pFile = HANDLE_TO_WINFILE(phFile);
00480   BOOL bReturn = FALSE;
00481 
00482   if (!pFile->hMutex) return TRUE;
00483   winceMutexAcquire(pFile->hMutex);
00484 
00485   /* Releasing a reader lock or an exclusive lock */
00486   if (dwFileOffsetLow >= SHARED_FIRST &&
00487        dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){
00488     /* Did we have an exclusive lock? */
00489     if (pFile->local.bExclusive){
00490       pFile->local.bExclusive = FALSE;
00491       pFile->shared->bExclusive = FALSE;
00492       bReturn = TRUE;
00493     }
00494 
00495     /* Did we just have a reader lock? */
00496     else if (pFile->local.nReaders){
00497       pFile->local.nReaders --;
00498       if (pFile->local.nReaders == 0)
00499       {
00500         pFile->shared->nReaders --;
00501       }
00502       bReturn = TRUE;
00503     }
00504   }
00505 
00506   /* Releasing a pending lock */
00507   else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
00508     if (pFile->local.bPending){
00509       pFile->local.bPending = FALSE;
00510       pFile->shared->bPending = FALSE;
00511       bReturn = TRUE;
00512     }
00513   }
00514   /* Releasing a reserved lock */
00515   else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
00516     if (pFile->local.bReserved) {
00517       pFile->local.bReserved = FALSE;
00518       pFile->shared->bReserved = FALSE;
00519       bReturn = TRUE;
00520     }
00521   }
00522 
00523   winceMutexRelease(pFile->hMutex);
00524   return bReturn;
00525 }
00526 
00527 /*
00528 ** An implementation of the LockFileEx() API of windows for wince
00529 */
00530 static BOOL winceLockFileEx(
00531   HANDLE *phFile,
00532   DWORD dwFlags,
00533   DWORD dwReserved,
00534   DWORD nNumberOfBytesToLockLow,
00535   DWORD nNumberOfBytesToLockHigh,
00536   LPOVERLAPPED lpOverlapped
00537 ){
00538   /* If the caller wants a shared read lock, forward this call
00539   ** to winceLockFile */
00540   if (lpOverlapped->Offset == SHARED_FIRST &&
00541       dwFlags == 1 &&
00542       nNumberOfBytesToLockLow == SHARED_SIZE){
00543     return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
00544   }
00545   return FALSE;
00546 }
00547 /*
00548 ** End of the special code for wince
00549 *****************************************************************************/
00550 #endif /* OS_WINCE */
00551 
00552 static void *convertUtf8Filename(const char *zFilename){
00553   void *zConverted = 0;
00554   if( isNT() ){
00555     zConverted = utf8ToUnicode(zFilename);
00556   }else{
00557     zConverted = utf8ToMbcs(zFilename);
00558   }
00559   /* caller will handle out of memory */
00560   return zConverted;
00561 }
00562 
00563 /*
00564 ** Delete the named file
00565 */
00566 int sqlite3WinDelete(const char *zFilename){
00567   void *zConverted = convertUtf8Filename(zFilename);
00568   if( zConverted==0 )
00569     return SQLITE_NOMEM;
00570   if( isNT() ){
00571     DeleteFileW((WCHAR*)zConverted);
00572   }else{
00573     DeleteFileA((char*)zConverted);
00574   }
00575   sqliteFree(zConverted);
00576   TRACE2("DELETE \"%s\"\n", zFilename);
00577   return SQLITE_OK;
00578 }
00579 
00580 /*
00581 ** Return TRUE if the named file exists.
00582 */
00583 int sqlite3WinFileExists(const char *zFilename){
00584   int exists = 0;
00585   void *zConverted = convertUtf8Filename(zFilename);
00586   if( zConverted==0 )
00587     return SQLITE_NOMEM;
00588   if( isNT() ){
00589     exists = GetFileAttributesW((WCHAR*)zConverted) != 0xffffffff;
00590   }else{
00591     exists = GetFileAttributesA((char*)zConverted) != 0xffffffff;
00592   }
00593   sqliteFree(zConverted);
00594   return exists;
00595 }
00596 
00597 /* Forward declaration */
00598 static int allocateWinFile(winFile *pInit, OsFile **pId);
00599 
00600 /*
00601 ** Attempt to open a file for both reading and writing.  If that
00602 ** fails, try opening it read-only.  If the file does not exist,
00603 ** try to create it.
00604 **
00605 ** On success, a handle for the open file is written to *id
00606 ** and *pReadonly is set to 0 if the file was opened for reading and
00607 ** writing or 1 if the file was opened read-only.  The function returns
00608 ** SQLITE_OK.
00609 **
00610 ** On failure, the function returns SQLITE_CANTOPEN and leaves
00611 ** *id and *pReadonly unchanged.
00612 */
00613 int sqlite3WinOpenReadWrite(
00614   const char *zFilename,
00615   OsFile **pId,
00616   int *pReadonly
00617 ){
00618   winFile f;
00619   HANDLE h;
00620   void *zConverted = convertUtf8Filename(zFilename);
00621   if( zConverted==0 )
00622     return SQLITE_NOMEM;
00623   assert( *pId==0 );
00624 
00625   if( isNT() ){
00626     h = CreateFileW((WCHAR*)zConverted,
00627        GENERIC_READ | GENERIC_WRITE,
00628        FILE_SHARE_READ | FILE_SHARE_WRITE,
00629        NULL,
00630        OPEN_ALWAYS,
00631        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00632        NULL
00633     );
00634     if( h==INVALID_HANDLE_VALUE ){
00635       h = CreateFileW((WCHAR*)zConverted,
00636          GENERIC_READ,
00637          FILE_SHARE_READ,
00638          NULL,
00639          OPEN_ALWAYS,
00640          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00641          NULL
00642       );
00643       if( h==INVALID_HANDLE_VALUE ){
00644         sqliteFree(zConverted);
00645         return SQLITE_CANTOPEN;
00646       }
00647       *pReadonly = 1;
00648     }else{
00649       *pReadonly = 0;
00650     }
00651 #if OS_WINCE
00652     if (!winceCreateLock(zFilename, &f)){
00653       CloseHandle(h);
00654       sqliteFree(zConverted);
00655       return SQLITE_CANTOPEN;
00656     }
00657 #endif
00658   }else{
00659     h = CreateFileA((char*)zConverted,
00660        GENERIC_READ | GENERIC_WRITE,
00661        FILE_SHARE_READ | FILE_SHARE_WRITE,
00662        NULL,
00663        OPEN_ALWAYS,
00664        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00665        NULL
00666     );
00667     if( h==INVALID_HANDLE_VALUE ){
00668       h = CreateFileA((char*)zConverted,
00669          GENERIC_READ,
00670          FILE_SHARE_READ,
00671          NULL,
00672          OPEN_ALWAYS,
00673          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00674          NULL
00675       );
00676       if( h==INVALID_HANDLE_VALUE ){
00677         sqliteFree(zConverted);
00678         return SQLITE_CANTOPEN;
00679       }
00680       *pReadonly = 1;
00681     }else{
00682       *pReadonly = 0;
00683     }
00684   }
00685 
00686   sqliteFree(zConverted);
00687 
00688   f.h = h;
00689 #if OS_WINCE
00690   f.zDeleteOnClose = 0;
00691 #endif
00692   TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
00693   return allocateWinFile(&f, pId);
00694 }
00695 
00696 
00697 /*
00698 ** Attempt to open a new file for exclusive access by this process.
00699 ** The file will be opened for both reading and writing.  To avoid
00700 ** a potential security problem, we do not allow the file to have
00701 ** previously existed.  Nor do we allow the file to be a symbolic
00702 ** link.
00703 **
00704 ** If delFlag is true, then make arrangements to automatically delete
00705 ** the file when it is closed.
00706 **
00707 ** On success, write the file handle into *id and return SQLITE_OK.
00708 **
00709 ** On failure, return SQLITE_CANTOPEN.
00710 */
00711 int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
00712   winFile f;
00713   HANDLE h;
00714   int fileflags;
00715   void *zConverted = convertUtf8Filename(zFilename);
00716   if( zConverted==0 )
00717     return SQLITE_NOMEM;
00718   assert( *pId == 0 );
00719   fileflags = FILE_FLAG_RANDOM_ACCESS;
00720 #if !OS_WINCE
00721   if( delFlag ){
00722     fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
00723   }
00724 #endif
00725   if( isNT() ){
00726     h = CreateFileW((WCHAR*)zConverted,
00727        GENERIC_READ | GENERIC_WRITE,
00728        0,
00729        NULL,
00730        CREATE_ALWAYS,
00731        fileflags,
00732        NULL
00733     );
00734   }else{
00735     h = CreateFileA((char*)zConverted,
00736        GENERIC_READ | GENERIC_WRITE,
00737        0,
00738        NULL,
00739        CREATE_ALWAYS,
00740        fileflags,
00741        NULL
00742     );
00743   }
00744   sqliteFree(zConverted);
00745   if( h==INVALID_HANDLE_VALUE ){
00746     return SQLITE_CANTOPEN;
00747   }
00748   f.h = h;
00749 #if OS_WINCE
00750   f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0;
00751   f.hMutex = NULL;
00752 #endif
00753   TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
00754   return allocateWinFile(&f, pId);
00755 }
00756 
00757 /*
00758 ** Attempt to open a new file for read-only access.
00759 **
00760 ** On success, write the file handle into *id and return SQLITE_OK.
00761 **
00762 ** On failure, return SQLITE_CANTOPEN.
00763 */
00764 int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
00765   winFile f;
00766   HANDLE h;
00767   void *zConverted = convertUtf8Filename(zFilename);
00768   if( zConverted==0 )
00769     return SQLITE_NOMEM;
00770   assert( *pId==0 );
00771   if( isNT() ){
00772     h = CreateFileW((WCHAR*)zConverted,
00773        GENERIC_READ,
00774        0,
00775        NULL,
00776        OPEN_EXISTING,
00777        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00778        NULL
00779     );
00780   }else{
00781     h = CreateFileA((char*)zConverted,
00782        GENERIC_READ,
00783        0,
00784        NULL,
00785        OPEN_EXISTING,
00786        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
00787        NULL
00788     );
00789   }
00790   sqliteFree(zConverted);
00791   if( h==INVALID_HANDLE_VALUE ){
00792     return SQLITE_CANTOPEN;
00793   }
00794   f.h = h;
00795 #if OS_WINCE
00796   f.zDeleteOnClose = 0;
00797   f.hMutex = NULL;
00798 #endif
00799   TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
00800   return allocateWinFile(&f, pId);
00801 }
00802 
00803 /*
00804 ** Attempt to open a file descriptor for the directory that contains a
00805 ** file.  This file descriptor can be used to fsync() the directory
00806 ** in order to make sure the creation of a new file is actually written
00807 ** to disk.
00808 **
00809 ** This routine is only meaningful for Unix.  It is a no-op under
00810 ** windows since windows does not support hard links.
00811 **
00812 ** On success, a handle for a previously open file is at *id is
00813 ** updated with the new directory file descriptor and SQLITE_OK is
00814 ** returned.
00815 **
00816 ** On failure, the function returns SQLITE_CANTOPEN and leaves
00817 ** *id unchanged.
00818 */
00819 static int winOpenDirectory(
00820   OsFile *id,
00821   const char *zDirname
00822 ){
00823   return SQLITE_OK;
00824 }
00825 
00826 /*
00827 ** If the following global variable points to a string which is the
00828 ** name of a directory, then that directory will be used to store
00829 ** temporary files.
00830 */
00831 char *sqlite3_temp_directory = 0;
00832 
00833 /*
00834 ** Create a temporary file name in zBuf.  zBuf must be big enough to
00835 ** hold at least SQLITE_TEMPNAME_SIZE characters.
00836 */
00837 int sqlite3WinTempFileName(char *zBuf){
00838   static char zChars[] =
00839     "abcdefghijklmnopqrstuvwxyz"
00840     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
00841     "0123456789";
00842   int i, j;
00843   char zTempPath[SQLITE_TEMPNAME_SIZE];
00844   if( sqlite3_temp_directory ){
00845     strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
00846     zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
00847   }else if( isNT() ){
00848     char *zMulti;
00849     WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
00850     GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
00851     zMulti = unicodeToUtf8(zWidePath);
00852     if( zMulti ){
00853       strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
00854       zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
00855       sqliteFree(zMulti);
00856     }else{
00857       return SQLITE_NOMEM;
00858     }
00859   }else{
00860     char *zUtf8;
00861     char zMbcsPath[SQLITE_TEMPNAME_SIZE];
00862     GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zMbcsPath);
00863     zUtf8 = mbcsToUtf8(zMbcsPath);
00864     if( zUtf8 ){
00865       strncpy(zTempPath, zUtf8, SQLITE_TEMPNAME_SIZE-30);
00866       zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
00867       sqliteFree(zUtf8);
00868     }else{
00869       return SQLITE_NOMEM;
00870     }
00871   }
00872   for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
00873   zTempPath[i] = 0;
00874   for(;;){
00875     sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
00876     j = strlen(zBuf);
00877     sqlite3Randomness(15, &zBuf[j]);
00878     for(i=0; i<15; i++, j++){
00879       zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
00880     }
00881     zBuf[j] = 0;
00882     if( !sqlite3OsFileExists(zBuf) ) break;
00883   }
00884   TRACE2("TEMP FILENAME: %s\n", zBuf);
00885   return SQLITE_OK; 
00886 }
00887 
00888 /*
00889 ** Close a file.
00890 */
00891 static int winClose(OsFile **pId){
00892   winFile *pFile;
00893   if( pId && (pFile = (winFile*)*pId)!=0 ){
00894     TRACE2("CLOSE %d\n", pFile->h);
00895     CloseHandle(pFile->h);
00896 #if OS_WINCE
00897     winceDestroyLock(pFile);
00898     if( pFile->zDeleteOnClose ){
00899       DeleteFileW(pFile->zDeleteOnClose);
00900       sqliteFree(pFile->zDeleteOnClose);
00901     }
00902 #endif
00903     OpenCounter(-1);
00904     sqliteFree(pFile);
00905     *pId = 0;
00906   }
00907   return SQLITE_OK;
00908 }
00909 
00910 /*
00911 ** Read data from a file into a buffer.  Return SQLITE_OK if all
00912 ** bytes were read successfully and SQLITE_IOERR if anything goes
00913 ** wrong.
00914 */
00915 static int winRead(OsFile *id, void *pBuf, int amt){
00916   DWORD got;
00917   assert( id!=0 );
00918   SimulateIOError(SQLITE_IOERR);
00919   TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
00920   if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
00921     got = 0;
00922   }
00923   if( got==(DWORD)amt ){
00924     return SQLITE_OK;
00925   }else{
00926     return SQLITE_IOERR;
00927   }
00928 }
00929 
00930 /*
00931 ** Write data from a buffer into a file.  Return SQLITE_OK on success
00932 ** or some other error code on failure.
00933 */
00934 static int winWrite(OsFile *id, const void *pBuf, int amt){
00935   int rc = 0;
00936   DWORD wrote;
00937   assert( id!=0 );
00938   SimulateIOError(SQLITE_IOERR);
00939   SimulateDiskfullError;
00940   TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
00941   assert( amt>0 );
00942   while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
00943          && wrote>0 ){
00944     amt -= wrote;
00945     pBuf = &((char*)pBuf)[wrote];
00946   }
00947   if( !rc || amt>(int)wrote ){
00948     return SQLITE_FULL;
00949   }
00950   return SQLITE_OK;
00951 }
00952 
00953 /*
00954 ** Some microsoft compilers lack this definition.
00955 */
00956 #ifndef INVALID_SET_FILE_POINTER
00957 # define INVALID_SET_FILE_POINTER ((DWORD)-1)
00958 #endif
00959 
00960 /*
00961 ** Move the read/write pointer in a file.
00962 */
00963 static int winSeek(OsFile *id, i64 offset){
00964   LONG upperBits = offset>>32;
00965   LONG lowerBits = offset & 0xffffffff;
00966   DWORD rc;
00967   assert( id!=0 );
00968 #ifdef SQLITE_TEST
00969   if( offset ) SimulateDiskfullError
00970 #endif
00971   SEEK(offset/1024 + 1);
00972   rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
00973   TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
00974   if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
00975     return SQLITE_FULL;
00976   }
00977   return SQLITE_OK;
00978 }
00979 
00980 /*
00981 ** Make sure all writes to a particular file are committed to disk.
00982 */
00983 static int winSync(OsFile *id, int dataOnly){
00984   assert( id!=0 );
00985   TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
00986   if( FlushFileBuffers(((winFile*)id)->h) ){
00987     return SQLITE_OK;
00988   }else{
00989     return SQLITE_IOERR;
00990   }
00991 }
00992 
00993 /*
00994 ** Sync the directory zDirname. This is a no-op on operating systems other
00995 ** than UNIX.
00996 */
00997 int sqlite3WinSyncDirectory(const char *zDirname){
00998   SimulateIOError(SQLITE_IOERR);
00999   return SQLITE_OK;
01000 }
01001 
01002 /*
01003 ** Truncate an open file to a specified size
01004 */
01005 static int winTruncate(OsFile *id, i64 nByte){
01006   LONG upperBits = nByte>>32;
01007   assert( id!=0 );
01008   TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
01009   SimulateIOError(SQLITE_IOERR);
01010   SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN);
01011   SetEndOfFile(((winFile*)id)->h);
01012   return SQLITE_OK;
01013 }
01014 
01015 /*
01016 ** Determine the current size of a file in bytes
01017 */
01018 static int winFileSize(OsFile *id, i64 *pSize){
01019   DWORD upperBits, lowerBits;
01020   assert( id!=0 );
01021   SimulateIOError(SQLITE_IOERR);
01022   lowerBits = GetFileSize(((winFile*)id)->h, &upperBits);
01023   *pSize = (((i64)upperBits)<<32) + lowerBits;
01024   return SQLITE_OK;
01025 }
01026 
01027 /*
01028 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
01029 */
01030 #ifndef LOCKFILE_FAIL_IMMEDIATELY
01031 # define LOCKFILE_FAIL_IMMEDIATELY 1
01032 #endif
01033 
01034 /*
01035 ** Acquire a reader lock.
01036 ** Different API routines are called depending on whether or not this
01037 ** is Win95 or WinNT.
01038 */
01039 static int getReadLock(winFile *id){
01040   int res;
01041   if( isNT() ){
01042     OVERLAPPED ovlp;
01043     ovlp.Offset = SHARED_FIRST;
01044     ovlp.OffsetHigh = 0;
01045     ovlp.hEvent = 0;
01046     res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp);
01047   }else{
01048     int lk;
01049     sqlite3Randomness(sizeof(lk), &lk);
01050     id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
01051     res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
01052   }
01053   return res;
01054 }
01055 
01056 /*
01057 ** Undo a readlock
01058 */
01059 static int unlockReadLock(winFile *pFile){
01060   int res;
01061   if( isNT() ){
01062     res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
01063   }else{
01064     res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
01065   }
01066   return res;
01067 }
01068 
01069 #ifndef SQLITE_OMIT_PAGER_PRAGMAS
01070 /*
01071 ** Check that a given pathname is a directory and is writable 
01072 **
01073 */
01074 int sqlite3WinIsDirWritable(char *zDirname){
01075   int fileAttr;
01076   void *zConverted;
01077   if( zDirname==0 ) return 0;
01078   if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
01079 
01080   zConverted = convertUtf8Filename(zDirname);
01081   if( zConverted==0 )
01082     return SQLITE_NOMEM;
01083   if( isNT() ){
01084     fileAttr = GetFileAttributesW((WCHAR*)zConverted);
01085   }else{
01086     fileAttr = GetFileAttributesA((char*)zConverted);
01087   }
01088   sqliteFree(zConverted);
01089   if( fileAttr == 0xffffffff ) return 0;
01090   if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
01091     return 0;
01092   }
01093   return 1;
01094 }
01095 #endif /* SQLITE_OMIT_PAGER_PRAGMAS */
01096 
01097 /*
01098 ** Lock the file with the lock specified by parameter locktype - one
01099 ** of the following:
01100 **
01101 **     (1) SHARED_LOCK
01102 **     (2) RESERVED_LOCK
01103 **     (3) PENDING_LOCK
01104 **     (4) EXCLUSIVE_LOCK
01105 **
01106 ** Sometimes when requesting one lock state, additional lock states
01107 ** are inserted in between.  The locking might fail on one of the later
01108 ** transitions leaving the lock state different from what it started but
01109 ** still short of its goal.  The following chart shows the allowed
01110 ** transitions and the inserted intermediate states:
01111 **
01112 **    UNLOCKED -> SHARED
01113 **    SHARED -> RESERVED
01114 **    SHARED -> (PENDING) -> EXCLUSIVE
01115 **    RESERVED -> (PENDING) -> EXCLUSIVE
01116 **    PENDING -> EXCLUSIVE
01117 **
01118 ** This routine will only increase a lock.  The winUnlock() routine
01119 ** erases all locks at once and returns us immediately to locking level 0.
01120 ** It is not possible to lower the locking level one step at a time.  You
01121 ** must go straight to locking level 0.
01122 */
01123 static int winLock(OsFile *id, int locktype){
01124   int rc = SQLITE_OK;    /* Return code from subroutines */
01125   int res = 1;           /* Result of a windows lock call */
01126   int newLocktype;       /* Set id->locktype to this value before exiting */
01127   int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
01128   winFile *pFile = (winFile*)id;
01129 
01130   assert( pFile!=0 );
01131   TRACE5("LOCK %d %d was %d(%d)\n",
01132           pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
01133 
01134   /* If there is already a lock of this type or more restrictive on the
01135   ** OsFile, do nothing. Don't use the end_lock: exit path, as
01136   ** sqlite3OsEnterMutex() hasn't been called yet.
01137   */
01138   if( pFile->locktype>=locktype ){
01139     return SQLITE_OK;
01140   }
01141 
01142   /* Make sure the locking sequence is correct
01143   */
01144   assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
01145   assert( locktype!=PENDING_LOCK );
01146   assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
01147 
01148   /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
01149   ** a SHARED lock.  If we are acquiring a SHARED lock, the acquisition of
01150   ** the PENDING_LOCK byte is temporary.
01151   */
01152   newLocktype = pFile->locktype;
01153   if( pFile->locktype==NO_LOCK
01154    || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
01155   ){
01156     int cnt = 3;
01157     while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
01158       /* Try 3 times to get the pending lock.  The pending lock might be
01159       ** held by another reader process who will release it momentarily.
01160       */
01161       TRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
01162       Sleep(1);
01163     }
01164     gotPendingLock = res;
01165   }
01166 
01167   /* Acquire a shared lock
01168   */
01169   if( locktype==SHARED_LOCK && res ){
01170     assert( pFile->locktype==NO_LOCK );
01171     res = getReadLock(pFile);
01172     if( res ){
01173       newLocktype = SHARED_LOCK;
01174     }
01175   }
01176 
01177   /* Acquire a RESERVED lock
01178   */
01179   if( locktype==RESERVED_LOCK && res ){
01180     assert( pFile->locktype==SHARED_LOCK );
01181     res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
01182     if( res ){
01183       newLocktype = RESERVED_LOCK;
01184     }
01185   }
01186 
01187   /* Acquire a PENDING lock
01188   */
01189   if( locktype==EXCLUSIVE_LOCK && res ){
01190     newLocktype = PENDING_LOCK;
01191     gotPendingLock = 0;
01192   }
01193 
01194   /* Acquire an EXCLUSIVE lock
01195   */
01196   if( locktype==EXCLUSIVE_LOCK && res ){
01197     assert( pFile->locktype>=SHARED_LOCK );
01198     res = unlockReadLock(pFile);
01199     TRACE2("unreadlock = %d\n", res);
01200     res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
01201     if( res ){
01202       newLocktype = EXCLUSIVE_LOCK;
01203     }else{
01204       TRACE2("error-code = %d\n", GetLastError());
01205     }
01206   }
01207 
01208   /* If we are holding a PENDING lock that ought to be released, then
01209   ** release it now.
01210   */
01211   if( gotPendingLock && locktype==SHARED_LOCK ){
01212     UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
01213   }
01214 
01215   /* Update the state of the lock has held in the file descriptor then
01216   ** return the appropriate result code.
01217   */
01218   if( res ){
01219     rc = SQLITE_OK;
01220   }else{
01221     TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
01222            locktype, newLocktype);
01223     rc = SQLITE_BUSY;
01224   }
01225   pFile->locktype = newLocktype;
01226   return rc;
01227 }
01228 
01229 /*
01230 ** This routine checks if there is a RESERVED lock held on the specified
01231 ** file by this or any other process. If such a lock is held, return
01232 ** non-zero, otherwise zero.
01233 */
01234 static int winCheckReservedLock(OsFile *id){
01235   int rc;
01236   winFile *pFile = (winFile*)id;
01237   assert( pFile!=0 );
01238   if( pFile->locktype>=RESERVED_LOCK ){
01239     rc = 1;
01240     TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
01241   }else{
01242     rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
01243     if( rc ){
01244       UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
01245     }
01246     rc = !rc;
01247     TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
01248   }
01249   return rc;
01250 }
01251 
01252 /*
01253 ** Lower the locking level on file descriptor id to locktype.  locktype
01254 ** must be either NO_LOCK or SHARED_LOCK.
01255 **
01256 ** If the locking level of the file descriptor is already at or below
01257 ** the requested locking level, this routine is a no-op.
01258 **
01259 ** It is not possible for this routine to fail if the second argument
01260 ** is NO_LOCK.  If the second argument is SHARED_LOCK then this routine
01261 ** might return SQLITE_IOERR;
01262 */
01263 static int winUnlock(OsFile *id, int locktype){
01264   int type;
01265   int rc = SQLITE_OK;
01266   winFile *pFile = (winFile*)id;
01267   assert( pFile!=0 );
01268   assert( locktype<=SHARED_LOCK );
01269   TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
01270           pFile->locktype, pFile->sharedLockByte);
01271   type = pFile->locktype;
01272   if( type>=EXCLUSIVE_LOCK ){
01273     UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
01274     if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
01275       /* This should never happen.  We should always be able to
01276       ** reacquire the read lock */
01277       rc = SQLITE_IOERR;
01278     }
01279   }
01280   if( type>=RESERVED_LOCK ){
01281     UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
01282   }
01283   if( locktype==NO_LOCK && type>=SHARED_LOCK ){
01284     unlockReadLock(pFile);
01285   }
01286   if( type>=PENDING_LOCK ){
01287     UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
01288   }
01289   pFile->locktype = locktype;
01290   return rc;
01291 }
01292 
01293 /*
01294 ** Turn a relative pathname into a full pathname.  Return a pointer
01295 ** to the full pathname stored in space obtained from sqliteMalloc().
01296 ** The calling function is responsible for freeing this space once it
01297 ** is no longer needed.
01298 */
01299 char *sqlite3WinFullPathname(const char *zRelative){
01300   char *zFull;
01301 #if defined(__CYGWIN__)
01302   int nByte;
01303   nByte = strlen(zRelative) + MAX_PATH + 1001;
01304   zFull = sqliteMalloc( nByte );
01305   if( zFull==0 ) return 0;
01306   if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
01307 #elif OS_WINCE
01308   /* WinCE has no concept of a relative pathname, or so I am told. */
01309   zFull = sqliteStrDup(zRelative);
01310 #else
01311   int nByte;
01312   void *zConverted;
01313   zConverted = convertUtf8Filename(zRelative);
01314   if( isNT() ){
01315     WCHAR *zTemp, *zNotUsedW;
01316     nByte = GetFullPathNameW((WCHAR*)zConverted, 0, 0, &zNotUsedW) + 1;
01317     zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
01318     if( zTemp==0 ){
01319       sqliteFree(zConverted);
01320       return 0;
01321     }
01322     GetFullPathNameW((WCHAR*)zConverted, nByte, zTemp, &zNotUsedW);
01323     sqliteFree(zConverted);
01324     zFull = unicodeToUtf8(zTemp);
01325     sqliteFree(zTemp);
01326   }else{
01327     char *zTemp, *zNotUsed;
01328     nByte = GetFullPathNameA((char*)zConverted, 0, 0, &zNotUsed) + 1;
01329     zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
01330     if( zTemp==0 ){
01331       sqliteFree(zConverted);
01332       return 0;
01333     }
01334     GetFullPathNameA((char*)zConverted, nByte, zTemp, &zNotUsed);
01335     sqliteFree(zConverted);
01336     zFull = mbcsToUtf8(zTemp);
01337     sqliteFree(zTemp);
01338   }
01339 #endif
01340   return zFull;
01341 }
01342 
01343 /*
01344 ** The fullSync option is meaningless on windows.   This is a no-op.
01345 */
01346 static void winSetFullSync(OsFile *id, int v){
01347   return;
01348 }
01349 
01350 /*
01351 ** Return the underlying file handle for an OsFile
01352 */
01353 static int winFileHandle(OsFile *id){
01354   return (int)((winFile*)id)->h;
01355 }
01356 
01357 /*
01358 ** Return an integer that indices the type of lock currently held
01359 ** by this handle.  (Used for testing and analysis only.)
01360 */
01361 static int winLockState(OsFile *id){
01362   return ((winFile*)id)->locktype;
01363 }
01364 
01365 /*
01366 ** This vector defines all the methods that can operate on an OsFile
01367 ** for win32.
01368 */
01369 static const IoMethod sqlite3WinIoMethod = {
01370   winClose,
01371   winOpenDirectory,
01372   winRead,
01373   winWrite,
01374   winSeek,
01375   winTruncate,
01376   winSync,
01377   winSetFullSync,
01378   winFileHandle,
01379   winFileSize,
01380   winLock,
01381   winUnlock,
01382   winLockState,
01383   winCheckReservedLock,
01384 };
01385 
01386 /*
01387 ** Allocate memory for an OsFile.  Initialize the new OsFile
01388 ** to the value given in pInit and return a pointer to the new
01389 ** OsFile.  If we run out of memory, close the file and return NULL.
01390 */
01391 static int allocateWinFile(winFile *pInit, OsFile **pId){
01392   winFile *pNew;
01393   pNew = sqliteMalloc( sizeof(*pNew) );
01394   if( pNew==0 ){
01395     CloseHandle(pInit->h);
01396 #if OS_WINCE
01397     sqliteFree(pInit->zDeleteOnClose);
01398 #endif
01399     *pId = 0;
01400     return SQLITE_NOMEM;
01401   }else{
01402     *pNew = *pInit;
01403     pNew->pMethod = &sqlite3WinIoMethod;
01404     pNew->locktype = NO_LOCK;
01405     pNew->sharedLockByte = 0;
01406     *pId = (OsFile*)pNew;
01407     OpenCounter(+1);
01408     return SQLITE_OK;
01409   }
01410 }
01411 
01412 
01413 #endif /* SQLITE_OMIT_DISKIO */
01414 /***************************************************************************
01415 ** Everything above deals with file I/O.  Everything that follows deals
01416 ** with other miscellanous aspects of the operating system interface
01417 ****************************************************************************/
01418 
01419 /*
01420 ** Get information to seed the random number generator.  The seed
01421 ** is written into the buffer zBuf[256].  The calling function must
01422 ** supply a sufficiently large buffer.
01423 */
01424 int sqlite3WinRandomSeed(char *zBuf){
01425   /* We have to initialize zBuf to prevent valgrind from reporting
01426   ** errors.  The reports issued by valgrind are incorrect - we would
01427   ** prefer that the randomness be increased by making use of the
01428   ** uninitialized space in zBuf - but valgrind errors tend to worry
01429   ** some users.  Rather than argue, it seems easier just to initialize
01430   ** the whole array and silence valgrind, even if that means less randomness
01431   ** in the random seed.
01432   **
01433   ** When testing, initializing zBuf[] to zero is all we do.  That means
01434   ** that we always use the same random number sequence.* This makes the
01435   ** tests repeatable.
01436   */
01437   memset(zBuf, 0, 256);
01438   GetSystemTime((LPSYSTEMTIME)zBuf);
01439   return SQLITE_OK;
01440 }
01441 
01442 /*
01443 ** Sleep for a little while.  Return the amount of time slept.
01444 */
01445 int sqlite3WinSleep(int ms){
01446   Sleep(ms);
01447   return ms;
01448 }
01449 
01450 /*
01451 ** Static variables used for thread synchronization
01452 */
01453 static int inMutex = 0;
01454 #ifdef SQLITE_W32_THREADS
01455   static DWORD mutexOwner;
01456   static CRITICAL_SECTION cs;
01457 #endif
01458 
01459 /*
01460 ** The following pair of routines implement mutual exclusion for
01461 ** multi-threaded processes.  Only a single thread is allowed to
01462 ** executed code that is surrounded by EnterMutex() and LeaveMutex().
01463 **
01464 ** SQLite uses only a single Mutex.  There is not much critical
01465 ** code and what little there is executes quickly and without blocking.
01466 **
01467 ** Version 3.3.1 and earlier used a simple mutex.  Beginning with
01468 ** version 3.3.2, a recursive mutex is required.
01469 */
01470 void sqlite3WinEnterMutex(){
01471 #ifdef SQLITE_W32_THREADS
01472   static int isInit = 0;
01473   while( !isInit ){
01474     static long lock = 0;
01475     if( InterlockedIncrement(&lock)==1 ){
01476       InitializeCriticalSection(&cs);
01477       isInit = 1;
01478     }else{
01479       Sleep(1);
01480     }
01481   }
01482   EnterCriticalSection(&cs);
01483   mutexOwner = GetCurrentThreadId();
01484 #endif
01485   inMutex++;
01486 }
01487 void sqlite3WinLeaveMutex(){
01488   assert( inMutex );
01489   inMutex--;
01490 #ifdef SQLITE_W32_THREADS
01491   assert( mutexOwner==GetCurrentThreadId() );
01492   LeaveCriticalSection(&cs);
01493 #endif
01494 }
01495 
01496 /*
01497 ** Return TRUE if the mutex is currently held.
01498 **
01499 ** If the thisThreadOnly parameter is true, return true if and only if the
01500 ** calling thread holds the mutex.  If the parameter is false, return
01501 ** true if any thread holds the mutex.
01502 */
01503 int sqlite3WinInMutex(int thisThreadOnly){
01504 #ifdef SQLITE_W32_THREADS
01505   return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId());
01506 #else
01507   return inMutex>0;
01508 #endif
01509 }
01510 
01511 
01512 /*
01513 ** The following variable, if set to a non-zero value, becomes the result
01514 ** returned from sqlite3OsCurrentTime().  This is used for testing.
01515 */
01516 #ifdef SQLITE_TEST
01517 int sqlite3_current_time = 0;
01518 #endif
01519 
01520 /*
01521 ** Find the current time (in Universal Coordinated Time).  Write the
01522 ** current time and date as a Julian Day number into *prNow and
01523 ** return 0.  Return 1 if the time and date cannot be found.
01524 */
01525 int sqlite3WinCurrentTime(double *prNow){
01526   FILETIME ft;
01527   /* FILETIME structure is a 64-bit value representing the number of 
01528      100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 
01529   */
01530   double now;
01531 #if OS_WINCE
01532   SYSTEMTIME time;
01533   GetSystemTime(&time);
01534   SystemTimeToFileTime(&time,&ft);
01535 #else
01536   GetSystemTimeAsFileTime( &ft );
01537 #endif
01538   now = ((double)ft.dwHighDateTime) * 4294967296.0; 
01539   *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
01540 #ifdef SQLITE_TEST
01541   if( sqlite3_current_time ){
01542     *prNow = sqlite3_current_time/86400.0 + 2440587.5;
01543   }
01544 #endif
01545   return 0;
01546 }
01547 
01548 /*
01549 ** Remember the number of thread-specific-data blocks allocated.
01550 ** Use this to verify that we are not leaking thread-specific-data.
01551 ** Ticket #1601
01552 */
01553 #ifdef SQLITE_TEST
01554 int sqlite3_tsd_count = 0;
01555 # define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
01556 # define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
01557 #else
01558 # define TSD_COUNTER_INCR  /* no-op */
01559 # define TSD_COUNTER_DECR  /* no-op */
01560 #endif
01561 
01562 
01563 
01564 /*
01565 ** If called with allocateFlag>1, then return a pointer to thread
01566 ** specific data for the current thread.  Allocate and zero the
01567 ** thread-specific data if it does not already exist necessary.
01568 **
01569 ** If called with allocateFlag==0, then check the current thread
01570 ** specific data.  Return it if it exists.  If it does not exist,
01571 ** then return NULL.
01572 **
01573 ** If called with allocateFlag<0, check to see if the thread specific
01574 ** data is allocated and is all zero.  If it is then deallocate it.
01575 ** Return a pointer to the thread specific data or NULL if it is
01576 ** unallocated or gets deallocated.
01577 */
01578 ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
01579   static int key;
01580   static int keyInit = 0;
01581   static const ThreadData zeroData = {0};
01582   ThreadData *pTsd;
01583 
01584   if( !keyInit ){
01585     sqlite3OsEnterMutex();
01586     if( !keyInit ){
01587       key = TlsAlloc();
01588       if( key==0xffffffff ){
01589         sqlite3OsLeaveMutex();
01590         return 0;
01591       }
01592       keyInit = 1;
01593     }
01594     sqlite3OsLeaveMutex();
01595   }
01596   pTsd = TlsGetValue(key);
01597   if( allocateFlag>0 ){
01598     if( !pTsd ){
01599       pTsd = sqlite3OsMalloc( sizeof(zeroData) );
01600       if( pTsd ){
01601         *pTsd = zeroData;
01602         TlsSetValue(key, pTsd);
01603         TSD_COUNTER_INCR;
01604       }
01605     }
01606   }else if( pTsd!=0 && allocateFlag<0 
01607               && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){
01608     sqlite3OsFree(pTsd);
01609     TlsSetValue(key, 0);
01610     TSD_COUNTER_DECR;
01611     pTsd = 0;
01612   }
01613   return pTsd;
01614 }
01615 #endif /* OS_WIN */