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