1 /* 2 ** 2004 May 22 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ****************************************************************************** 12 ** 13 ** This file contains code that is specific to windows. 14 */ 15 #include "os.h" /* Must be first to enable large file support */ 16 #if OS_WIN /* This file is used for windows only */ 17 #include "sqliteInt.h" 18 19 #include <winbase.h> 20 21 /* 22 ** Macros used to determine whether or not to use threads. 23 */ 24 #if defined(THREADSAFE) && THREADSAFE 25 # define SQLITE_W32_THREADS 1 26 #endif 27 28 /* 29 ** Include code that is common to all os_*.c files 30 */ 31 #include "os_common.h" 32 33 /* 34 ** Delete the named file 35 */ 36 int sqlite3OsDelete(const char *zFilename){ 37 DeleteFile(zFilename); 38 TRACE2("DELETE \"%s\"\n", zFilename); 39 return SQLITE_OK; 40 } 41 42 /* 43 ** Return TRUE if the named file exists. 44 */ 45 int sqlite3OsFileExists(const char *zFilename){ 46 return GetFileAttributes(zFilename) != 0xffffffff; 47 } 48 49 /* 50 ** Attempt to open a file for both reading and writing. If that 51 ** fails, try opening it read-only. If the file does not exist, 52 ** try to create it. 53 ** 54 ** On success, a handle for the open file is written to *id 55 ** and *pReadonly is set to 0 if the file was opened for reading and 56 ** writing or 1 if the file was opened read-only. The function returns 57 ** SQLITE_OK. 58 ** 59 ** On failure, the function returns SQLITE_CANTOPEN and leaves 60 ** *id and *pReadonly unchanged. 61 */ 62 int sqlite3OsOpenReadWrite( 63 const char *zFilename, 64 OsFile *id, 65 int *pReadonly 66 ){ 67 HANDLE h = CreateFile(zFilename, 68 GENERIC_READ | GENERIC_WRITE, 69 FILE_SHARE_READ | FILE_SHARE_WRITE, 70 NULL, 71 OPEN_ALWAYS, 72 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 73 NULL 74 ); 75 if( h==INVALID_HANDLE_VALUE ){ 76 h = CreateFile(zFilename, 77 GENERIC_READ, 78 FILE_SHARE_READ, 79 NULL, 80 OPEN_ALWAYS, 81 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 82 NULL 83 ); 84 if( h==INVALID_HANDLE_VALUE ){ 85 return SQLITE_CANTOPEN; 86 } 87 *pReadonly = 1; 88 }else{ 89 *pReadonly = 0; 90 } 91 id->h = h; 92 id->locktype = NO_LOCK; 93 id->sharedLockByte = 0; 94 OpenCounter(+1); 95 TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename); 96 return SQLITE_OK; 97 } 98 99 100 /* 101 ** Attempt to open a new file for exclusive access by this process. 102 ** The file will be opened for both reading and writing. To avoid 103 ** a potential security problem, we do not allow the file to have 104 ** previously existed. Nor do we allow the file to be a symbolic 105 ** link. 106 ** 107 ** If delFlag is true, then make arrangements to automatically delete 108 ** the file when it is closed. 109 ** 110 ** On success, write the file handle into *id and return SQLITE_OK. 111 ** 112 ** On failure, return SQLITE_CANTOPEN. 113 */ 114 int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){ 115 HANDLE h; 116 int fileflags; 117 if( delFlag ){ 118 fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS 119 | FILE_FLAG_DELETE_ON_CLOSE; 120 }else{ 121 fileflags = FILE_FLAG_RANDOM_ACCESS; 122 } 123 h = CreateFile(zFilename, 124 GENERIC_READ | GENERIC_WRITE, 125 0, 126 NULL, 127 CREATE_ALWAYS, 128 fileflags, 129 NULL 130 ); 131 if( h==INVALID_HANDLE_VALUE ){ 132 return SQLITE_CANTOPEN; 133 } 134 id->h = h; 135 id->locktype = NO_LOCK; 136 id->sharedLockByte = 0; 137 OpenCounter(+1); 138 TRACE3("OPEN EX %d \"%s\"\n", h, zFilename); 139 return SQLITE_OK; 140 } 141 142 /* 143 ** Attempt to open a new file for read-only access. 144 ** 145 ** On success, write the file handle into *id and return SQLITE_OK. 146 ** 147 ** On failure, return SQLITE_CANTOPEN. 148 */ 149 int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){ 150 HANDLE h = CreateFile(zFilename, 151 GENERIC_READ, 152 0, 153 NULL, 154 OPEN_EXISTING, 155 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, 156 NULL 157 ); 158 if( h==INVALID_HANDLE_VALUE ){ 159 return SQLITE_CANTOPEN; 160 } 161 id->h = h; 162 id->locktype = NO_LOCK; 163 id->sharedLockByte = 0; 164 OpenCounter(+1); 165 TRACE3("OPEN RO %d \"%s\"\n", h, zFilename); 166 return SQLITE_OK; 167 } 168 169 /* 170 ** Attempt to open a file descriptor for the directory that contains a 171 ** file. This file descriptor can be used to fsync() the directory 172 ** in order to make sure the creation of a new file is actually written 173 ** to disk. 174 ** 175 ** This routine is only meaningful for Unix. It is a no-op under 176 ** windows since windows does not support hard links. 177 ** 178 ** On success, a handle for a previously open file is at *id is 179 ** updated with the new directory file descriptor and SQLITE_OK is 180 ** returned. 181 ** 182 ** On failure, the function returns SQLITE_CANTOPEN and leaves 183 ** *id unchanged. 184 */ 185 int sqlite3OsOpenDirectory( 186 const char *zDirname, 187 OsFile *id 188 ){ 189 return SQLITE_OK; 190 } 191 192 /* 193 ** Create a temporary file name in zBuf. zBuf must be big enough to 194 ** hold at least SQLITE_TEMPNAME_SIZE characters. 195 */ 196 int sqlite3OsTempFileName(char *zBuf){ 197 static char zChars[] = 198 "abcdefghijklmnopqrstuvwxyz" 199 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 200 "0123456789"; 201 int i, j; 202 char zTempPath[SQLITE_TEMPNAME_SIZE]; 203 GetTempPath(SQLITE_TEMPNAME_SIZE-30, zTempPath); 204 for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){} 205 zTempPath[i] = 0; 206 for(;;){ 207 sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath); 208 j = strlen(zBuf); 209 sqlite3Randomness(15, &zBuf[j]); 210 for(i=0; i<15; i++, j++){ 211 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; 212 } 213 zBuf[j] = 0; 214 if( !sqlite3OsFileExists(zBuf) ) break; 215 } 216 TRACE2("TEMP FILENAME: %s\n", zBuf); 217 return SQLITE_OK; 218 } 219 220 /* 221 ** Close a file. 222 */ 223 int sqlite3OsClose(OsFile *id){ 224 TRACE2("CLOSE %d\n", id->h); 225 CloseHandle(id->h); 226 OpenCounter(-1); 227 return SQLITE_OK; 228 } 229 230 /* 231 ** Read data from a file into a buffer. Return SQLITE_OK if all 232 ** bytes were read successfully and SQLITE_IOERR if anything goes 233 ** wrong. 234 */ 235 int sqlite3OsRead(OsFile *id, void *pBuf, int amt){ 236 DWORD got; 237 SimulateIOError(SQLITE_IOERR); 238 TRACE3("READ %d lock=%d\n", id->h, id->locktype); 239 if( !ReadFile(id->h, pBuf, amt, &got, 0) ){ 240 got = 0; 241 } 242 if( got==(DWORD)amt ){ 243 return SQLITE_OK; 244 }else{ 245 return SQLITE_IOERR; 246 } 247 } 248 249 /* 250 ** Write data from a buffer into a file. Return SQLITE_OK on success 251 ** or some other error code on failure. 252 */ 253 int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){ 254 int rc; 255 DWORD wrote; 256 SimulateIOError(SQLITE_IOERR); 257 TRACE3("WRITE %d lock=%d\n", id->h, id->locktype); 258 while( amt>0 && (rc = WriteFile(id->h, pBuf, amt, &wrote, 0))!=0 && wrote>0 ){ 259 amt -= wrote; 260 pBuf = &((char*)pBuf)[wrote]; 261 } 262 if( !rc || amt>(int)wrote ){ 263 return SQLITE_FULL; 264 } 265 return SQLITE_OK; 266 } 267 268 /* 269 ** Move the read/write pointer in a file. 270 */ 271 int sqlite3OsSeek(OsFile *id, off_t offset){ 272 LONG upperBits = offset>>32; 273 LONG lowerBits = offset & 0xffffffff; 274 DWORD rc; 275 SEEK(offset/1024 + 1); 276 rc = SetFilePointer(id->h, lowerBits, &upperBits, FILE_BEGIN); 277 TRACE3("SEEK %d %lld\n", id->h, offset); 278 return SQLITE_OK; 279 } 280 281 /* 282 ** Make sure all writes to a particular file are committed to disk. 283 */ 284 int sqlite3OsSync(OsFile *id){ 285 TRACE3("SYNC %d lock=%d\n", id->h, id->locktype); 286 if( FlushFileBuffers(id->h) ){ 287 return SQLITE_OK; 288 }else{ 289 return SQLITE_IOERR; 290 } 291 } 292 293 /* 294 ** Truncate an open file to a specified size 295 */ 296 int sqlite3OsTruncate(OsFile *id, off_t nByte){ 297 LONG upperBits = nByte>>32; 298 TRACE3("TRUNCATE %d %lld\n", id->h, nByte); 299 SimulateIOError(SQLITE_IOERR); 300 SetFilePointer(id->h, nByte, &upperBits, FILE_BEGIN); 301 SetEndOfFile(id->h); 302 return SQLITE_OK; 303 } 304 305 /* 306 ** Determine the current size of a file in bytes 307 */ 308 int sqlite3OsFileSize(OsFile *id, off_t *pSize){ 309 DWORD upperBits, lowerBits; 310 SimulateIOError(SQLITE_IOERR); 311 lowerBits = GetFileSize(id->h, &upperBits); 312 *pSize = (((off_t)upperBits)<<32) + lowerBits; 313 return SQLITE_OK; 314 } 315 316 /* 317 ** Return true (non-zero) if we are running under WinNT, Win2K or WinXP. 318 ** Return false (zero) for Win95, Win98, or WinME. 319 ** 320 ** Here is an interesting observation: Win95, Win98, and WinME lack 321 ** the LockFileEx() API. But we can still statically link against that 322 ** API as long as we don't call it win running Win95/98/ME. A call to 323 ** this routine is used to determine if the host is Win95/98/ME or 324 ** WinNT/2K/XP so that we will know whether or not we can safely call 325 ** the LockFileEx() API. 326 */ 327 static int isNT(void){ 328 static int osType = 0; /* 0=unknown 1=win95 2=winNT */ 329 if( osType==0 ){ 330 OSVERSIONINFO sInfo; 331 sInfo.dwOSVersionInfoSize = sizeof(sInfo); 332 GetVersionEx(&sInfo); 333 osType = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1; 334 } 335 return osType==2; 336 } 337 338 /* 339 ** Acquire a reader lock on the range of bytes from iByte...iByte+nByte-1. 340 ** Different API routines are called depending on whether or not this 341 ** is Win95 or WinNT. 342 */ 343 static int getReadLock(HANDLE h, unsigned int iByte, unsigned int nByte){ 344 int res; 345 if( isNT() ){ 346 OVERLAPPED ovlp; 347 ovlp.Offset = iByte; 348 ovlp.OffsetHigh = 0; 349 ovlp.hEvent = 0; 350 res = LockFileEx(h, LOCKFILE_FAIL_IMMEDIATELY, 0, nByte, 0, &ovlp); 351 }else{ 352 res = LockFile(h, iByte, 0, nByte, 0); 353 } 354 return res; 355 } 356 357 /* 358 ** Undo a readlock 359 */ 360 static int unlockReadLock(OsFile *id){ 361 int res; 362 if( isNT() ){ 363 res = UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 364 }else{ 365 res = UnlockFile(id->h, SHARED_FIRST + id->sharedLockByte, 0, 1, 0); 366 } 367 return res; 368 } 369 370 /* 371 ** Lock the file with the lock specified by parameter locktype - one 372 ** of the following: 373 ** 374 ** (1) SHARED_LOCK 375 ** (2) RESERVED_LOCK 376 ** (3) PENDING_LOCK 377 ** (4) EXCLUSIVE_LOCK 378 ** 379 ** Sometimes when requesting one lock state, additional lock states 380 ** are inserted in between. The locking might fail on one of the later 381 ** transitions leaving the lock state different from what it started but 382 ** still short of its goal. The following chart shows the allowed 383 ** transitions and the inserted intermediate states: 384 ** 385 ** UNLOCKED -> SHARED 386 ** SHARED -> RESERVED 387 ** SHARED -> (PENDING) -> EXCLUSIVE 388 ** RESERVED -> (PENDING) -> EXCLUSIVE 389 ** PENDING -> EXCLUSIVE 390 ** 391 ** This routine will only increase a lock. The sqlite3OsUnlock() routine 392 ** erases all locks at once and returns us immediately to locking level 0. 393 ** It is not possible to lower the locking level one step at a time. You 394 ** must go straight to locking level 0. 395 */ 396 int sqlite3OsLock(OsFile *id, int locktype){ 397 int rc = SQLITE_OK; /* Return code from subroutines */ 398 int res = 1; /* Result of a windows lock call */ 399 int newLocktype; /* Set id->locktype to this value before exiting */ 400 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ 401 402 TRACE5("LOCK %d %d was %d(%d)\n", 403 id->h, locktype, id->locktype, id->sharedLockByte); 404 405 /* If there is already a lock of this type or more restrictive on the 406 ** OsFile, do nothing. Don't use the end_lock: exit path, as 407 ** sqlite3OsEnterMutex() hasn't been called yet. 408 */ 409 if( id->locktype>=locktype ){ 410 return SQLITE_OK; 411 } 412 413 /* Make sure the locking sequence is correct 414 */ 415 assert( id->locktype!=NO_LOCK || locktype==SHARED_LOCK ); 416 assert( locktype!=PENDING_LOCK ); 417 assert( locktype!=RESERVED_LOCK || id->locktype==SHARED_LOCK ); 418 419 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or 420 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of 421 ** the PENDING_LOCK byte is temporary. 422 */ 423 if( id->locktype==NO_LOCK 424 || (locktype==EXCLUSIVE_LOCK && id->locktype==RESERVED_LOCK) 425 ){ 426 int cnt = 3; 427 while( cnt-->0 && (res = LockFile(id->h, PENDING_BYTE, 0, 1, 0))==0 ){ 428 /* Try 3 times to get the pending lock. The pending lock might be 429 ** held by another reader process who will release it momentarily. 430 */ 431 TRACE2("could not get a PENDING lock. cnt=%d\n", cnt); 432 Sleep(1); 433 } 434 gotPendingLock = res; 435 } 436 437 /* Acquire a shared lock 438 */ 439 if( locktype==SHARED_LOCK && res ){ 440 assert( id->locktype==NO_LOCK ); 441 if( isNT() ){ 442 res = getReadLock(id->h, SHARED_FIRST, SHARED_SIZE); 443 }else{ 444 int lk; 445 sqlite3Randomness(sizeof(lk), &lk); 446 id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1); 447 res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0); 448 } 449 if( res ){ 450 newLocktype = SHARED_LOCK; 451 } 452 } 453 454 /* Acquire a RESERVED lock 455 */ 456 if( locktype==RESERVED_LOCK && res ){ 457 assert( id->locktype==SHARED_LOCK ); 458 res = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); 459 if( res ){ 460 newLocktype = RESERVED_LOCK; 461 } 462 } 463 464 /* Acquire a PENDING lock 465 */ 466 if( locktype==EXCLUSIVE_LOCK && res ){ 467 newLocktype = PENDING_LOCK; 468 gotPendingLock = 0; 469 } 470 471 /* Acquire an EXCLUSIVE lock 472 */ 473 if( locktype==EXCLUSIVE_LOCK && res ){ 474 assert( id->locktype>=SHARED_LOCK ); 475 res = unlockReadLock(id); 476 TRACE2("unreadlock = %d\n", res); 477 res = LockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 478 if( res ){ 479 newLocktype = EXCLUSIVE_LOCK; 480 }else{ 481 TRACE2("error-code = %d\n", GetLastError()); 482 } 483 } 484 485 /* If we are holding a PENDING lock that ought to be released, then 486 ** release it now. 487 */ 488 if( gotPendingLock && locktype==SHARED_LOCK ){ 489 UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); 490 } 491 492 /* Update the state of the lock has held in the file descriptor then 493 ** return the appropriate result code. 494 */ 495 if( res ){ 496 rc = SQLITE_OK; 497 }else{ 498 TRACE4("LOCK FAILED %d trying for %d but got %d\n", id->h, 499 locktype, newLocktype); 500 rc = SQLITE_BUSY; 501 } 502 id->locktype = newLocktype; 503 return rc; 504 } 505 506 /* 507 ** This routine checks if there is a RESERVED lock held on the specified 508 ** file by this or any other process. If such a lock is held, return 509 ** non-zero, otherwise zero. 510 */ 511 int sqlite3OsCheckReservedLock(OsFile *id){ 512 int rc; 513 if( id->locktype>=RESERVED_LOCK ){ 514 rc = 1; 515 TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc); 516 }else{ 517 rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0); 518 if( rc ){ 519 UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); 520 } 521 rc = !rc; 522 TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc); 523 } 524 return rc; 525 } 526 527 /* 528 ** Lower the locking level on file descriptor id to locktype. locktype 529 ** must be either NO_LOCK or SHARED_LOCK. 530 ** 531 ** If the locking level of the file descriptor is already at or below 532 ** the requested locking level, this routine is a no-op. 533 ** 534 ** It is not possible for this routine to fail. 535 */ 536 int sqlite3OsUnlock(OsFile *id, int locktype){ 537 int rc, type; 538 assert( locktype<=SHARED_LOCK ); 539 TRACE4("UNLOCK %d to %d was %d(%d)\n", id->h, locktype, 540 id->locktype, id->sharedLockByte); 541 type = id->locktype; 542 if( type>=EXCLUSIVE_LOCK ){ 543 UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0); 544 } 545 if( type>=RESERVED_LOCK ){ 546 UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0); 547 } 548 if( locktype==NO_LOCK && type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){ 549 unlockReadLock(id); 550 } 551 if( type>=PENDING_LOCK ){ 552 UnlockFile(id->h, PENDING_BYTE, 0, 1, 0); 553 } 554 id->locktype = locktype; 555 return SQLITE_OK; 556 } 557 558 /* 559 ** Get information to seed the random number generator. The seed 560 ** is written into the buffer zBuf[256]. The calling function must 561 ** supply a sufficiently large buffer. 562 */ 563 int sqlite3OsRandomSeed(char *zBuf){ 564 /* We have to initialize zBuf to prevent valgrind from reporting 565 ** errors. The reports issued by valgrind are incorrect - we would 566 ** prefer that the randomness be increased by making use of the 567 ** uninitialized space in zBuf - but valgrind errors tend to worry 568 ** some users. Rather than argue, it seems easier just to initialize 569 ** the whole array and silence valgrind, even if that means less randomness 570 ** in the random seed. 571 ** 572 ** When testing, initializing zBuf[] to zero is all we do. That means 573 ** that we always use the same random number sequence.* This makes the 574 ** tests repeatable. 575 */ 576 memset(zBuf, 0, 256); 577 GetSystemTime((LPSYSTEMTIME)zBuf); 578 return SQLITE_OK; 579 } 580 581 /* 582 ** Sleep for a little while. Return the amount of time slept. 583 */ 584 int sqlite3OsSleep(int ms){ 585 Sleep(ms); 586 return ms; 587 } 588 589 /* 590 ** Static variables used for thread synchronization 591 */ 592 static int inMutex = 0; 593 #ifdef SQLITE_W32_THREADS 594 static CRITICAL_SECTION cs; 595 #endif 596 597 /* 598 ** The following pair of routine implement mutual exclusion for 599 ** multi-threaded processes. Only a single thread is allowed to 600 ** executed code that is surrounded by EnterMutex() and LeaveMutex(). 601 ** 602 ** SQLite uses only a single Mutex. There is not much critical 603 ** code and what little there is executes quickly and without blocking. 604 */ 605 void sqlite3OsEnterMutex(){ 606 #ifdef SQLITE_W32_THREADS 607 static int isInit = 0; 608 while( !isInit ){ 609 static long lock = 0; 610 if( InterlockedIncrement(&lock)==1 ){ 611 InitializeCriticalSection(&cs); 612 isInit = 1; 613 }else{ 614 Sleep(1); 615 } 616 } 617 EnterCriticalSection(&cs); 618 #endif 619 assert( !inMutex ); 620 inMutex = 1; 621 } 622 void sqlite3OsLeaveMutex(){ 623 assert( inMutex ); 624 inMutex = 0; 625 #ifdef SQLITE_W32_THREADS 626 LeaveCriticalSection(&cs); 627 #endif 628 } 629 630 /* 631 ** Turn a relative pathname into a full pathname. Return a pointer 632 ** to the full pathname stored in space obtained from sqliteMalloc(). 633 ** The calling function is responsible for freeing this space once it 634 ** is no longer needed. 635 */ 636 char *sqlite3OsFullPathname(const char *zRelative){ 637 char *zNotUsed; 638 char *zFull; 639 int nByte; 640 nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1; 641 zFull = sqliteMalloc( nByte ); 642 if( zFull==0 ) return 0; 643 GetFullPathName(zRelative, nByte, zFull, &zNotUsed); 644 return zFull; 645 } 646 647 /* 648 ** The following variable, if set to a non-zero value, becomes the result 649 ** returned from sqlite3OsCurrentTime(). This is used for testing. 650 */ 651 #ifdef SQLITE_TEST 652 int sqlite3_current_time = 0; 653 #endif 654 655 /* 656 ** Find the current time (in Universal Coordinated Time). Write the 657 ** current time and date as a Julian Day number into *prNow and 658 ** return 0. Return 1 if the time and date cannot be found. 659 */ 660 int sqlite3OsCurrentTime(double *prNow){ 661 FILETIME ft; 662 /* FILETIME structure is a 64-bit value representing the number of 663 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). 664 */ 665 double now; 666 GetSystemTimeAsFileTime( &ft ); 667 now = ((double)ft.dwHighDateTime) * 4294967296.0; 668 *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5; 669 #ifdef SQLITE_TEST 670 if( sqlite3_current_time ){ 671 *prNow = sqlite3_current_time/86400.0 + 2440587.5; 672 } 673 #endif 674 return 0; 675 } 676 677 #endif /* OS_WIN */ 678