1: /*
2: ** 2004 May 22
3: **
4: ** The author disclaims copyright to this source code. In place of
5: ** a legal notice, here is a blessing:
6: **
7: ** May you do good and not evil.
8: ** May you find forgiveness for yourself and forgive others.
9: ** May you share freely, never taking more than you give.
10: **
11: ******************************************************************************
12: **
13: ** This file contains code that is specific to Windows.
14: */
15: #include "sqliteInt.h"
16: #if SQLITE_OS_WIN /* This file is used for Windows only */
17:
18: #ifdef __CYGWIN__
19: # include <sys/cygwin.h>
20: #endif
21:
22: /*
23: ** Include code that is common to all os_*.c files
24: */
25: #include "os_common.h"
26:
27: /*
28: ** Some Microsoft compilers lack this definition.
29: */
30: #ifndef INVALID_FILE_ATTRIBUTES
31: # define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
32: #endif
33:
34: /* Forward references */
35: typedef struct winShm winShm; /* A connection to shared-memory */
36: typedef struct winShmNode winShmNode; /* A region of shared-memory */
37:
38: /*
39: ** WinCE lacks native support for file locking so we have to fake it
40: ** with some code of our own.
41: */
42: #if SQLITE_OS_WINCE
43: typedef struct winceLock {
44: int nReaders; /* Number of reader locks obtained */
45: BOOL bPending; /* Indicates a pending lock has been obtained */
46: BOOL bReserved; /* Indicates a reserved lock has been obtained */
47: BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
48: } winceLock;
49: #endif
50:
51: /*
52: ** The winFile structure is a subclass of sqlite3_file* specific to the win32
53: ** portability layer.
54: */
55: typedef struct winFile winFile;
56: struct winFile {
57: const sqlite3_io_methods *pMethod; /*** Must be first ***/
58: sqlite3_vfs *pVfs; /* The VFS used to open this file */
59: HANDLE h; /* Handle for accessing the file */
60: u8 locktype; /* Type of lock currently held on this file */
61: short sharedLockByte; /* Randomly chosen byte used as a shared lock */
62: u8 ctrlFlags; /* Flags. See WINFILE_* below */
63: DWORD lastErrno; /* The Windows errno from the last I/O error */
64: winShm *pShm; /* Instance of shared memory on this file */
65: const char *zPath; /* Full pathname of this file */
66: int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
67: #if SQLITE_OS_WINCE
68: LPWSTR zDeleteOnClose; /* Name of file to delete when closing */
69: HANDLE hMutex; /* Mutex used to control access to shared lock */
70: HANDLE hShared; /* Shared memory segment used for locking */
71: winceLock local; /* Locks obtained by this instance of winFile */
72: winceLock *shared; /* Global shared lock memory for the file */
73: #endif
74: };
75:
76: /*
77: ** Allowed values for winFile.ctrlFlags
78: */
79: #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */
80: #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */
81:
82: /*
83: * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
84: * various Win32 API heap functions instead of our own.
85: */
86: #ifdef SQLITE_WIN32_MALLOC
87: /*
88: * The initial size of the Win32-specific heap. This value may be zero.
89: */
90: #ifndef SQLITE_WIN32_HEAP_INIT_SIZE
91: # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \
92: (SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
93: #endif
94:
95: /*
96: * The maximum size of the Win32-specific heap. This value may be zero.
97: */
98: #ifndef SQLITE_WIN32_HEAP_MAX_SIZE
99: # define SQLITE_WIN32_HEAP_MAX_SIZE (0)
100: #endif
101:
102: /*
103: * The extra flags to use in calls to the Win32 heap APIs. This value may be
104: * zero for the default behavior.
105: */
106: #ifndef SQLITE_WIN32_HEAP_FLAGS
107: # define SQLITE_WIN32_HEAP_FLAGS (0)
108: #endif
109:
110: /*
111: ** The winMemData structure stores information required by the Win32-specific
112: ** sqlite3_mem_methods implementation.
113: */
114: typedef struct winMemData winMemData;
115: struct winMemData {
116: #ifndef NDEBUG
117: u32 magic; /* Magic number to detect structure corruption. */
118: #endif
119: HANDLE hHeap; /* The handle to our heap. */
120: BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */
121: };
122:
123: #ifndef NDEBUG
124: #define WINMEM_MAGIC 0x42b2830b
125: #endif
126:
127: static struct winMemData win_mem_data = {
128: #ifndef NDEBUG
129: WINMEM_MAGIC,
130: #endif
131: NULL, FALSE
132: };
133:
134: #ifndef NDEBUG
135: #define winMemAssertMagic() assert( win_mem_data.magic==WINMEM_MAGIC )
136: #else
137: #define winMemAssertMagic()
138: #endif
139:
140: #define winMemGetHeap() win_mem_data.hHeap
141:
142: static void *winMemMalloc(int nBytes);
143: static void winMemFree(void *pPrior);
144: static void *winMemRealloc(void *pPrior, int nBytes);
145: static int winMemSize(void *p);
146: static int winMemRoundup(int n);
147: static int winMemInit(void *pAppData);
148: static void winMemShutdown(void *pAppData);
149:
150: const sqlite3_mem_methods *sqlite3MemGetWin32(void);
151: #endif /* SQLITE_WIN32_MALLOC */
152:
153: /*
154: ** The following variable is (normally) set once and never changes
155: ** thereafter. It records whether the operating system is Win9x
156: ** or WinNT.
157: **
158: ** 0: Operating system unknown.
159: ** 1: Operating system is Win9x.
160: ** 2: Operating system is WinNT.
161: **
162: ** In order to facilitate testing on a WinNT system, the test fixture
163: ** can manually set this value to 1 to emulate Win98 behavior.
164: */
165: #ifdef SQLITE_TEST
166: int sqlite3_os_type = 0;
167: #else
168: static int sqlite3_os_type = 0;
169: #endif
170:
171: /*
172: ** Many system calls are accessed through pointer-to-functions so that
173: ** they may be overridden at runtime to facilitate fault injection during
174: ** testing and sandboxing. The following array holds the names and pointers
175: ** to all overrideable system calls.
176: */
177: #if !SQLITE_OS_WINCE
178: # define SQLITE_WIN32_HAS_ANSI
179: #endif
180:
181: #if SQLITE_OS_WINCE || SQLITE_OS_WINNT
182: # define SQLITE_WIN32_HAS_WIDE
183: #endif
184:
185: #ifndef SYSCALL
186: # define SYSCALL sqlite3_syscall_ptr
187: #endif
188:
189: #if SQLITE_OS_WINCE
190: /*
191: ** These macros are necessary because Windows CE does not natively support the
192: ** Win32 APIs LockFile, UnlockFile, and LockFileEx.
193: */
194:
195: # define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
196: # define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
197: # define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
198:
199: /*
200: ** These are the special syscall hacks for Windows CE. The locking related
201: ** defines here refer to the macros defined just above.
202: */
203:
204: # define osAreFileApisANSI() 1
205: # define osLockFile LockFile
206: # define osUnlockFile UnlockFile
207: # define osLockFileEx LockFileEx
208: #endif
209:
210: static struct win_syscall {
211: const char *zName; /* Name of the sytem call */
212: sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
213: sqlite3_syscall_ptr pDefault; /* Default value */
214: } aSyscall[] = {
215: #if !SQLITE_OS_WINCE
216: { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 },
217:
218: #define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent)
219: #else
220: { "AreFileApisANSI", (SYSCALL)0, 0 },
221: #endif
222:
223: #if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
224: { "CharLowerW", (SYSCALL)CharLowerW, 0 },
225: #else
226: { "CharLowerW", (SYSCALL)0, 0 },
227: #endif
228:
229: #define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent)
230:
231: #if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
232: { "CharUpperW", (SYSCALL)CharUpperW, 0 },
233: #else
234: { "CharUpperW", (SYSCALL)0, 0 },
235: #endif
236:
237: #define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent)
238:
239: { "CloseHandle", (SYSCALL)CloseHandle, 0 },
240:
241: #define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent)
242:
243: #if defined(SQLITE_WIN32_HAS_ANSI)
244: { "CreateFileA", (SYSCALL)CreateFileA, 0 },
245: #else
246: { "CreateFileA", (SYSCALL)0, 0 },
247: #endif
248:
249: #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \
250: LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent)
251:
252: #if defined(SQLITE_WIN32_HAS_WIDE)
253: { "CreateFileW", (SYSCALL)CreateFileW, 0 },
254: #else
255: { "CreateFileW", (SYSCALL)0, 0 },
256: #endif
257:
258: #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \
259: LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent)
260:
261: { "CreateFileMapping", (SYSCALL)CreateFileMapping, 0 },
262:
263: #define osCreateFileMapping ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
264: DWORD,DWORD,DWORD,LPCTSTR))aSyscall[6].pCurrent)
265:
266: #if defined(SQLITE_WIN32_HAS_WIDE)
267: { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 },
268: #else
269: { "CreateFileMappingW", (SYSCALL)0, 0 },
270: #endif
271:
272: #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \
273: DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent)
274:
275: #if defined(SQLITE_WIN32_HAS_WIDE)
276: { "CreateMutexW", (SYSCALL)CreateMutexW, 0 },
277: #else
278: { "CreateMutexW", (SYSCALL)0, 0 },
279: #endif
280:
281: #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \
282: LPCWSTR))aSyscall[8].pCurrent)
283:
284: #if defined(SQLITE_WIN32_HAS_ANSI)
285: { "DeleteFileA", (SYSCALL)DeleteFileA, 0 },
286: #else
287: { "DeleteFileA", (SYSCALL)0, 0 },
288: #endif
289:
290: #define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent)
291:
292: #if defined(SQLITE_WIN32_HAS_WIDE)
293: { "DeleteFileW", (SYSCALL)DeleteFileW, 0 },
294: #else
295: { "DeleteFileW", (SYSCALL)0, 0 },
296: #endif
297:
298: #define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent)
299:
300: #if SQLITE_OS_WINCE
301: { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 },
302: #else
303: { "FileTimeToLocalFileTime", (SYSCALL)0, 0 },
304: #endif
305:
306: #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \
307: LPFILETIME))aSyscall[11].pCurrent)
308:
309: #if SQLITE_OS_WINCE
310: { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 },
311: #else
312: { "FileTimeToSystemTime", (SYSCALL)0, 0 },
313: #endif
314:
315: #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \
316: LPSYSTEMTIME))aSyscall[12].pCurrent)
317:
318: { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 },
319:
320: #define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent)
321:
322: #if defined(SQLITE_WIN32_HAS_ANSI)
323: { "FormatMessageA", (SYSCALL)FormatMessageA, 0 },
324: #else
325: { "FormatMessageA", (SYSCALL)0, 0 },
326: #endif
327:
328: #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \
329: DWORD,va_list*))aSyscall[14].pCurrent)
330:
331: #if defined(SQLITE_WIN32_HAS_WIDE)
332: { "FormatMessageW", (SYSCALL)FormatMessageW, 0 },
333: #else
334: { "FormatMessageW", (SYSCALL)0, 0 },
335: #endif
336:
337: #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \
338: DWORD,va_list*))aSyscall[15].pCurrent)
339:
340: { "FreeLibrary", (SYSCALL)FreeLibrary, 0 },
341:
342: #define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent)
343:
344: { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 },
345:
346: #define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent)
347:
348: #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
349: { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 },
350: #else
351: { "GetDiskFreeSpaceA", (SYSCALL)0, 0 },
352: #endif
353:
354: #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \
355: LPDWORD))aSyscall[18].pCurrent)
356:
357: #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
358: { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 },
359: #else
360: { "GetDiskFreeSpaceW", (SYSCALL)0, 0 },
361: #endif
362:
363: #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \
364: LPDWORD))aSyscall[19].pCurrent)
365:
366: #if defined(SQLITE_WIN32_HAS_ANSI)
367: { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 },
368: #else
369: { "GetFileAttributesA", (SYSCALL)0, 0 },
370: #endif
371:
372: #define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent)
373:
374: #if defined(SQLITE_WIN32_HAS_WIDE)
375: { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 },
376: #else
377: { "GetFileAttributesW", (SYSCALL)0, 0 },
378: #endif
379:
380: #define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent)
381:
382: #if defined(SQLITE_WIN32_HAS_WIDE)
383: { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 },
384: #else
385: { "GetFileAttributesExW", (SYSCALL)0, 0 },
386: #endif
387:
388: #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \
389: LPVOID))aSyscall[22].pCurrent)
390:
391: { "GetFileSize", (SYSCALL)GetFileSize, 0 },
392:
393: #define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent)
394:
395: #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI)
396: { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 },
397: #else
398: { "GetFullPathNameA", (SYSCALL)0, 0 },
399: #endif
400:
401: #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \
402: LPSTR*))aSyscall[24].pCurrent)
403:
404: #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE)
405: { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 },
406: #else
407: { "GetFullPathNameW", (SYSCALL)0, 0 },
408: #endif
409:
410: #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \
411: LPWSTR*))aSyscall[25].pCurrent)
412:
413: { "GetLastError", (SYSCALL)GetLastError, 0 },
414:
415: #define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent)
416:
417: #if SQLITE_OS_WINCE
418: /* The GetProcAddressA() routine is only available on Windows CE. */
419: { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 },
420: #else
421: /* All other Windows platforms expect GetProcAddress() to take
422: ** an ANSI string regardless of the _UNICODE setting */
423: { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 },
424: #endif
425:
426: #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \
427: LPCSTR))aSyscall[27].pCurrent)
428:
429: { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 },
430:
431: #define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent)
432:
433: { "GetSystemTime", (SYSCALL)GetSystemTime, 0 },
434:
435: #define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent)
436:
437: #if !SQLITE_OS_WINCE
438: { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 },
439: #else
440: { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 },
441: #endif
442:
443: #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \
444: LPFILETIME))aSyscall[30].pCurrent)
445:
446: #if defined(SQLITE_WIN32_HAS_ANSI)
447: { "GetTempPathA", (SYSCALL)GetTempPathA, 0 },
448: #else
449: { "GetTempPathA", (SYSCALL)0, 0 },
450: #endif
451:
452: #define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent)
453:
454: #if defined(SQLITE_WIN32_HAS_WIDE)
455: { "GetTempPathW", (SYSCALL)GetTempPathW, 0 },
456: #else
457: { "GetTempPathW", (SYSCALL)0, 0 },
458: #endif
459:
460: #define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent)
461:
462: { "GetTickCount", (SYSCALL)GetTickCount, 0 },
463:
464: #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent)
465:
466: #if defined(SQLITE_WIN32_HAS_ANSI)
467: { "GetVersionExA", (SYSCALL)GetVersionExA, 0 },
468: #else
469: { "GetVersionExA", (SYSCALL)0, 0 },
470: #endif
471:
472: #define osGetVersionExA ((BOOL(WINAPI*)( \
473: LPOSVERSIONINFOA))aSyscall[34].pCurrent)
474:
475: { "HeapAlloc", (SYSCALL)HeapAlloc, 0 },
476:
477: #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \
478: SIZE_T))aSyscall[35].pCurrent)
479:
480: { "HeapCreate", (SYSCALL)HeapCreate, 0 },
481:
482: #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \
483: SIZE_T))aSyscall[36].pCurrent)
484:
485: { "HeapDestroy", (SYSCALL)HeapDestroy, 0 },
486:
487: #define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[37].pCurrent)
488:
489: { "HeapFree", (SYSCALL)HeapFree, 0 },
490:
491: #define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[38].pCurrent)
492:
493: { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 },
494:
495: #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \
496: SIZE_T))aSyscall[39].pCurrent)
497:
498: { "HeapSize", (SYSCALL)HeapSize, 0 },
499:
500: #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \
501: LPCVOID))aSyscall[40].pCurrent)
502:
503: { "HeapValidate", (SYSCALL)HeapValidate, 0 },
504:
505: #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \
506: LPCVOID))aSyscall[41].pCurrent)
507:
508: #if defined(SQLITE_WIN32_HAS_ANSI)
509: { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 },
510: #else
511: { "LoadLibraryA", (SYSCALL)0, 0 },
512: #endif
513:
514: #define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[42].pCurrent)
515:
516: #if defined(SQLITE_WIN32_HAS_WIDE)
517: { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 },
518: #else
519: { "LoadLibraryW", (SYSCALL)0, 0 },
520: #endif
521:
522: #define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[43].pCurrent)
523:
524: { "LocalFree", (SYSCALL)LocalFree, 0 },
525:
526: #define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[44].pCurrent)
527:
528: #if !SQLITE_OS_WINCE
529: { "LockFile", (SYSCALL)LockFile, 0 },
530:
531: #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
532: DWORD))aSyscall[45].pCurrent)
533: #else
534: { "LockFile", (SYSCALL)0, 0 },
535: #endif
536:
537: #if !SQLITE_OS_WINCE
538: { "LockFileEx", (SYSCALL)LockFileEx, 0 },
539:
540: #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \
541: LPOVERLAPPED))aSyscall[46].pCurrent)
542: #else
543: { "LockFileEx", (SYSCALL)0, 0 },
544: #endif
545:
546: { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 },
547:
548: #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
549: SIZE_T))aSyscall[47].pCurrent)
550:
551: { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 },
552:
553: #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \
554: int))aSyscall[48].pCurrent)
555:
556: { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 },
557:
558: #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \
559: LARGE_INTEGER*))aSyscall[49].pCurrent)
560:
561: { "ReadFile", (SYSCALL)ReadFile, 0 },
562:
563: #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \
564: LPOVERLAPPED))aSyscall[50].pCurrent)
565:
566: { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 },
567:
568: #define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[51].pCurrent)
569:
570: { "SetFilePointer", (SYSCALL)SetFilePointer, 0 },
571:
572: #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \
573: DWORD))aSyscall[52].pCurrent)
574:
575: { "Sleep", (SYSCALL)Sleep, 0 },
576:
577: #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[53].pCurrent)
578:
579: { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 },
580:
581: #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \
582: LPFILETIME))aSyscall[54].pCurrent)
583:
584: #if !SQLITE_OS_WINCE
585: { "UnlockFile", (SYSCALL)UnlockFile, 0 },
586:
587: #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
588: DWORD))aSyscall[55].pCurrent)
589: #else
590: { "UnlockFile", (SYSCALL)0, 0 },
591: #endif
592:
593: #if !SQLITE_OS_WINCE
594: { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 },
595:
596: #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \
597: LPOVERLAPPED))aSyscall[56].pCurrent)
598: #else
599: { "UnlockFileEx", (SYSCALL)0, 0 },
600: #endif
601:
602: { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 },
603:
604: #define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[57].pCurrent)
605:
606: { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 },
607:
608: #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \
609: LPCSTR,LPBOOL))aSyscall[58].pCurrent)
610:
611: { "WriteFile", (SYSCALL)WriteFile, 0 },
612:
613: #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \
614: LPOVERLAPPED))aSyscall[59].pCurrent)
615:
616: }; /* End of the overrideable system calls */
617:
618: /*
619: ** This is the xSetSystemCall() method of sqlite3_vfs for all of the
620: ** "win32" VFSes. Return SQLITE_OK opon successfully updating the
621: ** system call pointer, or SQLITE_NOTFOUND if there is no configurable
622: ** system call named zName.
623: */
624: static int winSetSystemCall(
625: sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */
626: const char *zName, /* Name of system call to override */
627: sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */
628: ){
629: unsigned int i;
630: int rc = SQLITE_NOTFOUND;
631:
632: UNUSED_PARAMETER(pNotUsed);
633: if( zName==0 ){
634: /* If no zName is given, restore all system calls to their default
635: ** settings and return NULL
636: */
637: rc = SQLITE_OK;
638: for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
639: if( aSyscall[i].pDefault ){
640: aSyscall[i].pCurrent = aSyscall[i].pDefault;
641: }
642: }
643: }else{
644: /* If zName is specified, operate on only the one system call
645: ** specified.
646: */
647: for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
648: if( strcmp(zName, aSyscall[i].zName)==0 ){
649: if( aSyscall[i].pDefault==0 ){
650: aSyscall[i].pDefault = aSyscall[i].pCurrent;
651: }
652: rc = SQLITE_OK;
653: if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault;
654: aSyscall[i].pCurrent = pNewFunc;
655: break;
656: }
657: }
658: }
659: return rc;
660: }
661:
662: /*
663: ** Return the value of a system call. Return NULL if zName is not a
664: ** recognized system call name. NULL is also returned if the system call
665: ** is currently undefined.
666: */
667: static sqlite3_syscall_ptr winGetSystemCall(
668: sqlite3_vfs *pNotUsed,
669: const char *zName
670: ){
671: unsigned int i;
672:
673: UNUSED_PARAMETER(pNotUsed);
674: for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){
675: if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent;
676: }
677: return 0;
678: }
679:
680: /*
681: ** Return the name of the first system call after zName. If zName==NULL
682: ** then return the name of the first system call. Return NULL if zName
683: ** is the last system call or if zName is not the name of a valid
684: ** system call.
685: */
686: static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
687: int i = -1;
688:
689: UNUSED_PARAMETER(p);
690: if( zName ){
691: for(i=0; i<ArraySize(aSyscall)-1; i++){
692: if( strcmp(zName, aSyscall[i].zName)==0 ) break;
693: }
694: }
695: for(i++; i<ArraySize(aSyscall); i++){
696: if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName;
697: }
698: return 0;
699: }
700:
701: /*
702: ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
703: ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
704: **
705: ** Here is an interesting observation: Win95, Win98, and WinME lack
706: ** the LockFileEx() API. But we can still statically link against that
707: ** API as long as we don't call it when running Win95/98/ME. A call to
708: ** this routine is used to determine if the host is Win95/98/ME or
709: ** WinNT/2K/XP so that we will know whether or not we can safely call
710: ** the LockFileEx() API.
711: */
712: #if SQLITE_OS_WINCE
713: # define isNT() (1)
714: #else
715: static int isNT(void){
716: if( sqlite3_os_type==0 ){
717: OSVERSIONINFOA sInfo;
718: sInfo.dwOSVersionInfoSize = sizeof(sInfo);
719: osGetVersionExA(&sInfo);
720: sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
721: }
722: return sqlite3_os_type==2;
723: }
724: #endif /* SQLITE_OS_WINCE */
725:
726: #ifdef SQLITE_WIN32_MALLOC
727: /*
728: ** Allocate nBytes of memory.
729: */
730: static void *winMemMalloc(int nBytes){
731: HANDLE hHeap;
732: void *p;
733:
734: winMemAssertMagic();
735: hHeap = winMemGetHeap();
736: assert( hHeap!=0 );
737: assert( hHeap!=INVALID_HANDLE_VALUE );
738: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
739: assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
740: #endif
741: assert( nBytes>=0 );
742: p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
743: if( !p ){
744: sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%d), heap=%p",
745: nBytes, osGetLastError(), (void*)hHeap);
746: }
747: return p;
748: }
749:
750: /*
751: ** Free memory.
752: */
753: static void winMemFree(void *pPrior){
754: HANDLE hHeap;
755:
756: winMemAssertMagic();
757: hHeap = winMemGetHeap();
758: assert( hHeap!=0 );
759: assert( hHeap!=INVALID_HANDLE_VALUE );
760: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
761: assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
762: #endif
763: if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */
764: if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){
765: sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%d), heap=%p",
766: pPrior, osGetLastError(), (void*)hHeap);
767: }
768: }
769:
770: /*
771: ** Change the size of an existing memory allocation
772: */
773: static void *winMemRealloc(void *pPrior, int nBytes){
774: HANDLE hHeap;
775: void *p;
776:
777: winMemAssertMagic();
778: hHeap = winMemGetHeap();
779: assert( hHeap!=0 );
780: assert( hHeap!=INVALID_HANDLE_VALUE );
781: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
782: assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) );
783: #endif
784: assert( nBytes>=0 );
785: if( !pPrior ){
786: p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes);
787: }else{
788: p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes);
789: }
790: if( !p ){
791: sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%d), heap=%p",
792: pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(),
793: (void*)hHeap);
794: }
795: return p;
796: }
797:
798: /*
799: ** Return the size of an outstanding allocation, in bytes.
800: */
801: static int winMemSize(void *p){
802: HANDLE hHeap;
803: SIZE_T n;
804:
805: winMemAssertMagic();
806: hHeap = winMemGetHeap();
807: assert( hHeap!=0 );
808: assert( hHeap!=INVALID_HANDLE_VALUE );
809: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
810: assert ( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
811: #endif
812: if( !p ) return 0;
813: n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p);
814: if( n==(SIZE_T)-1 ){
815: sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%d), heap=%p",
816: p, osGetLastError(), (void*)hHeap);
817: return 0;
818: }
819: return (int)n;
820: }
821:
822: /*
823: ** Round up a request size to the next valid allocation size.
824: */
825: static int winMemRoundup(int n){
826: return n;
827: }
828:
829: /*
830: ** Initialize this module.
831: */
832: static int winMemInit(void *pAppData){
833: winMemData *pWinMemData = (winMemData *)pAppData;
834:
835: if( !pWinMemData ) return SQLITE_ERROR;
836: assert( pWinMemData->magic==WINMEM_MAGIC );
837: if( !pWinMemData->hHeap ){
838: pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS,
839: SQLITE_WIN32_HEAP_INIT_SIZE,
840: SQLITE_WIN32_HEAP_MAX_SIZE);
841: if( !pWinMemData->hHeap ){
842: sqlite3_log(SQLITE_NOMEM,
843: "failed to HeapCreate (%d), flags=%u, initSize=%u, maxSize=%u",
844: osGetLastError(), SQLITE_WIN32_HEAP_FLAGS,
845: SQLITE_WIN32_HEAP_INIT_SIZE, SQLITE_WIN32_HEAP_MAX_SIZE);
846: return SQLITE_NOMEM;
847: }
848: pWinMemData->bOwned = TRUE;
849: }
850: assert( pWinMemData->hHeap!=0 );
851: assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
852: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
853: assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
854: #endif
855: return SQLITE_OK;
856: }
857:
858: /*
859: ** Deinitialize this module.
860: */
861: static void winMemShutdown(void *pAppData){
862: winMemData *pWinMemData = (winMemData *)pAppData;
863:
864: if( !pWinMemData ) return;
865: if( pWinMemData->hHeap ){
866: assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE );
867: #ifdef SQLITE_WIN32_MALLOC_VALIDATE
868: assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) );
869: #endif
870: if( pWinMemData->bOwned ){
871: if( !osHeapDestroy(pWinMemData->hHeap) ){
872: sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%d), heap=%p",
873: osGetLastError(), (void*)pWinMemData->hHeap);
874: }
875: pWinMemData->bOwned = FALSE;
876: }
877: pWinMemData->hHeap = NULL;
878: }
879: }
880:
881: /*
882: ** Populate the low-level memory allocation function pointers in
883: ** sqlite3GlobalConfig.m with pointers to the routines in this file. The
884: ** arguments specify the block of memory to manage.
885: **
886: ** This routine is only called by sqlite3_config(), and therefore
887: ** is not required to be threadsafe (it is not).
888: */
889: const sqlite3_mem_methods *sqlite3MemGetWin32(void){
890: static const sqlite3_mem_methods winMemMethods = {
891: winMemMalloc,
892: winMemFree,
893: winMemRealloc,
894: winMemSize,
895: winMemRoundup,
896: winMemInit,
897: winMemShutdown,
898: &win_mem_data
899: };
900: return &winMemMethods;
901: }
902:
903: void sqlite3MemSetDefault(void){
904: sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32());
905: }
906: #endif /* SQLITE_WIN32_MALLOC */
907:
908: /*
909: ** Convert a UTF-8 string to Microsoft Unicode (UTF-16?).
910: **
911: ** Space to hold the returned string is obtained from malloc.
912: */
913: static LPWSTR utf8ToUnicode(const char *zFilename){
914: int nChar;
915: LPWSTR zWideFilename;
916:
917: nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
918: if( nChar==0 ){
919: return 0;
920: }
921: zWideFilename = sqlite3_malloc( nChar*sizeof(zWideFilename[0]) );
922: if( zWideFilename==0 ){
923: return 0;
924: }
925: nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename,
926: nChar);
927: if( nChar==0 ){
928: sqlite3_free(zWideFilename);
929: zWideFilename = 0;
930: }
931: return zWideFilename;
932: }
933:
934: /*
935: ** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is
936: ** obtained from sqlite3_malloc().
937: */
938: static char *unicodeToUtf8(LPCWSTR zWideFilename){
939: int nByte;
940: char *zFilename;
941:
942: nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
943: if( nByte == 0 ){
944: return 0;
945: }
946: zFilename = sqlite3_malloc( nByte );
947: if( zFilename==0 ){
948: return 0;
949: }
950: nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
951: 0, 0);
952: if( nByte == 0 ){
953: sqlite3_free(zFilename);
954: zFilename = 0;
955: }
956: return zFilename;
957: }
958:
959: /*
960: ** Convert an ANSI string to Microsoft Unicode, based on the
961: ** current codepage settings for file apis.
962: **
963: ** Space to hold the returned string is obtained
964: ** from sqlite3_malloc.
965: */
966: static LPWSTR mbcsToUnicode(const char *zFilename){
967: int nByte;
968: LPWSTR zMbcsFilename;
969: int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
970:
971: nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL,
972: 0)*sizeof(WCHAR);
973: if( nByte==0 ){
974: return 0;
975: }
976: zMbcsFilename = sqlite3_malloc( nByte*sizeof(zMbcsFilename[0]) );
977: if( zMbcsFilename==0 ){
978: return 0;
979: }
980: nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename,
981: nByte);
982: if( nByte==0 ){
983: sqlite3_free(zMbcsFilename);
984: zMbcsFilename = 0;
985: }
986: return zMbcsFilename;
987: }
988:
989: /*
990: ** Convert Microsoft Unicode to multi-byte character string, based on the
991: ** user's ANSI codepage.
992: **
993: ** Space to hold the returned string is obtained from
994: ** sqlite3_malloc().
995: */
996: static char *unicodeToMbcs(LPCWSTR zWideFilename){
997: int nByte;
998: char *zFilename;
999: int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP;
1000:
1001: nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
1002: if( nByte == 0 ){
1003: return 0;
1004: }
1005: zFilename = sqlite3_malloc( nByte );
1006: if( zFilename==0 ){
1007: return 0;
1008: }
1009: nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename,
1010: nByte, 0, 0);
1011: if( nByte == 0 ){
1012: sqlite3_free(zFilename);
1013: zFilename = 0;
1014: }
1015: return zFilename;
1016: }
1017:
1018: /*
1019: ** Convert multibyte character string to UTF-8. Space to hold the
1020: ** returned string is obtained from sqlite3_malloc().
1021: */
1022: char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
1023: char *zFilenameUtf8;
1024: LPWSTR zTmpWide;
1025:
1026: zTmpWide = mbcsToUnicode(zFilename);
1027: if( zTmpWide==0 ){
1028: return 0;
1029: }
1030: zFilenameUtf8 = unicodeToUtf8(zTmpWide);
1031: sqlite3_free(zTmpWide);
1032: return zFilenameUtf8;
1033: }
1034:
1035: /*
1036: ** Convert UTF-8 to multibyte character string. Space to hold the
1037: ** returned string is obtained from sqlite3_malloc().
1038: */
1039: char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
1040: char *zFilenameMbcs;
1041: LPWSTR zTmpWide;
1042:
1043: zTmpWide = utf8ToUnicode(zFilename);
1044: if( zTmpWide==0 ){
1045: return 0;
1046: }
1047: zFilenameMbcs = unicodeToMbcs(zTmpWide);
1048: sqlite3_free(zTmpWide);
1049: return zFilenameMbcs;
1050: }
1051:
1052:
1053: /*
1054: ** The return value of getLastErrorMsg
1055: ** is zero if the error message fits in the buffer, or non-zero
1056: ** otherwise (if the message was truncated).
1057: */
1058: static int getLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){
1059: /* FormatMessage returns 0 on failure. Otherwise it
1060: ** returns the number of TCHARs written to the output
1061: ** buffer, excluding the terminating null char.
1062: */
1063: DWORD dwLen = 0;
1064: char *zOut = 0;
1065:
1066: if( isNT() ){
1067: LPWSTR zTempWide = NULL;
1068: dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1069: FORMAT_MESSAGE_FROM_SYSTEM |
1070: FORMAT_MESSAGE_IGNORE_INSERTS,
1071: NULL,
1072: lastErrno,
1073: 0,
1074: (LPWSTR) &zTempWide,
1075: 0,
1076: 0);
1077: if( dwLen > 0 ){
1078: /* allocate a buffer and convert to UTF8 */
1079: sqlite3BeginBenignMalloc();
1080: zOut = unicodeToUtf8(zTempWide);
1081: sqlite3EndBenignMalloc();
1082: /* free the system buffer allocated by FormatMessage */
1083: osLocalFree(zTempWide);
1084: }
1085: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
1086: ** Since the ANSI version of these Windows API do not exist for WINCE,
1087: ** it's important to not reference them for WINCE builds.
1088: */
1089: #if SQLITE_OS_WINCE==0
1090: }else{
1091: char *zTemp = NULL;
1092: dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
1093: FORMAT_MESSAGE_FROM_SYSTEM |
1094: FORMAT_MESSAGE_IGNORE_INSERTS,
1095: NULL,
1096: lastErrno,
1097: 0,
1098: (LPSTR) &zTemp,
1099: 0,
1100: 0);
1101: if( dwLen > 0 ){
1102: /* allocate a buffer and convert to UTF8 */
1103: sqlite3BeginBenignMalloc();
1104: zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
1105: sqlite3EndBenignMalloc();
1106: /* free the system buffer allocated by FormatMessage */
1107: osLocalFree(zTemp);
1108: }
1109: #endif
1110: }
1111: if( 0 == dwLen ){
1112: sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", lastErrno, lastErrno);
1113: }else{
1114: /* copy a maximum of nBuf chars to output buffer */
1115: sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
1116: /* free the UTF8 buffer */
1117: sqlite3_free(zOut);
1118: }
1119: return 0;
1120: }
1121:
1122: /*
1123: **
1124: ** This function - winLogErrorAtLine() - is only ever called via the macro
1125: ** winLogError().
1126: **
1127: ** This routine is invoked after an error occurs in an OS function.
1128: ** It logs a message using sqlite3_log() containing the current value of
1129: ** error code and, if possible, the human-readable equivalent from
1130: ** FormatMessage.
1131: **
1132: ** The first argument passed to the macro should be the error code that
1133: ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
1134: ** The two subsequent arguments should be the name of the OS function that
1135: ** failed and the the associated file-system path, if any.
1136: */
1137: #define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__)
1138: static int winLogErrorAtLine(
1139: int errcode, /* SQLite error code */
1140: DWORD lastErrno, /* Win32 last error */
1141: const char *zFunc, /* Name of OS function that failed */
1142: const char *zPath, /* File path associated with error */
1143: int iLine /* Source line number where error occurred */
1144: ){
1145: char zMsg[500]; /* Human readable error text */
1146: int i; /* Loop counter */
1147:
1148: zMsg[0] = 0;
1149: getLastErrorMsg(lastErrno, sizeof(zMsg), zMsg);
1150: assert( errcode!=SQLITE_OK );
1151: if( zPath==0 ) zPath = "";
1152: for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){}
1153: zMsg[i] = 0;
1154: sqlite3_log(errcode,
1155: "os_win.c:%d: (%d) %s(%s) - %s",
1156: iLine, lastErrno, zFunc, zPath, zMsg
1157: );
1158:
1159: return errcode;
1160: }
1161:
1162: /*
1163: ** The number of times that a ReadFile(), WriteFile(), and DeleteFile()
1164: ** will be retried following a locking error - probably caused by
1165: ** antivirus software. Also the initial delay before the first retry.
1166: ** The delay increases linearly with each retry.
1167: */
1168: #ifndef SQLITE_WIN32_IOERR_RETRY
1169: # define SQLITE_WIN32_IOERR_RETRY 10
1170: #endif
1171: #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY
1172: # define SQLITE_WIN32_IOERR_RETRY_DELAY 25
1173: #endif
1174: static int win32IoerrRetry = SQLITE_WIN32_IOERR_RETRY;
1175: static int win32IoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
1176:
1177: /*
1178: ** If a ReadFile() or WriteFile() error occurs, invoke this routine
1179: ** to see if it should be retried. Return TRUE to retry. Return FALSE
1180: ** to give up with an error.
1181: */
1182: static int retryIoerr(int *pnRetry, DWORD *pError){
1183: DWORD e = osGetLastError();
1184: if( *pnRetry>=win32IoerrRetry ){
1185: if( pError ){
1186: *pError = e;
1187: }
1188: return 0;
1189: }
1190: if( e==ERROR_ACCESS_DENIED ||
1191: e==ERROR_LOCK_VIOLATION ||
1192: e==ERROR_SHARING_VIOLATION ){
1193: osSleep(win32IoerrRetryDelay*(1+*pnRetry));
1194: ++*pnRetry;
1195: return 1;
1196: }
1197: if( pError ){
1198: *pError = e;
1199: }
1200: return 0;
1201: }
1202:
1203: /*
1204: ** Log a I/O error retry episode.
1205: */
1206: static void logIoerr(int nRetry){
1207: if( nRetry ){
1208: sqlite3_log(SQLITE_IOERR,
1209: "delayed %dms for lock/sharing conflict",
1210: win32IoerrRetryDelay*nRetry*(nRetry+1)/2
1211: );
1212: }
1213: }
1214:
1215: #if SQLITE_OS_WINCE
1216: /*************************************************************************
1217: ** This section contains code for WinCE only.
1218: */
1219: /*
1220: ** Windows CE does not have a localtime() function. So create a
1221: ** substitute.
1222: */
1223: #include <time.h>
1224: struct tm *__cdecl localtime(const time_t *t)
1225: {
1226: static struct tm y;
1227: FILETIME uTm, lTm;
1228: SYSTEMTIME pTm;
1229: sqlite3_int64 t64;
1230: t64 = *t;
1231: t64 = (t64 + 11644473600)*10000000;
1232: uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
1233: uTm.dwHighDateTime= (DWORD)(t64 >> 32);
1234: osFileTimeToLocalFileTime(&uTm,&lTm);
1235: osFileTimeToSystemTime(&lTm,&pTm);
1236: y.tm_year = pTm.wYear - 1900;
1237: y.tm_mon = pTm.wMonth - 1;
1238: y.tm_wday = pTm.wDayOfWeek;
1239: y.tm_mday = pTm.wDay;
1240: y.tm_hour = pTm.wHour;
1241: y.tm_min = pTm.wMinute;
1242: y.tm_sec = pTm.wSecond;
1243: return &y;
1244: }
1245:
1246: #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
1247:
1248: /*
1249: ** Acquire a lock on the handle h
1250: */
1251: static void winceMutexAcquire(HANDLE h){
1252: DWORD dwErr;
1253: do {
1254: dwErr = WaitForSingleObject(h, INFINITE);
1255: } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
1256: }
1257: /*
1258: ** Release a lock acquired by winceMutexAcquire()
1259: */
1260: #define winceMutexRelease(h) ReleaseMutex(h)
1261:
1262: /*
1263: ** Create the mutex and shared memory used for locking in the file
1264: ** descriptor pFile
1265: */
1266: static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
1267: LPWSTR zTok;
1268: LPWSTR zName;
1269: BOOL bInit = TRUE;
1270:
1271: zName = utf8ToUnicode(zFilename);
1272: if( zName==0 ){
1273: /* out of memory */
1274: return FALSE;
1275: }
1276:
1277: /* Initialize the local lockdata */
1278: memset(&pFile->local, 0, sizeof(pFile->local));
1279:
1280: /* Replace the backslashes from the filename and lowercase it
1281: ** to derive a mutex name. */
1282: zTok = osCharLowerW(zName);
1283: for (;*zTok;zTok++){
1284: if (*zTok == '\\') *zTok = '_';
1285: }
1286:
1287: /* Create/open the named mutex */
1288: pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
1289: if (!pFile->hMutex){
1290: pFile->lastErrno = osGetLastError();
1291: winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename);
1292: sqlite3_free(zName);
1293: return FALSE;
1294: }
1295:
1296: /* Acquire the mutex before continuing */
1297: winceMutexAcquire(pFile->hMutex);
1298:
1299: /* Since the names of named mutexes, semaphores, file mappings etc are
1300: ** case-sensitive, take advantage of that by uppercasing the mutex name
1301: ** and using that as the shared filemapping name.
1302: */
1303: osCharUpperW(zName);
1304: pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
1305: PAGE_READWRITE, 0, sizeof(winceLock),
1306: zName);
1307:
1308: /* Set a flag that indicates we're the first to create the memory so it
1309: ** must be zero-initialized */
1310: if (osGetLastError() == ERROR_ALREADY_EXISTS){
1311: bInit = FALSE;
1312: }
1313:
1314: sqlite3_free(zName);
1315:
1316: /* If we succeeded in making the shared memory handle, map it. */
1317: if (pFile->hShared){
1318: pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared,
1319: FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
1320: /* If mapping failed, close the shared memory handle and erase it */
1321: if (!pFile->shared){
1322: pFile->lastErrno = osGetLastError();
1323: winLogError(SQLITE_ERROR, pFile->lastErrno,
1324: "winceCreateLock2", zFilename);
1325: osCloseHandle(pFile->hShared);
1326: pFile->hShared = NULL;
1327: }
1328: }
1329:
1330: /* If shared memory could not be created, then close the mutex and fail */
1331: if (pFile->hShared == NULL){
1332: winceMutexRelease(pFile->hMutex);
1333: osCloseHandle(pFile->hMutex);
1334: pFile->hMutex = NULL;
1335: return FALSE;
1336: }
1337:
1338: /* Initialize the shared memory if we're supposed to */
1339: if (bInit) {
1340: memset(pFile->shared, 0, sizeof(winceLock));
1341: }
1342:
1343: winceMutexRelease(pFile->hMutex);
1344: return TRUE;
1345: }
1346:
1347: /*
1348: ** Destroy the part of winFile that deals with wince locks
1349: */
1350: static void winceDestroyLock(winFile *pFile){
1351: if (pFile->hMutex){
1352: /* Acquire the mutex */
1353: winceMutexAcquire(pFile->hMutex);
1354:
1355: /* The following blocks should probably assert in debug mode, but they
1356: are to cleanup in case any locks remained open */
1357: if (pFile->local.nReaders){
1358: pFile->shared->nReaders --;
1359: }
1360: if (pFile->local.bReserved){
1361: pFile->shared->bReserved = FALSE;
1362: }
1363: if (pFile->local.bPending){
1364: pFile->shared->bPending = FALSE;
1365: }
1366: if (pFile->local.bExclusive){
1367: pFile->shared->bExclusive = FALSE;
1368: }
1369:
1370: /* De-reference and close our copy of the shared memory handle */
1371: osUnmapViewOfFile(pFile->shared);
1372: osCloseHandle(pFile->hShared);
1373:
1374: /* Done with the mutex */
1375: winceMutexRelease(pFile->hMutex);
1376: osCloseHandle(pFile->hMutex);
1377: pFile->hMutex = NULL;
1378: }
1379: }
1380:
1381: /*
1382: ** An implementation of the LockFile() API of Windows for CE
1383: */
1384: static BOOL winceLockFile(
1385: HANDLE *phFile,
1386: DWORD dwFileOffsetLow,
1387: DWORD dwFileOffsetHigh,
1388: DWORD nNumberOfBytesToLockLow,
1389: DWORD nNumberOfBytesToLockHigh
1390: ){
1391: winFile *pFile = HANDLE_TO_WINFILE(phFile);
1392: BOOL bReturn = FALSE;
1393:
1394: UNUSED_PARAMETER(dwFileOffsetHigh);
1395: UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
1396:
1397: if (!pFile->hMutex) return TRUE;
1398: winceMutexAcquire(pFile->hMutex);
1399:
1400: /* Wanting an exclusive lock? */
1401: if (dwFileOffsetLow == (DWORD)SHARED_FIRST
1402: && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
1403: if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
1404: pFile->shared->bExclusive = TRUE;
1405: pFile->local.bExclusive = TRUE;
1406: bReturn = TRUE;
1407: }
1408: }
1409:
1410: /* Want a read-only lock? */
1411: else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
1412: nNumberOfBytesToLockLow == 1){
1413: if (pFile->shared->bExclusive == 0){
1414: pFile->local.nReaders ++;
1415: if (pFile->local.nReaders == 1){
1416: pFile->shared->nReaders ++;
1417: }
1418: bReturn = TRUE;
1419: }
1420: }
1421:
1422: /* Want a pending lock? */
1423: else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
1424: /* If no pending lock has been acquired, then acquire it */
1425: if (pFile->shared->bPending == 0) {
1426: pFile->shared->bPending = TRUE;
1427: pFile->local.bPending = TRUE;
1428: bReturn = TRUE;
1429: }
1430: }
1431:
1432: /* Want a reserved lock? */
1433: else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
1434: if (pFile->shared->bReserved == 0) {
1435: pFile->shared->bReserved = TRUE;
1436: pFile->local.bReserved = TRUE;
1437: bReturn = TRUE;
1438: }
1439: }
1440:
1441: winceMutexRelease(pFile->hMutex);
1442: return bReturn;
1443: }
1444:
1445: /*
1446: ** An implementation of the UnlockFile API of Windows for CE
1447: */
1448: static BOOL winceUnlockFile(
1449: HANDLE *phFile,
1450: DWORD dwFileOffsetLow,
1451: DWORD dwFileOffsetHigh,
1452: DWORD nNumberOfBytesToUnlockLow,
1453: DWORD nNumberOfBytesToUnlockHigh
1454: ){
1455: winFile *pFile = HANDLE_TO_WINFILE(phFile);
1456: BOOL bReturn = FALSE;
1457:
1458: UNUSED_PARAMETER(dwFileOffsetHigh);
1459: UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
1460:
1461: if (!pFile->hMutex) return TRUE;
1462: winceMutexAcquire(pFile->hMutex);
1463:
1464: /* Releasing a reader lock or an exclusive lock */
1465: if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
1466: /* Did we have an exclusive lock? */
1467: if (pFile->local.bExclusive){
1468: assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
1469: pFile->local.bExclusive = FALSE;
1470: pFile->shared->bExclusive = FALSE;
1471: bReturn = TRUE;
1472: }
1473:
1474: /* Did we just have a reader lock? */
1475: else if (pFile->local.nReaders){
1476: assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
1477: pFile->local.nReaders --;
1478: if (pFile->local.nReaders == 0)
1479: {
1480: pFile->shared->nReaders --;
1481: }
1482: bReturn = TRUE;
1483: }
1484: }
1485:
1486: /* Releasing a pending lock */
1487: else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
1488: if (pFile->local.bPending){
1489: pFile->local.bPending = FALSE;
1490: pFile->shared->bPending = FALSE;
1491: bReturn = TRUE;
1492: }
1493: }
1494: /* Releasing a reserved lock */
1495: else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
1496: if (pFile->local.bReserved) {
1497: pFile->local.bReserved = FALSE;
1498: pFile->shared->bReserved = FALSE;
1499: bReturn = TRUE;
1500: }
1501: }
1502:
1503: winceMutexRelease(pFile->hMutex);
1504: return bReturn;
1505: }
1506:
1507: /*
1508: ** An implementation of the LockFileEx() API of Windows for CE
1509: */
1510: static BOOL winceLockFileEx(
1511: HANDLE *phFile,
1512: DWORD dwFlags,
1513: DWORD dwReserved,
1514: DWORD nNumberOfBytesToLockLow,
1515: DWORD nNumberOfBytesToLockHigh,
1516: LPOVERLAPPED lpOverlapped
1517: ){
1518: UNUSED_PARAMETER(dwReserved);
1519: UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
1520:
1521: /* If the caller wants a shared read lock, forward this call
1522: ** to winceLockFile */
1523: if (lpOverlapped->Offset == (DWORD)SHARED_FIRST &&
1524: dwFlags == 1 &&
1525: nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
1526: return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
1527: }
1528: return FALSE;
1529: }
1530: /*
1531: ** End of the special code for wince
1532: *****************************************************************************/
1533: #endif /* SQLITE_OS_WINCE */
1534:
1535: /*****************************************************************************
1536: ** The next group of routines implement the I/O methods specified
1537: ** by the sqlite3_io_methods object.
1538: ******************************************************************************/
1539:
1540: /*
1541: ** Some Microsoft compilers lack this definition.
1542: */
1543: #ifndef INVALID_SET_FILE_POINTER
1544: # define INVALID_SET_FILE_POINTER ((DWORD)-1)
1545: #endif
1546:
1547: /*
1548: ** Move the current position of the file handle passed as the first
1549: ** argument to offset iOffset within the file. If successful, return 0.
1550: ** Otherwise, set pFile->lastErrno and return non-zero.
1551: */
1552: static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
1553: LONG upperBits; /* Most sig. 32 bits of new offset */
1554: LONG lowerBits; /* Least sig. 32 bits of new offset */
1555: DWORD dwRet; /* Value returned by SetFilePointer() */
1556: DWORD lastErrno; /* Value returned by GetLastError() */
1557:
1558: upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
1559: lowerBits = (LONG)(iOffset & 0xffffffff);
1560:
1561: /* API oddity: If successful, SetFilePointer() returns a dword
1562: ** containing the lower 32-bits of the new file-offset. Or, if it fails,
1563: ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
1564: ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
1565: ** whether an error has actually occured, it is also necessary to call
1566: ** GetLastError().
1567: */
1568: dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
1569:
1570: if( (dwRet==INVALID_SET_FILE_POINTER
1571: && ((lastErrno = osGetLastError())!=NO_ERROR)) ){
1572: pFile->lastErrno = lastErrno;
1573: winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno,
1574: "seekWinFile", pFile->zPath);
1575: return 1;
1576: }
1577:
1578: return 0;
1579: }
1580:
1581: /*
1582: ** Close a file.
1583: **
1584: ** It is reported that an attempt to close a handle might sometimes
1585: ** fail. This is a very unreasonable result, but Windows is notorious
1586: ** for being unreasonable so I do not doubt that it might happen. If
1587: ** the close fails, we pause for 100 milliseconds and try again. As
1588: ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
1589: ** giving up and returning an error.
1590: */
1591: #define MX_CLOSE_ATTEMPT 3
1592: static int winClose(sqlite3_file *id){
1593: int rc, cnt = 0;
1594: winFile *pFile = (winFile*)id;
1595:
1596: assert( id!=0 );
1597: assert( pFile->pShm==0 );
1598: OSTRACE(("CLOSE %d\n", pFile->h));
1599: do{
1600: rc = osCloseHandle(pFile->h);
1601: /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
1602: }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (osSleep(100), 1) );
1603: #if SQLITE_OS_WINCE
1604: #define WINCE_DELETION_ATTEMPTS 3
1605: winceDestroyLock(pFile);
1606: if( pFile->zDeleteOnClose ){
1607: int cnt = 0;
1608: while(
1609: osDeleteFileW(pFile->zDeleteOnClose)==0
1610: && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff
1611: && cnt++ < WINCE_DELETION_ATTEMPTS
1612: ){
1613: osSleep(100); /* Wait a little before trying again */
1614: }
1615: sqlite3_free(pFile->zDeleteOnClose);
1616: }
1617: #endif
1618: OSTRACE(("CLOSE %d %s\n", pFile->h, rc ? "ok" : "failed"));
1619: OpenCounter(-1);
1620: return rc ? SQLITE_OK
1621: : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
1622: "winClose", pFile->zPath);
1623: }
1624:
1625: /*
1626: ** Read data from a file into a buffer. Return SQLITE_OK if all
1627: ** bytes were read successfully and SQLITE_IOERR if anything goes
1628: ** wrong.
1629: */
1630: static int winRead(
1631: sqlite3_file *id, /* File to read from */
1632: void *pBuf, /* Write content into this buffer */
1633: int amt, /* Number of bytes to read */
1634: sqlite3_int64 offset /* Begin reading at this offset */
1635: ){
1636: winFile *pFile = (winFile*)id; /* file handle */
1637: DWORD nRead; /* Number of bytes actually read from file */
1638: int nRetry = 0; /* Number of retrys */
1639:
1640: assert( id!=0 );
1641: SimulateIOError(return SQLITE_IOERR_READ);
1642: OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
1643:
1644: if( seekWinFile(pFile, offset) ){
1645: return SQLITE_FULL;
1646: }
1647: while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
1648: DWORD lastErrno;
1649: if( retryIoerr(&nRetry, &lastErrno) ) continue;
1650: pFile->lastErrno = lastErrno;
1651: return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
1652: "winRead", pFile->zPath);
1653: }
1654: logIoerr(nRetry);
1655: if( nRead<(DWORD)amt ){
1656: /* Unread parts of the buffer must be zero-filled */
1657: memset(&((char*)pBuf)[nRead], 0, amt-nRead);
1658: return SQLITE_IOERR_SHORT_READ;
1659: }
1660:
1661: return SQLITE_OK;
1662: }
1663:
1664: /*
1665: ** Write data from a buffer into a file. Return SQLITE_OK on success
1666: ** or some other error code on failure.
1667: */
1668: static int winWrite(
1669: sqlite3_file *id, /* File to write into */
1670: const void *pBuf, /* The bytes to be written */
1671: int amt, /* Number of bytes to write */
1672: sqlite3_int64 offset /* Offset into the file to begin writing at */
1673: ){
1674: int rc; /* True if error has occured, else false */
1675: winFile *pFile = (winFile*)id; /* File handle */
1676: int nRetry = 0; /* Number of retries */
1677:
1678: assert( amt>0 );
1679: assert( pFile );
1680: SimulateIOError(return SQLITE_IOERR_WRITE);
1681: SimulateDiskfullError(return SQLITE_FULL);
1682:
1683: OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
1684:
1685: rc = seekWinFile(pFile, offset);
1686: if( rc==0 ){
1687: u8 *aRem = (u8 *)pBuf; /* Data yet to be written */
1688: int nRem = amt; /* Number of bytes yet to be written */
1689: DWORD nWrite; /* Bytes written by each WriteFile() call */
1690: DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */
1691:
1692: while( nRem>0 ){
1693: if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
1694: if( retryIoerr(&nRetry, &lastErrno) ) continue;
1695: break;
1696: }
1697: if( nWrite<=0 ) break;
1698: aRem += nWrite;
1699: nRem -= nWrite;
1700: }
1701: if( nRem>0 ){
1702: pFile->lastErrno = lastErrno;
1703: rc = 1;
1704: }
1705: }
1706:
1707: if( rc ){
1708: if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
1709: || ( pFile->lastErrno==ERROR_DISK_FULL )){
1710: return SQLITE_FULL;
1711: }
1712: return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
1713: "winWrite", pFile->zPath);
1714: }else{
1715: logIoerr(nRetry);
1716: }
1717: return SQLITE_OK;
1718: }
1719:
1720: /*
1721: ** Truncate an open file to a specified size
1722: */
1723: static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
1724: winFile *pFile = (winFile*)id; /* File handle object */
1725: int rc = SQLITE_OK; /* Return code for this function */
1726:
1727: assert( pFile );
1728:
1729: OSTRACE(("TRUNCATE %d %lld\n", pFile->h, nByte));
1730: SimulateIOError(return SQLITE_IOERR_TRUNCATE);
1731:
1732: /* If the user has configured a chunk-size for this file, truncate the
1733: ** file so that it consists of an integer number of chunks (i.e. the
1734: ** actual file size after the operation may be larger than the requested
1735: ** size).
1736: */
1737: if( pFile->szChunk>0 ){
1738: nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk;
1739: }
1740:
1741: /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
1742: if( seekWinFile(pFile, nByte) ){
1743: rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
1744: "winTruncate1", pFile->zPath);
1745: }else if( 0==osSetEndOfFile(pFile->h) ){
1746: pFile->lastErrno = osGetLastError();
1747: rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno,
1748: "winTruncate2", pFile->zPath);
1749: }
1750:
1751: OSTRACE(("TRUNCATE %d %lld %s\n", pFile->h, nByte, rc ? "failed" : "ok"));
1752: return rc;
1753: }
1754:
1755: #ifdef SQLITE_TEST
1756: /*
1757: ** Count the number of fullsyncs and normal syncs. This is used to test
1758: ** that syncs and fullsyncs are occuring at the right times.
1759: */
1760: int sqlite3_sync_count = 0;
1761: int sqlite3_fullsync_count = 0;
1762: #endif
1763:
1764: /*
1765: ** Make sure all writes to a particular file are committed to disk.
1766: */
1767: static int winSync(sqlite3_file *id, int flags){
1768: #ifndef SQLITE_NO_SYNC
1769: /*
1770: ** Used only when SQLITE_NO_SYNC is not defined.
1771: */
1772: BOOL rc;
1773: #endif
1774: #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
1775: (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
1776: /*
1777: ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
1778: ** OSTRACE() macros.
1779: */
1780: winFile *pFile = (winFile*)id;
1781: #else
1782: UNUSED_PARAMETER(id);
1783: #endif
1784:
1785: assert( pFile );
1786: /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
1787: assert((flags&0x0F)==SQLITE_SYNC_NORMAL
1788: || (flags&0x0F)==SQLITE_SYNC_FULL
1789: );
1790:
1791: OSTRACE(("SYNC %d lock=%d\n", pFile->h, pFile->locktype));
1792:
1793: /* Unix cannot, but some systems may return SQLITE_FULL from here. This
1794: ** line is to test that doing so does not cause any problems.
1795: */
1796: SimulateDiskfullError( return SQLITE_FULL );
1797:
1798: #ifndef SQLITE_TEST
1799: UNUSED_PARAMETER(flags);
1800: #else
1801: if( (flags&0x0F)==SQLITE_SYNC_FULL ){
1802: sqlite3_fullsync_count++;
1803: }
1804: sqlite3_sync_count++;
1805: #endif
1806:
1807: /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
1808: ** no-op
1809: */
1810: #ifdef SQLITE_NO_SYNC
1811: return SQLITE_OK;
1812: #else
1813: rc = osFlushFileBuffers(pFile->h);
1814: SimulateIOError( rc=FALSE );
1815: if( rc ){
1816: return SQLITE_OK;
1817: }else{
1818: pFile->lastErrno = osGetLastError();
1819: return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
1820: "winSync", pFile->zPath);
1821: }
1822: #endif
1823: }
1824:
1825: /*
1826: ** Determine the current size of a file in bytes
1827: */
1828: static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){
1829: DWORD upperBits;
1830: DWORD lowerBits;
1831: winFile *pFile = (winFile*)id;
1832: DWORD lastErrno;
1833:
1834: assert( id!=0 );
1835: SimulateIOError(return SQLITE_IOERR_FSTAT);
1836: lowerBits = osGetFileSize(pFile->h, &upperBits);
1837: if( (lowerBits == INVALID_FILE_SIZE)
1838: && ((lastErrno = osGetLastError())!=NO_ERROR) )
1839: {
1840: pFile->lastErrno = lastErrno;
1841: return winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
1842: "winFileSize", pFile->zPath);
1843: }
1844: *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
1845: return SQLITE_OK;
1846: }
1847:
1848: /*
1849: ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
1850: */
1851: #ifndef LOCKFILE_FAIL_IMMEDIATELY
1852: # define LOCKFILE_FAIL_IMMEDIATELY 1
1853: #endif
1854:
1855: /*
1856: ** Acquire a reader lock.
1857: ** Different API routines are called depending on whether or not this
1858: ** is Win9x or WinNT.
1859: */
1860: static int getReadLock(winFile *pFile){
1861: int res;
1862: if( isNT() ){
1863: OVERLAPPED ovlp;
1864: ovlp.Offset = SHARED_FIRST;
1865: ovlp.OffsetHigh = 0;
1866: ovlp.hEvent = 0;
1867: res = osLockFileEx(pFile->h, LOCKFILE_FAIL_IMMEDIATELY,
1868: 0, SHARED_SIZE, 0, &ovlp);
1869: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
1870: */
1871: #if SQLITE_OS_WINCE==0
1872: }else{
1873: int lk;
1874: sqlite3_randomness(sizeof(lk), &lk);
1875: pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
1876: res = osLockFile(pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0);
1877: #endif
1878: }
1879: if( res == 0 ){
1880: pFile->lastErrno = osGetLastError();
1881: /* No need to log a failure to lock */
1882: }
1883: return res;
1884: }
1885:
1886: /*
1887: ** Undo a readlock
1888: */
1889: static int unlockReadLock(winFile *pFile){
1890: int res;
1891: DWORD lastErrno;
1892: if( isNT() ){
1893: res = osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
1894: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
1895: */
1896: #if SQLITE_OS_WINCE==0
1897: }else{
1898: res = osUnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
1899: #endif
1900: }
1901: if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){
1902: pFile->lastErrno = lastErrno;
1903: winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
1904: "unlockReadLock", pFile->zPath);
1905: }
1906: return res;
1907: }
1908:
1909: /*
1910: ** Lock the file with the lock specified by parameter locktype - one
1911: ** of the following:
1912: **
1913: ** (1) SHARED_LOCK
1914: ** (2) RESERVED_LOCK
1915: ** (3) PENDING_LOCK
1916: ** (4) EXCLUSIVE_LOCK
1917: **
1918: ** Sometimes when requesting one lock state, additional lock states
1919: ** are inserted in between. The locking might fail on one of the later
1920: ** transitions leaving the lock state different from what it started but
1921: ** still short of its goal. The following chart shows the allowed
1922: ** transitions and the inserted intermediate states:
1923: **
1924: ** UNLOCKED -> SHARED
1925: ** SHARED -> RESERVED
1926: ** SHARED -> (PENDING) -> EXCLUSIVE
1927: ** RESERVED -> (PENDING) -> EXCLUSIVE
1928: ** PENDING -> EXCLUSIVE
1929: **
1930: ** This routine will only increase a lock. The winUnlock() routine
1931: ** erases all locks at once and returns us immediately to locking level 0.
1932: ** It is not possible to lower the locking level one step at a time. You
1933: ** must go straight to locking level 0.
1934: */
1935: static int winLock(sqlite3_file *id, int locktype){
1936: int rc = SQLITE_OK; /* Return code from subroutines */
1937: int res = 1; /* Result of a Windows lock call */
1938: int newLocktype; /* Set pFile->locktype to this value before exiting */
1939: int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
1940: winFile *pFile = (winFile*)id;
1941: DWORD lastErrno = NO_ERROR;
1942:
1943: assert( id!=0 );
1944: OSTRACE(("LOCK %d %d was %d(%d)\n",
1945: pFile->h, locktype, pFile->locktype, pFile->sharedLockByte));
1946:
1947: /* If there is already a lock of this type or more restrictive on the
1948: ** OsFile, do nothing. Don't use the end_lock: exit path, as
1949: ** sqlite3OsEnterMutex() hasn't been called yet.
1950: */
1951: if( pFile->locktype>=locktype ){
1952: return SQLITE_OK;
1953: }
1954:
1955: /* Make sure the locking sequence is correct
1956: */
1957: assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
1958: assert( locktype!=PENDING_LOCK );
1959: assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
1960:
1961: /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
1962: ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
1963: ** the PENDING_LOCK byte is temporary.
1964: */
1965: newLocktype = pFile->locktype;
1966: if( (pFile->locktype==NO_LOCK)
1967: || ( (locktype==EXCLUSIVE_LOCK)
1968: && (pFile->locktype==RESERVED_LOCK))
1969: ){
1970: int cnt = 3;
1971: while( cnt-->0 && (res = osLockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
1972: /* Try 3 times to get the pending lock. This is needed to work
1973: ** around problems caused by indexing and/or anti-virus software on
1974: ** Windows systems.
1975: ** If you are using this code as a model for alternative VFSes, do not
1976: ** copy this retry logic. It is a hack intended for Windows only.
1977: */
1978: OSTRACE(("could not get a PENDING lock. cnt=%d\n", cnt));
1979: if( cnt ) osSleep(1);
1980: }
1981: gotPendingLock = res;
1982: if( !res ){
1983: lastErrno = osGetLastError();
1984: }
1985: }
1986:
1987: /* Acquire a shared lock
1988: */
1989: if( locktype==SHARED_LOCK && res ){
1990: assert( pFile->locktype==NO_LOCK );
1991: res = getReadLock(pFile);
1992: if( res ){
1993: newLocktype = SHARED_LOCK;
1994: }else{
1995: lastErrno = osGetLastError();
1996: }
1997: }
1998:
1999: /* Acquire a RESERVED lock
2000: */
2001: if( locktype==RESERVED_LOCK && res ){
2002: assert( pFile->locktype==SHARED_LOCK );
2003: res = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
2004: if( res ){
2005: newLocktype = RESERVED_LOCK;
2006: }else{
2007: lastErrno = osGetLastError();
2008: }
2009: }
2010:
2011: /* Acquire a PENDING lock
2012: */
2013: if( locktype==EXCLUSIVE_LOCK && res ){
2014: newLocktype = PENDING_LOCK;
2015: gotPendingLock = 0;
2016: }
2017:
2018: /* Acquire an EXCLUSIVE lock
2019: */
2020: if( locktype==EXCLUSIVE_LOCK && res ){
2021: assert( pFile->locktype>=SHARED_LOCK );
2022: res = unlockReadLock(pFile);
2023: OSTRACE(("unreadlock = %d\n", res));
2024: res = osLockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
2025: if( res ){
2026: newLocktype = EXCLUSIVE_LOCK;
2027: }else{
2028: lastErrno = osGetLastError();
2029: OSTRACE(("error-code = %d\n", lastErrno));
2030: getReadLock(pFile);
2031: }
2032: }
2033:
2034: /* If we are holding a PENDING lock that ought to be released, then
2035: ** release it now.
2036: */
2037: if( gotPendingLock && locktype==SHARED_LOCK ){
2038: osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
2039: }
2040:
2041: /* Update the state of the lock has held in the file descriptor then
2042: ** return the appropriate result code.
2043: */
2044: if( res ){
2045: rc = SQLITE_OK;
2046: }else{
2047: OSTRACE(("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
2048: locktype, newLocktype));
2049: pFile->lastErrno = lastErrno;
2050: rc = SQLITE_BUSY;
2051: }
2052: pFile->locktype = (u8)newLocktype;
2053: return rc;
2054: }
2055:
2056: /*
2057: ** This routine checks if there is a RESERVED lock held on the specified
2058: ** file by this or any other process. If such a lock is held, return
2059: ** non-zero, otherwise zero.
2060: */
2061: static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
2062: int rc;
2063: winFile *pFile = (winFile*)id;
2064:
2065: SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
2066:
2067: assert( id!=0 );
2068: if( pFile->locktype>=RESERVED_LOCK ){
2069: rc = 1;
2070: OSTRACE(("TEST WR-LOCK %d %d (local)\n", pFile->h, rc));
2071: }else{
2072: rc = osLockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
2073: if( rc ){
2074: osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
2075: }
2076: rc = !rc;
2077: OSTRACE(("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc));
2078: }
2079: *pResOut = rc;
2080: return SQLITE_OK;
2081: }
2082:
2083: /*
2084: ** Lower the locking level on file descriptor id to locktype. locktype
2085: ** must be either NO_LOCK or SHARED_LOCK.
2086: **
2087: ** If the locking level of the file descriptor is already at or below
2088: ** the requested locking level, this routine is a no-op.
2089: **
2090: ** It is not possible for this routine to fail if the second argument
2091: ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
2092: ** might return SQLITE_IOERR;
2093: */
2094: static int winUnlock(sqlite3_file *id, int locktype){
2095: int type;
2096: winFile *pFile = (winFile*)id;
2097: int rc = SQLITE_OK;
2098: assert( pFile!=0 );
2099: assert( locktype<=SHARED_LOCK );
2100: OSTRACE(("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
2101: pFile->locktype, pFile->sharedLockByte));
2102: type = pFile->locktype;
2103: if( type>=EXCLUSIVE_LOCK ){
2104: osUnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
2105: if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
2106: /* This should never happen. We should always be able to
2107: ** reacquire the read lock */
2108: rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(),
2109: "winUnlock", pFile->zPath);
2110: }
2111: }
2112: if( type>=RESERVED_LOCK ){
2113: osUnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
2114: }
2115: if( locktype==NO_LOCK && type>=SHARED_LOCK ){
2116: unlockReadLock(pFile);
2117: }
2118: if( type>=PENDING_LOCK ){
2119: osUnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
2120: }
2121: pFile->locktype = (u8)locktype;
2122: return rc;
2123: }
2124:
2125: /*
2126: ** If *pArg is inititially negative then this is a query. Set *pArg to
2127: ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set.
2128: **
2129: ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags.
2130: */
2131: static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){
2132: if( *pArg<0 ){
2133: *pArg = (pFile->ctrlFlags & mask)!=0;
2134: }else if( (*pArg)==0 ){
2135: pFile->ctrlFlags &= ~mask;
2136: }else{
2137: pFile->ctrlFlags |= mask;
2138: }
2139: }
2140:
2141: /*
2142: ** Control and query of the open file handle.
2143: */
2144: static int winFileControl(sqlite3_file *id, int op, void *pArg){
2145: winFile *pFile = (winFile*)id;
2146: switch( op ){
2147: case SQLITE_FCNTL_LOCKSTATE: {
2148: *(int*)pArg = pFile->locktype;
2149: return SQLITE_OK;
2150: }
2151: case SQLITE_LAST_ERRNO: {
2152: *(int*)pArg = (int)pFile->lastErrno;
2153: return SQLITE_OK;
2154: }
2155: case SQLITE_FCNTL_CHUNK_SIZE: {
2156: pFile->szChunk = *(int *)pArg;
2157: return SQLITE_OK;
2158: }
2159: case SQLITE_FCNTL_SIZE_HINT: {
2160: if( pFile->szChunk>0 ){
2161: sqlite3_int64 oldSz;
2162: int rc = winFileSize(id, &oldSz);
2163: if( rc==SQLITE_OK ){
2164: sqlite3_int64 newSz = *(sqlite3_int64*)pArg;
2165: if( newSz>oldSz ){
2166: SimulateIOErrorBenign(1);
2167: rc = winTruncate(id, newSz);
2168: SimulateIOErrorBenign(0);
2169: }
2170: }
2171: return rc;
2172: }
2173: return SQLITE_OK;
2174: }
2175: case SQLITE_FCNTL_PERSIST_WAL: {
2176: winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg);
2177: return SQLITE_OK;
2178: }
2179: case SQLITE_FCNTL_POWERSAFE_OVERWRITE: {
2180: winModeBit(pFile, WINFILE_PSOW, (int*)pArg);
2181: return SQLITE_OK;
2182: }
2183: case SQLITE_FCNTL_VFSNAME: {
2184: *(char**)pArg = sqlite3_mprintf("win32");
2185: return SQLITE_OK;
2186: }
2187: case SQLITE_FCNTL_WIN32_AV_RETRY: {
2188: int *a = (int*)pArg;
2189: if( a[0]>0 ){
2190: win32IoerrRetry = a[0];
2191: }else{
2192: a[0] = win32IoerrRetry;
2193: }
2194: if( a[1]>0 ){
2195: win32IoerrRetryDelay = a[1];
2196: }else{
2197: a[1] = win32IoerrRetryDelay;
2198: }
2199: return SQLITE_OK;
2200: }
2201: }
2202: return SQLITE_NOTFOUND;
2203: }
2204:
2205: /*
2206: ** Return the sector size in bytes of the underlying block device for
2207: ** the specified file. This is almost always 512 bytes, but may be
2208: ** larger for some devices.
2209: **
2210: ** SQLite code assumes this function cannot fail. It also assumes that
2211: ** if two files are created in the same file-system directory (i.e.
2212: ** a database and its journal file) that the sector size will be the
2213: ** same for both.
2214: */
2215: static int winSectorSize(sqlite3_file *id){
2216: (void)id;
2217: return SQLITE_DEFAULT_SECTOR_SIZE;
2218: }
2219:
2220: /*
2221: ** Return a vector of device characteristics.
2222: */
2223: static int winDeviceCharacteristics(sqlite3_file *id){
2224: winFile *p = (winFile*)id;
2225: return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN |
2226: ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0);
2227: }
2228:
2229: #ifndef SQLITE_OMIT_WAL
2230:
2231: /*
2232: ** Windows will only let you create file view mappings
2233: ** on allocation size granularity boundaries.
2234: ** During sqlite3_os_init() we do a GetSystemInfo()
2235: ** to get the granularity size.
2236: */
2237: SYSTEM_INFO winSysInfo;
2238:
2239: /*
2240: ** Helper functions to obtain and relinquish the global mutex. The
2241: ** global mutex is used to protect the winLockInfo objects used by
2242: ** this file, all of which may be shared by multiple threads.
2243: **
2244: ** Function winShmMutexHeld() is used to assert() that the global mutex
2245: ** is held when required. This function is only used as part of assert()
2246: ** statements. e.g.
2247: **
2248: ** winShmEnterMutex()
2249: ** assert( winShmMutexHeld() );
2250: ** winShmLeaveMutex()
2251: */
2252: static void winShmEnterMutex(void){
2253: sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
2254: }
2255: static void winShmLeaveMutex(void){
2256: sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
2257: }
2258: #ifdef SQLITE_DEBUG
2259: static int winShmMutexHeld(void) {
2260: return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
2261: }
2262: #endif
2263:
2264: /*
2265: ** Object used to represent a single file opened and mmapped to provide
2266: ** shared memory. When multiple threads all reference the same
2267: ** log-summary, each thread has its own winFile object, but they all
2268: ** point to a single instance of this object. In other words, each
2269: ** log-summary is opened only once per process.
2270: **
2271: ** winShmMutexHeld() must be true when creating or destroying
2272: ** this object or while reading or writing the following fields:
2273: **
2274: ** nRef
2275: ** pNext
2276: **
2277: ** The following fields are read-only after the object is created:
2278: **
2279: ** fid
2280: ** zFilename
2281: **
2282: ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and
2283: ** winShmMutexHeld() is true when reading or writing any other field
2284: ** in this structure.
2285: **
2286: */
2287: struct winShmNode {
2288: sqlite3_mutex *mutex; /* Mutex to access this object */
2289: char *zFilename; /* Name of the file */
2290: winFile hFile; /* File handle from winOpen */
2291:
2292: int szRegion; /* Size of shared-memory regions */
2293: int nRegion; /* Size of array apRegion */
2294: struct ShmRegion {
2295: HANDLE hMap; /* File handle from CreateFileMapping */
2296: void *pMap;
2297: } *aRegion;
2298: DWORD lastErrno; /* The Windows errno from the last I/O error */
2299:
2300: int nRef; /* Number of winShm objects pointing to this */
2301: winShm *pFirst; /* All winShm objects pointing to this */
2302: winShmNode *pNext; /* Next in list of all winShmNode objects */
2303: #ifdef SQLITE_DEBUG
2304: u8 nextShmId; /* Next available winShm.id value */
2305: #endif
2306: };
2307:
2308: /*
2309: ** A global array of all winShmNode objects.
2310: **
2311: ** The winShmMutexHeld() must be true while reading or writing this list.
2312: */
2313: static winShmNode *winShmNodeList = 0;
2314:
2315: /*
2316: ** Structure used internally by this VFS to record the state of an
2317: ** open shared memory connection.
2318: **
2319: ** The following fields are initialized when this object is created and
2320: ** are read-only thereafter:
2321: **
2322: ** winShm.pShmNode
2323: ** winShm.id
2324: **
2325: ** All other fields are read/write. The winShm.pShmNode->mutex must be held
2326: ** while accessing any read/write fields.
2327: */
2328: struct winShm {
2329: winShmNode *pShmNode; /* The underlying winShmNode object */
2330: winShm *pNext; /* Next winShm with the same winShmNode */
2331: u8 hasMutex; /* True if holding the winShmNode mutex */
2332: u16 sharedMask; /* Mask of shared locks held */
2333: u16 exclMask; /* Mask of exclusive locks held */
2334: #ifdef SQLITE_DEBUG
2335: u8 id; /* Id of this connection with its winShmNode */
2336: #endif
2337: };
2338:
2339: /*
2340: ** Constants used for locking
2341: */
2342: #define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */
2343: #define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */
2344:
2345: /*
2346: ** Apply advisory locks for all n bytes beginning at ofst.
2347: */
2348: #define _SHM_UNLCK 1
2349: #define _SHM_RDLCK 2
2350: #define _SHM_WRLCK 3
2351: static int winShmSystemLock(
2352: winShmNode *pFile, /* Apply locks to this open shared-memory segment */
2353: int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */
2354: int ofst, /* Offset to first byte to be locked/unlocked */
2355: int nByte /* Number of bytes to lock or unlock */
2356: ){
2357: OVERLAPPED ovlp;
2358: DWORD dwFlags;
2359: int rc = 0; /* Result code form Lock/UnlockFileEx() */
2360:
2361: /* Access to the winShmNode object is serialized by the caller */
2362: assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
2363:
2364: /* Initialize the locking parameters */
2365: dwFlags = LOCKFILE_FAIL_IMMEDIATELY;
2366: if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
2367:
2368: memset(&ovlp, 0, sizeof(OVERLAPPED));
2369: ovlp.Offset = ofst;
2370:
2371: /* Release/Acquire the system-level lock */
2372: if( lockType==_SHM_UNLCK ){
2373: rc = osUnlockFileEx(pFile->hFile.h, 0, nByte, 0, &ovlp);
2374: }else{
2375: rc = osLockFileEx(pFile->hFile.h, dwFlags, 0, nByte, 0, &ovlp);
2376: }
2377:
2378: if( rc!= 0 ){
2379: rc = SQLITE_OK;
2380: }else{
2381: pFile->lastErrno = osGetLastError();
2382: rc = SQLITE_BUSY;
2383: }
2384:
2385: OSTRACE(("SHM-LOCK %d %s %s 0x%08lx\n",
2386: pFile->hFile.h,
2387: rc==SQLITE_OK ? "ok" : "failed",
2388: lockType==_SHM_UNLCK ? "UnlockFileEx" : "LockFileEx",
2389: pFile->lastErrno));
2390:
2391: return rc;
2392: }
2393:
2394: /* Forward references to VFS methods */
2395: static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*);
2396: static int winDelete(sqlite3_vfs *,const char*,int);
2397:
2398: /*
2399: ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0.
2400: **
2401: ** This is not a VFS shared-memory method; it is a utility function called
2402: ** by VFS shared-memory methods.
2403: */
2404: static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
2405: winShmNode **pp;
2406: winShmNode *p;
2407: BOOL bRc;
2408: assert( winShmMutexHeld() );
2409: pp = &winShmNodeList;
2410: while( (p = *pp)!=0 ){
2411: if( p->nRef==0 ){
2412: int i;
2413: if( p->mutex ) sqlite3_mutex_free(p->mutex);
2414: for(i=0; i<p->nRegion; i++){
2415: bRc = osUnmapViewOfFile(p->aRegion[i].pMap);
2416: OSTRACE(("SHM-PURGE pid-%d unmap region=%d %s\n",
2417: (int)osGetCurrentProcessId(), i,
2418: bRc ? "ok" : "failed"));
2419: bRc = osCloseHandle(p->aRegion[i].hMap);
2420: OSTRACE(("SHM-PURGE pid-%d close region=%d %s\n",
2421: (int)osGetCurrentProcessId(), i,
2422: bRc ? "ok" : "failed"));
2423: }
2424: if( p->hFile.h != INVALID_HANDLE_VALUE ){
2425: SimulateIOErrorBenign(1);
2426: winClose((sqlite3_file *)&p->hFile);
2427: SimulateIOErrorBenign(0);
2428: }
2429: if( deleteFlag ){
2430: SimulateIOErrorBenign(1);
2431: sqlite3BeginBenignMalloc();
2432: winDelete(pVfs, p->zFilename, 0);
2433: sqlite3EndBenignMalloc();
2434: SimulateIOErrorBenign(0);
2435: }
2436: *pp = p->pNext;
2437: sqlite3_free(p->aRegion);
2438: sqlite3_free(p);
2439: }else{
2440: pp = &p->pNext;
2441: }
2442: }
2443: }
2444:
2445: /*
2446: ** Open the shared-memory area associated with database file pDbFd.
2447: **
2448: ** When opening a new shared-memory file, if no other instances of that
2449: ** file are currently open, in this process or in other processes, then
2450: ** the file must be truncated to zero length or have its header cleared.
2451: */
2452: static int winOpenSharedMemory(winFile *pDbFd){
2453: struct winShm *p; /* The connection to be opened */
2454: struct winShmNode *pShmNode = 0; /* The underlying mmapped file */
2455: int rc; /* Result code */
2456: struct winShmNode *pNew; /* Newly allocated winShmNode */
2457: int nName; /* Size of zName in bytes */
2458:
2459: assert( pDbFd->pShm==0 ); /* Not previously opened */
2460:
2461: /* Allocate space for the new sqlite3_shm object. Also speculatively
2462: ** allocate space for a new winShmNode and filename.
2463: */
2464: p = sqlite3_malloc( sizeof(*p) );
2465: if( p==0 ) return SQLITE_IOERR_NOMEM;
2466: memset(p, 0, sizeof(*p));
2467: nName = sqlite3Strlen30(pDbFd->zPath);
2468: pNew = sqlite3_malloc( sizeof(*pShmNode) + nName + 17 );
2469: if( pNew==0 ){
2470: sqlite3_free(p);
2471: return SQLITE_IOERR_NOMEM;
2472: }
2473: memset(pNew, 0, sizeof(*pNew) + nName + 17);
2474: pNew->zFilename = (char*)&pNew[1];
2475: sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath);
2476: sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename);
2477:
2478: /* Look to see if there is an existing winShmNode that can be used.
2479: ** If no matching winShmNode currently exists, create a new one.
2480: */
2481: winShmEnterMutex();
2482: for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){
2483: /* TBD need to come up with better match here. Perhaps
2484: ** use FILE_ID_BOTH_DIR_INFO Structure.
2485: */
2486: if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break;
2487: }
2488: if( pShmNode ){
2489: sqlite3_free(pNew);
2490: }else{
2491: pShmNode = pNew;
2492: pNew = 0;
2493: ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE;
2494: pShmNode->pNext = winShmNodeList;
2495: winShmNodeList = pShmNode;
2496:
2497: pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
2498: if( pShmNode->mutex==0 ){
2499: rc = SQLITE_IOERR_NOMEM;
2500: goto shm_open_err;
2501: }
2502:
2503: rc = winOpen(pDbFd->pVfs,
2504: pShmNode->zFilename, /* Name of the file (UTF-8) */
2505: (sqlite3_file*)&pShmNode->hFile, /* File handle here */
2506: SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
2507: 0);
2508: if( SQLITE_OK!=rc ){
2509: goto shm_open_err;
2510: }
2511:
2512: /* Check to see if another process is holding the dead-man switch.
2513: ** If not, truncate the file to zero length.
2514: */
2515: if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){
2516: rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0);
2517: if( rc!=SQLITE_OK ){
2518: rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(),
2519: "winOpenShm", pDbFd->zPath);
2520: }
2521: }
2522: if( rc==SQLITE_OK ){
2523: winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
2524: rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1);
2525: }
2526: if( rc ) goto shm_open_err;
2527: }
2528:
2529: /* Make the new connection a child of the winShmNode */
2530: p->pShmNode = pShmNode;
2531: #ifdef SQLITE_DEBUG
2532: p->id = pShmNode->nextShmId++;
2533: #endif
2534: pShmNode->nRef++;
2535: pDbFd->pShm = p;
2536: winShmLeaveMutex();
2537:
2538: /* The reference count on pShmNode has already been incremented under
2539: ** the cover of the winShmEnterMutex() mutex and the pointer from the
2540: ** new (struct winShm) object to the pShmNode has been set. All that is
2541: ** left to do is to link the new object into the linked list starting
2542: ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex
2543: ** mutex.
2544: */
2545: sqlite3_mutex_enter(pShmNode->mutex);
2546: p->pNext = pShmNode->pFirst;
2547: pShmNode->pFirst = p;
2548: sqlite3_mutex_leave(pShmNode->mutex);
2549: return SQLITE_OK;
2550:
2551: /* Jump here on any error */
2552: shm_open_err:
2553: winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1);
2554: winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */
2555: sqlite3_free(p);
2556: sqlite3_free(pNew);
2557: winShmLeaveMutex();
2558: return rc;
2559: }
2560:
2561: /*
2562: ** Close a connection to shared-memory. Delete the underlying
2563: ** storage if deleteFlag is true.
2564: */
2565: static int winShmUnmap(
2566: sqlite3_file *fd, /* Database holding shared memory */
2567: int deleteFlag /* Delete after closing if true */
2568: ){
2569: winFile *pDbFd; /* Database holding shared-memory */
2570: winShm *p; /* The connection to be closed */
2571: winShmNode *pShmNode; /* The underlying shared-memory file */
2572: winShm **pp; /* For looping over sibling connections */
2573:
2574: pDbFd = (winFile*)fd;
2575: p = pDbFd->pShm;
2576: if( p==0 ) return SQLITE_OK;
2577: pShmNode = p->pShmNode;
2578:
2579: /* Remove connection p from the set of connections associated
2580: ** with pShmNode */
2581: sqlite3_mutex_enter(pShmNode->mutex);
2582: for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
2583: *pp = p->pNext;
2584:
2585: /* Free the connection p */
2586: sqlite3_free(p);
2587: pDbFd->pShm = 0;
2588: sqlite3_mutex_leave(pShmNode->mutex);
2589:
2590: /* If pShmNode->nRef has reached 0, then close the underlying
2591: ** shared-memory file, too */
2592: winShmEnterMutex();
2593: assert( pShmNode->nRef>0 );
2594: pShmNode->nRef--;
2595: if( pShmNode->nRef==0 ){
2596: winShmPurge(pDbFd->pVfs, deleteFlag);
2597: }
2598: winShmLeaveMutex();
2599:
2600: return SQLITE_OK;
2601: }
2602:
2603: /*
2604: ** Change the lock state for a shared-memory segment.
2605: */
2606: static int winShmLock(
2607: sqlite3_file *fd, /* Database file holding the shared memory */
2608: int ofst, /* First lock to acquire or release */
2609: int n, /* Number of locks to acquire or release */
2610: int flags /* What to do with the lock */
2611: ){
2612: winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */
2613: winShm *p = pDbFd->pShm; /* The shared memory being locked */
2614: winShm *pX; /* For looping over all siblings */
2615: winShmNode *pShmNode = p->pShmNode;
2616: int rc = SQLITE_OK; /* Result code */
2617: u16 mask; /* Mask of locks to take or release */
2618:
2619: assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK );
2620: assert( n>=1 );
2621: assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED)
2622: || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE)
2623: || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED)
2624: || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) );
2625: assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 );
2626:
2627: mask = (u16)((1U<<(ofst+n)) - (1U<<ofst));
2628: assert( n>1 || mask==(1<<ofst) );
2629: sqlite3_mutex_enter(pShmNode->mutex);
2630: if( flags & SQLITE_SHM_UNLOCK ){
2631: u16 allMask = 0; /* Mask of locks held by siblings */
2632:
2633: /* See if any siblings hold this same lock */
2634: for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
2635: if( pX==p ) continue;
2636: assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
2637: allMask |= pX->sharedMask;
2638: }
2639:
2640: /* Unlock the system-level locks */
2641: if( (mask & allMask)==0 ){
2642: rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n);
2643: }else{
2644: rc = SQLITE_OK;
2645: }
2646:
2647: /* Undo the local locks */
2648: if( rc==SQLITE_OK ){
2649: p->exclMask &= ~mask;
2650: p->sharedMask &= ~mask;
2651: }
2652: }else if( flags & SQLITE_SHM_SHARED ){
2653: u16 allShared = 0; /* Union of locks held by connections other than "p" */
2654:
2655: /* Find out which shared locks are already held by sibling connections.
2656: ** If any sibling already holds an exclusive lock, go ahead and return
2657: ** SQLITE_BUSY.
2658: */
2659: for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
2660: if( (pX->exclMask & mask)!=0 ){
2661: rc = SQLITE_BUSY;
2662: break;
2663: }
2664: allShared |= pX->sharedMask;
2665: }
2666:
2667: /* Get shared locks at the system level, if necessary */
2668: if( rc==SQLITE_OK ){
2669: if( (allShared & mask)==0 ){
2670: rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n);
2671: }else{
2672: rc = SQLITE_OK;
2673: }
2674: }
2675:
2676: /* Get the local shared locks */
2677: if( rc==SQLITE_OK ){
2678: p->sharedMask |= mask;
2679: }
2680: }else{
2681: /* Make sure no sibling connections hold locks that will block this
2682: ** lock. If any do, return SQLITE_BUSY right away.
2683: */
2684: for(pX=pShmNode->pFirst; pX; pX=pX->pNext){
2685: if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){
2686: rc = SQLITE_BUSY;
2687: break;
2688: }
2689: }
2690:
2691: /* Get the exclusive locks at the system level. Then if successful
2692: ** also mark the local connection as being locked.
2693: */
2694: if( rc==SQLITE_OK ){
2695: rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n);
2696: if( rc==SQLITE_OK ){
2697: assert( (p->sharedMask & mask)==0 );
2698: p->exclMask |= mask;
2699: }
2700: }
2701: }
2702: sqlite3_mutex_leave(pShmNode->mutex);
2703: OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x %s\n",
2704: p->id, (int)osGetCurrentProcessId(), p->sharedMask, p->exclMask,
2705: rc ? "failed" : "ok"));
2706: return rc;
2707: }
2708:
2709: /*
2710: ** Implement a memory barrier or memory fence on shared memory.
2711: **
2712: ** All loads and stores begun before the barrier must complete before
2713: ** any load or store begun after the barrier.
2714: */
2715: static void winShmBarrier(
2716: sqlite3_file *fd /* Database holding the shared memory */
2717: ){
2718: UNUSED_PARAMETER(fd);
2719: /* MemoryBarrier(); // does not work -- do not know why not */
2720: winShmEnterMutex();
2721: winShmLeaveMutex();
2722: }
2723:
2724: /*
2725: ** This function is called to obtain a pointer to region iRegion of the
2726: ** shared-memory associated with the database file fd. Shared-memory regions
2727: ** are numbered starting from zero. Each shared-memory region is szRegion
2728: ** bytes in size.
2729: **
2730: ** If an error occurs, an error code is returned and *pp is set to NULL.
2731: **
2732: ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
2733: ** region has not been allocated (by any client, including one running in a
2734: ** separate process), then *pp is set to NULL and SQLITE_OK returned. If
2735: ** isWrite is non-zero and the requested shared-memory region has not yet
2736: ** been allocated, it is allocated by this function.
2737: **
2738: ** If the shared-memory region has already been allocated or is allocated by
2739: ** this call as described above, then it is mapped into this processes
2740: ** address space (if it is not already), *pp is set to point to the mapped
2741: ** memory and SQLITE_OK returned.
2742: */
2743: static int winShmMap(
2744: sqlite3_file *fd, /* Handle open on database file */
2745: int iRegion, /* Region to retrieve */
2746: int szRegion, /* Size of regions */
2747: int isWrite, /* True to extend file if necessary */
2748: void volatile **pp /* OUT: Mapped memory */
2749: ){
2750: winFile *pDbFd = (winFile*)fd;
2751: winShm *p = pDbFd->pShm;
2752: winShmNode *pShmNode;
2753: int rc = SQLITE_OK;
2754:
2755: if( !p ){
2756: rc = winOpenSharedMemory(pDbFd);
2757: if( rc!=SQLITE_OK ) return rc;
2758: p = pDbFd->pShm;
2759: }
2760: pShmNode = p->pShmNode;
2761:
2762: sqlite3_mutex_enter(pShmNode->mutex);
2763: assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
2764:
2765: if( pShmNode->nRegion<=iRegion ){
2766: struct ShmRegion *apNew; /* New aRegion[] array */
2767: int nByte = (iRegion+1)*szRegion; /* Minimum required file size */
2768: sqlite3_int64 sz; /* Current size of wal-index file */
2769:
2770: pShmNode->szRegion = szRegion;
2771:
2772: /* The requested region is not mapped into this processes address space.
2773: ** Check to see if it has been allocated (i.e. if the wal-index file is
2774: ** large enough to contain the requested region).
2775: */
2776: rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz);
2777: if( rc!=SQLITE_OK ){
2778: rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
2779: "winShmMap1", pDbFd->zPath);
2780: goto shmpage_out;
2781: }
2782:
2783: if( sz<nByte ){
2784: /* The requested memory region does not exist. If isWrite is set to
2785: ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
2786: **
2787: ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
2788: ** the requested memory region.
2789: */
2790: if( !isWrite ) goto shmpage_out;
2791: rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte);
2792: if( rc!=SQLITE_OK ){
2793: rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(),
2794: "winShmMap2", pDbFd->zPath);
2795: goto shmpage_out;
2796: }
2797: }
2798:
2799: /* Map the requested memory region into this processes address space. */
2800: apNew = (struct ShmRegion *)sqlite3_realloc(
2801: pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
2802: );
2803: if( !apNew ){
2804: rc = SQLITE_IOERR_NOMEM;
2805: goto shmpage_out;
2806: }
2807: pShmNode->aRegion = apNew;
2808:
2809: while( pShmNode->nRegion<=iRegion ){
2810: HANDLE hMap; /* file-mapping handle */
2811: void *pMap = 0; /* Mapped memory region */
2812:
2813: hMap = osCreateFileMapping(pShmNode->hFile.h,
2814: NULL, PAGE_READWRITE, 0, nByte, NULL
2815: );
2816: OSTRACE(("SHM-MAP pid-%d create region=%d nbyte=%d %s\n",
2817: (int)osGetCurrentProcessId(), pShmNode->nRegion, nByte,
2818: hMap ? "ok" : "failed"));
2819: if( hMap ){
2820: int iOffset = pShmNode->nRegion*szRegion;
2821: int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
2822: pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ,
2823: 0, iOffset - iOffsetShift, szRegion + iOffsetShift
2824: );
2825: OSTRACE(("SHM-MAP pid-%d map region=%d offset=%d size=%d %s\n",
2826: (int)osGetCurrentProcessId(), pShmNode->nRegion, iOffset,
2827: szRegion, pMap ? "ok" : "failed"));
2828: }
2829: if( !pMap ){
2830: pShmNode->lastErrno = osGetLastError();
2831: rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno,
2832: "winShmMap3", pDbFd->zPath);
2833: if( hMap ) osCloseHandle(hMap);
2834: goto shmpage_out;
2835: }
2836:
2837: pShmNode->aRegion[pShmNode->nRegion].pMap = pMap;
2838: pShmNode->aRegion[pShmNode->nRegion].hMap = hMap;
2839: pShmNode->nRegion++;
2840: }
2841: }
2842:
2843: shmpage_out:
2844: if( pShmNode->nRegion>iRegion ){
2845: int iOffset = iRegion*szRegion;
2846: int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity;
2847: char *p = (char *)pShmNode->aRegion[iRegion].pMap;
2848: *pp = (void *)&p[iOffsetShift];
2849: }else{
2850: *pp = 0;
2851: }
2852: sqlite3_mutex_leave(pShmNode->mutex);
2853: return rc;
2854: }
2855:
2856: #else
2857: # define winShmMap 0
2858: # define winShmLock 0
2859: # define winShmBarrier 0
2860: # define winShmUnmap 0
2861: #endif /* #ifndef SQLITE_OMIT_WAL */
2862:
2863: /*
2864: ** Here ends the implementation of all sqlite3_file methods.
2865: **
2866: ********************** End sqlite3_file Methods *******************************
2867: ******************************************************************************/
2868:
2869: /*
2870: ** This vector defines all the methods that can operate on an
2871: ** sqlite3_file for win32.
2872: */
2873: static const sqlite3_io_methods winIoMethod = {
2874: 2, /* iVersion */
2875: winClose, /* xClose */
2876: winRead, /* xRead */
2877: winWrite, /* xWrite */
2878: winTruncate, /* xTruncate */
2879: winSync, /* xSync */
2880: winFileSize, /* xFileSize */
2881: winLock, /* xLock */
2882: winUnlock, /* xUnlock */
2883: winCheckReservedLock, /* xCheckReservedLock */
2884: winFileControl, /* xFileControl */
2885: winSectorSize, /* xSectorSize */
2886: winDeviceCharacteristics, /* xDeviceCharacteristics */
2887: winShmMap, /* xShmMap */
2888: winShmLock, /* xShmLock */
2889: winShmBarrier, /* xShmBarrier */
2890: winShmUnmap /* xShmUnmap */
2891: };
2892:
2893: /****************************************************************************
2894: **************************** sqlite3_vfs methods ****************************
2895: **
2896: ** This division contains the implementation of methods on the
2897: ** sqlite3_vfs object.
2898: */
2899:
2900: /*
2901: ** Convert a UTF-8 filename into whatever form the underlying
2902: ** operating system wants filenames in. Space to hold the result
2903: ** is obtained from malloc and must be freed by the calling
2904: ** function.
2905: */
2906: static void *convertUtf8Filename(const char *zFilename){
2907: void *zConverted = 0;
2908: if( isNT() ){
2909: zConverted = utf8ToUnicode(zFilename);
2910: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
2911: */
2912: #if SQLITE_OS_WINCE==0
2913: }else{
2914: zConverted = sqlite3_win32_utf8_to_mbcs(zFilename);
2915: #endif
2916: }
2917: /* caller will handle out of memory */
2918: return zConverted;
2919: }
2920:
2921: /*
2922: ** Create a temporary file name in zBuf. zBuf must be big enough to
2923: ** hold at pVfs->mxPathname characters.
2924: */
2925: static int getTempname(int nBuf, char *zBuf){
2926: static char zChars[] =
2927: "abcdefghijklmnopqrstuvwxyz"
2928: "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2929: "0123456789";
2930: size_t i, j;
2931: char zTempPath[MAX_PATH+2];
2932:
2933: /* It's odd to simulate an io-error here, but really this is just
2934: ** using the io-error infrastructure to test that SQLite handles this
2935: ** function failing.
2936: */
2937: SimulateIOError( return SQLITE_IOERR );
2938:
2939: if( sqlite3_temp_directory ){
2940: sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", sqlite3_temp_directory);
2941: }else if( isNT() ){
2942: char *zMulti;
2943: WCHAR zWidePath[MAX_PATH];
2944: osGetTempPathW(MAX_PATH-30, zWidePath);
2945: zMulti = unicodeToUtf8(zWidePath);
2946: if( zMulti ){
2947: sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zMulti);
2948: sqlite3_free(zMulti);
2949: }else{
2950: return SQLITE_IOERR_NOMEM;
2951: }
2952: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
2953: ** Since the ANSI version of these Windows API do not exist for WINCE,
2954: ** it's important to not reference them for WINCE builds.
2955: */
2956: #if SQLITE_OS_WINCE==0
2957: }else{
2958: char *zUtf8;
2959: char zMbcsPath[MAX_PATH];
2960: osGetTempPathA(MAX_PATH-30, zMbcsPath);
2961: zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath);
2962: if( zUtf8 ){
2963: sqlite3_snprintf(MAX_PATH-30, zTempPath, "%s", zUtf8);
2964: sqlite3_free(zUtf8);
2965: }else{
2966: return SQLITE_IOERR_NOMEM;
2967: }
2968: #endif
2969: }
2970:
2971: /* Check that the output buffer is large enough for the temporary file
2972: ** name. If it is not, return SQLITE_ERROR.
2973: */
2974: if( (sqlite3Strlen30(zTempPath) + sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX) + 18) >= nBuf ){
2975: return SQLITE_ERROR;
2976: }
2977:
2978: for(i=sqlite3Strlen30(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
2979: zTempPath[i] = 0;
2980:
2981: sqlite3_snprintf(nBuf-18, zBuf,
2982: "%s\\"SQLITE_TEMP_FILE_PREFIX, zTempPath);
2983: j = sqlite3Strlen30(zBuf);
2984: sqlite3_randomness(15, &zBuf[j]);
2985: for(i=0; i<15; i++, j++){
2986: zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
2987: }
2988: zBuf[j] = 0;
2989: zBuf[j+1] = 0;
2990:
2991: OSTRACE(("TEMP FILENAME: %s\n", zBuf));
2992: return SQLITE_OK;
2993: }
2994:
2995: /*
2996: ** Open a file.
2997: */
2998: static int winOpen(
2999: sqlite3_vfs *pVfs, /* Not used */
3000: const char *zName, /* Name of the file (UTF-8) */
3001: sqlite3_file *id, /* Write the SQLite file handle here */
3002: int flags, /* Open mode flags */
3003: int *pOutFlags /* Status return flags */
3004: ){
3005: HANDLE h;
3006: DWORD lastErrno;
3007: DWORD dwDesiredAccess;
3008: DWORD dwShareMode;
3009: DWORD dwCreationDisposition;
3010: DWORD dwFlagsAndAttributes = 0;
3011: #if SQLITE_OS_WINCE
3012: int isTemp = 0;
3013: #endif
3014: winFile *pFile = (winFile*)id;
3015: void *zConverted; /* Filename in OS encoding */
3016: const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */
3017: int cnt = 0;
3018:
3019: /* If argument zPath is a NULL pointer, this function is required to open
3020: ** a temporary file. Use this buffer to store the file name in.
3021: */
3022: char zTmpname[MAX_PATH+2]; /* Buffer used to create temp filename */
3023:
3024: int rc = SQLITE_OK; /* Function Return Code */
3025: #if !defined(NDEBUG) || SQLITE_OS_WINCE
3026: int eType = flags&0xFFFFFF00; /* Type of file to open */
3027: #endif
3028:
3029: int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE);
3030: int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE);
3031: int isCreate = (flags & SQLITE_OPEN_CREATE);
3032: #ifndef NDEBUG
3033: int isReadonly = (flags & SQLITE_OPEN_READONLY);
3034: #endif
3035: int isReadWrite = (flags & SQLITE_OPEN_READWRITE);
3036:
3037: #ifndef NDEBUG
3038: int isOpenJournal = (isCreate && (
3039: eType==SQLITE_OPEN_MASTER_JOURNAL
3040: || eType==SQLITE_OPEN_MAIN_JOURNAL
3041: || eType==SQLITE_OPEN_WAL
3042: ));
3043: #endif
3044:
3045: /* Check the following statements are true:
3046: **
3047: ** (a) Exactly one of the READWRITE and READONLY flags must be set, and
3048: ** (b) if CREATE is set, then READWRITE must also be set, and
3049: ** (c) if EXCLUSIVE is set, then CREATE must also be set.
3050: ** (d) if DELETEONCLOSE is set, then CREATE must also be set.
3051: */
3052: assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
3053: assert(isCreate==0 || isReadWrite);
3054: assert(isExclusive==0 || isCreate);
3055: assert(isDelete==0 || isCreate);
3056:
3057: /* The main DB, main journal, WAL file and master journal are never
3058: ** automatically deleted. Nor are they ever temporary files. */
3059: assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
3060: assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
3061: assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
3062: assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
3063:
3064: /* Assert that the upper layer has set one of the "file-type" flags. */
3065: assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
3066: || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
3067: || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
3068: || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
3069: );
3070:
3071: assert( id!=0 );
3072: UNUSED_PARAMETER(pVfs);
3073:
3074: pFile->h = INVALID_HANDLE_VALUE;
3075:
3076: /* If the second argument to this function is NULL, generate a
3077: ** temporary file name to use
3078: */
3079: if( !zUtf8Name ){
3080: assert(isDelete && !isOpenJournal);
3081: rc = getTempname(MAX_PATH+2, zTmpname);
3082: if( rc!=SQLITE_OK ){
3083: return rc;
3084: }
3085: zUtf8Name = zTmpname;
3086: }
3087:
3088: /* Database filenames are double-zero terminated if they are not
3089: ** URIs with parameters. Hence, they can always be passed into
3090: ** sqlite3_uri_parameter().
3091: */
3092: assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) ||
3093: zUtf8Name[strlen(zUtf8Name)+1]==0 );
3094:
3095: /* Convert the filename to the system encoding. */
3096: zConverted = convertUtf8Filename(zUtf8Name);
3097: if( zConverted==0 ){
3098: return SQLITE_IOERR_NOMEM;
3099: }
3100:
3101: if( isReadWrite ){
3102: dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
3103: }else{
3104: dwDesiredAccess = GENERIC_READ;
3105: }
3106:
3107: /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is
3108: ** created. SQLite doesn't use it to indicate "exclusive access"
3109: ** as it is usually understood.
3110: */
3111: if( isExclusive ){
3112: /* Creates a new file, only if it does not already exist. */
3113: /* If the file exists, it fails. */
3114: dwCreationDisposition = CREATE_NEW;
3115: }else if( isCreate ){
3116: /* Open existing file, or create if it doesn't exist */
3117: dwCreationDisposition = OPEN_ALWAYS;
3118: }else{
3119: /* Opens a file, only if it exists. */
3120: dwCreationDisposition = OPEN_EXISTING;
3121: }
3122:
3123: dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
3124:
3125: if( isDelete ){
3126: #if SQLITE_OS_WINCE
3127: dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN;
3128: isTemp = 1;
3129: #else
3130: dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY
3131: | FILE_ATTRIBUTE_HIDDEN
3132: | FILE_FLAG_DELETE_ON_CLOSE;
3133: #endif
3134: }else{
3135: dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
3136: }
3137: /* Reports from the internet are that performance is always
3138: ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */
3139: #if SQLITE_OS_WINCE
3140: dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
3141: #endif
3142:
3143: if( isNT() ){
3144: while( (h = osCreateFileW((LPCWSTR)zConverted,
3145: dwDesiredAccess,
3146: dwShareMode, NULL,
3147: dwCreationDisposition,
3148: dwFlagsAndAttributes,
3149: NULL))==INVALID_HANDLE_VALUE &&
3150: retryIoerr(&cnt, &lastErrno) ){}
3151: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3152: ** Since the ANSI version of these Windows API do not exist for WINCE,
3153: ** it's important to not reference them for WINCE builds.
3154: */
3155: #if SQLITE_OS_WINCE==0
3156: }else{
3157: while( (h = osCreateFileA((LPCSTR)zConverted,
3158: dwDesiredAccess,
3159: dwShareMode, NULL,
3160: dwCreationDisposition,
3161: dwFlagsAndAttributes,
3162: NULL))==INVALID_HANDLE_VALUE &&
3163: retryIoerr(&cnt, &lastErrno) ){}
3164: #endif
3165: }
3166:
3167: logIoerr(cnt);
3168:
3169: OSTRACE(("OPEN %d %s 0x%lx %s\n",
3170: h, zName, dwDesiredAccess,
3171: h==INVALID_HANDLE_VALUE ? "failed" : "ok"));
3172:
3173: if( h==INVALID_HANDLE_VALUE ){
3174: pFile->lastErrno = lastErrno;
3175: winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name);
3176: sqlite3_free(zConverted);
3177: if( isReadWrite && !isExclusive ){
3178: return winOpen(pVfs, zName, id,
3179: ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
3180: }else{
3181: return SQLITE_CANTOPEN_BKPT;
3182: }
3183: }
3184:
3185: if( pOutFlags ){
3186: if( isReadWrite ){
3187: *pOutFlags = SQLITE_OPEN_READWRITE;
3188: }else{
3189: *pOutFlags = SQLITE_OPEN_READONLY;
3190: }
3191: }
3192:
3193: memset(pFile, 0, sizeof(*pFile));
3194: pFile->pMethod = &winIoMethod;
3195: pFile->h = h;
3196: pFile->lastErrno = NO_ERROR;
3197: pFile->pVfs = pVfs;
3198: pFile->pShm = 0;
3199: pFile->zPath = zName;
3200: if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
3201: pFile->ctrlFlags |= WINFILE_PSOW;
3202: }
3203:
3204: #if SQLITE_OS_WINCE
3205: if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
3206: && !winceCreateLock(zName, pFile)
3207: ){
3208: osCloseHandle(h);
3209: sqlite3_free(zConverted);
3210: return SQLITE_CANTOPEN_BKPT;
3211: }
3212: if( isTemp ){
3213: pFile->zDeleteOnClose = zConverted;
3214: }else
3215: #endif
3216: {
3217: sqlite3_free(zConverted);
3218: }
3219:
3220: OpenCounter(+1);
3221: return rc;
3222: }
3223:
3224: /*
3225: ** Delete the named file.
3226: **
3227: ** Note that Windows does not allow a file to be deleted if some other
3228: ** process has it open. Sometimes a virus scanner or indexing program
3229: ** will open a journal file shortly after it is created in order to do
3230: ** whatever it does. While this other process is holding the
3231: ** file open, we will be unable to delete it. To work around this
3232: ** problem, we delay 100 milliseconds and try to delete again. Up
3233: ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving
3234: ** up and returning an error.
3235: */
3236: static int winDelete(
3237: sqlite3_vfs *pVfs, /* Not used on win32 */
3238: const char *zFilename, /* Name of file to delete */
3239: int syncDir /* Not used on win32 */
3240: ){
3241: int cnt = 0;
3242: int rc;
3243: DWORD lastErrno;
3244: void *zConverted;
3245: UNUSED_PARAMETER(pVfs);
3246: UNUSED_PARAMETER(syncDir);
3247:
3248: SimulateIOError(return SQLITE_IOERR_DELETE);
3249: zConverted = convertUtf8Filename(zFilename);
3250: if( zConverted==0 ){
3251: return SQLITE_IOERR_NOMEM;
3252: }
3253: if( isNT() ){
3254: rc = 1;
3255: while( osGetFileAttributesW(zConverted)!=INVALID_FILE_ATTRIBUTES &&
3256: (rc = osDeleteFileW(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
3257: rc = rc ? SQLITE_OK : SQLITE_ERROR;
3258: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3259: ** Since the ANSI version of these Windows API do not exist for WINCE,
3260: ** it's important to not reference them for WINCE builds.
3261: */
3262: #if SQLITE_OS_WINCE==0
3263: }else{
3264: rc = 1;
3265: while( osGetFileAttributesA(zConverted)!=INVALID_FILE_ATTRIBUTES &&
3266: (rc = osDeleteFileA(zConverted))==0 && retryIoerr(&cnt, &lastErrno) ){}
3267: rc = rc ? SQLITE_OK : SQLITE_ERROR;
3268: #endif
3269: }
3270: if( rc ){
3271: rc = winLogError(SQLITE_IOERR_DELETE, lastErrno,
3272: "winDelete", zFilename);
3273: }else{
3274: logIoerr(cnt);
3275: }
3276: sqlite3_free(zConverted);
3277: OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" )));
3278: return rc;
3279: }
3280:
3281: /*
3282: ** Check the existance and status of a file.
3283: */
3284: static int winAccess(
3285: sqlite3_vfs *pVfs, /* Not used on win32 */
3286: const char *zFilename, /* Name of file to check */
3287: int flags, /* Type of test to make on this file */
3288: int *pResOut /* OUT: Result */
3289: ){
3290: DWORD attr;
3291: int rc = 0;
3292: DWORD lastErrno;
3293: void *zConverted;
3294: UNUSED_PARAMETER(pVfs);
3295:
3296: SimulateIOError( return SQLITE_IOERR_ACCESS; );
3297: zConverted = convertUtf8Filename(zFilename);
3298: if( zConverted==0 ){
3299: return SQLITE_IOERR_NOMEM;
3300: }
3301: if( isNT() ){
3302: int cnt = 0;
3303: WIN32_FILE_ATTRIBUTE_DATA sAttrData;
3304: memset(&sAttrData, 0, sizeof(sAttrData));
3305: while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted,
3306: GetFileExInfoStandard,
3307: &sAttrData)) && retryIoerr(&cnt, &lastErrno) ){}
3308: if( rc ){
3309: /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file
3310: ** as if it does not exist.
3311: */
3312: if( flags==SQLITE_ACCESS_EXISTS
3313: && sAttrData.nFileSizeHigh==0
3314: && sAttrData.nFileSizeLow==0 ){
3315: attr = INVALID_FILE_ATTRIBUTES;
3316: }else{
3317: attr = sAttrData.dwFileAttributes;
3318: }
3319: }else{
3320: logIoerr(cnt);
3321: if( lastErrno!=ERROR_FILE_NOT_FOUND ){
3322: winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", zFilename);
3323: sqlite3_free(zConverted);
3324: return SQLITE_IOERR_ACCESS;
3325: }else{
3326: attr = INVALID_FILE_ATTRIBUTES;
3327: }
3328: }
3329: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3330: ** Since the ANSI version of these Windows API do not exist for WINCE,
3331: ** it's important to not reference them for WINCE builds.
3332: */
3333: #if SQLITE_OS_WINCE==0
3334: }else{
3335: attr = osGetFileAttributesA((char*)zConverted);
3336: #endif
3337: }
3338: sqlite3_free(zConverted);
3339: switch( flags ){
3340: case SQLITE_ACCESS_READ:
3341: case SQLITE_ACCESS_EXISTS:
3342: rc = attr!=INVALID_FILE_ATTRIBUTES;
3343: break;
3344: case SQLITE_ACCESS_READWRITE:
3345: rc = attr!=INVALID_FILE_ATTRIBUTES &&
3346: (attr & FILE_ATTRIBUTE_READONLY)==0;
3347: break;
3348: default:
3349: assert(!"Invalid flags argument");
3350: }
3351: *pResOut = rc;
3352: return SQLITE_OK;
3353: }
3354:
3355:
3356: /*
3357: ** Turn a relative pathname into a full pathname. Write the full
3358: ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname
3359: ** bytes in size.
3360: */
3361: static int winFullPathname(
3362: sqlite3_vfs *pVfs, /* Pointer to vfs object */
3363: const char *zRelative, /* Possibly relative input path */
3364: int nFull, /* Size of output buffer in bytes */
3365: char *zFull /* Output buffer */
3366: ){
3367:
3368: #if defined(__CYGWIN__)
3369: SimulateIOError( return SQLITE_ERROR );
3370: UNUSED_PARAMETER(nFull);
3371: cygwin_conv_to_full_win32_path(zRelative, zFull);
3372: return SQLITE_OK;
3373: #endif
3374:
3375: #if SQLITE_OS_WINCE
3376: SimulateIOError( return SQLITE_ERROR );
3377: UNUSED_PARAMETER(nFull);
3378: /* WinCE has no concept of a relative pathname, or so I am told. */
3379: sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zRelative);
3380: return SQLITE_OK;
3381: #endif
3382:
3383: #if !SQLITE_OS_WINCE && !defined(__CYGWIN__)
3384: int nByte;
3385: void *zConverted;
3386: char *zOut;
3387:
3388: /* If this path name begins with "/X:", where "X" is any alphabetic
3389: ** character, discard the initial "/" from the pathname.
3390: */
3391: if( zRelative[0]=='/' && sqlite3Isalpha(zRelative[1]) && zRelative[2]==':' ){
3392: zRelative++;
3393: }
3394:
3395: /* It's odd to simulate an io-error here, but really this is just
3396: ** using the io-error infrastructure to test that SQLite handles this
3397: ** function failing. This function could fail if, for example, the
3398: ** current working directory has been unlinked.
3399: */
3400: SimulateIOError( return SQLITE_ERROR );
3401: UNUSED_PARAMETER(nFull);
3402: zConverted = convertUtf8Filename(zRelative);
3403: if( zConverted==0 ){
3404: return SQLITE_IOERR_NOMEM;
3405: }
3406: if( isNT() ){
3407: LPWSTR zTemp;
3408: nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0) + 3;
3409: zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
3410: if( zTemp==0 ){
3411: sqlite3_free(zConverted);
3412: return SQLITE_IOERR_NOMEM;
3413: }
3414: osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0);
3415: sqlite3_free(zConverted);
3416: zOut = unicodeToUtf8(zTemp);
3417: sqlite3_free(zTemp);
3418: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3419: ** Since the ANSI version of these Windows API do not exist for WINCE,
3420: ** it's important to not reference them for WINCE builds.
3421: */
3422: #if SQLITE_OS_WINCE==0
3423: }else{
3424: char *zTemp;
3425: nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0) + 3;
3426: zTemp = sqlite3_malloc( nByte*sizeof(zTemp[0]) );
3427: if( zTemp==0 ){
3428: sqlite3_free(zConverted);
3429: return SQLITE_IOERR_NOMEM;
3430: }
3431: osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0);
3432: sqlite3_free(zConverted);
3433: zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
3434: sqlite3_free(zTemp);
3435: #endif
3436: }
3437: if( zOut ){
3438: sqlite3_snprintf(pVfs->mxPathname, zFull, "%s", zOut);
3439: sqlite3_free(zOut);
3440: return SQLITE_OK;
3441: }else{
3442: return SQLITE_IOERR_NOMEM;
3443: }
3444: #endif
3445: }
3446:
3447: #ifndef SQLITE_OMIT_LOAD_EXTENSION
3448: /*
3449: ** Interfaces for opening a shared library, finding entry points
3450: ** within the shared library, and closing the shared library.
3451: */
3452: /*
3453: ** Interfaces for opening a shared library, finding entry points
3454: ** within the shared library, and closing the shared library.
3455: */
3456: static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){
3457: HANDLE h;
3458: void *zConverted = convertUtf8Filename(zFilename);
3459: UNUSED_PARAMETER(pVfs);
3460: if( zConverted==0 ){
3461: return 0;
3462: }
3463: if( isNT() ){
3464: h = osLoadLibraryW((LPCWSTR)zConverted);
3465: /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
3466: ** Since the ANSI version of these Windows API do not exist for WINCE,
3467: ** it's important to not reference them for WINCE builds.
3468: */
3469: #if SQLITE_OS_WINCE==0
3470: }else{
3471: h = osLoadLibraryA((char*)zConverted);
3472: #endif
3473: }
3474: sqlite3_free(zConverted);
3475: return (void*)h;
3476: }
3477: static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
3478: UNUSED_PARAMETER(pVfs);
3479: getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
3480: }
3481: static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
3482: UNUSED_PARAMETER(pVfs);
3483: return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol);
3484: }
3485: static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
3486: UNUSED_PARAMETER(pVfs);
3487: osFreeLibrary((HANDLE)pHandle);
3488: }
3489: #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
3490: #define winDlOpen 0
3491: #define winDlError 0
3492: #define winDlSym 0
3493: #define winDlClose 0
3494: #endif
3495:
3496:
3497: /*
3498: ** Write up to nBuf bytes of randomness into zBuf.
3499: */
3500: static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
3501: int n = 0;
3502: UNUSED_PARAMETER(pVfs);
3503: #if defined(SQLITE_TEST)
3504: n = nBuf;
3505: memset(zBuf, 0, nBuf);
3506: #else
3507: if( sizeof(SYSTEMTIME)<=nBuf-n ){
3508: SYSTEMTIME x;
3509: osGetSystemTime(&x);
3510: memcpy(&zBuf[n], &x, sizeof(x));
3511: n += sizeof(x);
3512: }
3513: if( sizeof(DWORD)<=nBuf-n ){
3514: DWORD pid = osGetCurrentProcessId();
3515: memcpy(&zBuf[n], &pid, sizeof(pid));
3516: n += sizeof(pid);
3517: }
3518: if( sizeof(DWORD)<=nBuf-n ){
3519: DWORD cnt = osGetTickCount();
3520: memcpy(&zBuf[n], &cnt, sizeof(cnt));
3521: n += sizeof(cnt);
3522: }
3523: if( sizeof(LARGE_INTEGER)<=nBuf-n ){
3524: LARGE_INTEGER i;
3525: osQueryPerformanceCounter(&i);
3526: memcpy(&zBuf[n], &i, sizeof(i));
3527: n += sizeof(i);
3528: }
3529: #endif
3530: return n;
3531: }
3532:
3533:
3534: /*
3535: ** Sleep for a little while. Return the amount of time slept.
3536: */
3537: static int winSleep(sqlite3_vfs *pVfs, int microsec){
3538: osSleep((microsec+999)/1000);
3539: UNUSED_PARAMETER(pVfs);
3540: return ((microsec+999)/1000)*1000;
3541: }
3542:
3543: /*
3544: ** The following variable, if set to a non-zero value, is interpreted as
3545: ** the number of seconds since 1970 and is used to set the result of
3546: ** sqlite3OsCurrentTime() during testing.
3547: */
3548: #ifdef SQLITE_TEST
3549: int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */
3550: #endif
3551:
3552: /*
3553: ** Find the current time (in Universal Coordinated Time). Write into *piNow
3554: ** the current time and date as a Julian Day number times 86_400_000. In
3555: ** other words, write into *piNow the number of milliseconds since the Julian
3556: ** epoch of noon in Greenwich on November 24, 4714 B.C according to the
3557: ** proleptic Gregorian calendar.
3558: **
3559: ** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date
3560: ** cannot be found.
3561: */
3562: static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
3563: /* FILETIME structure is a 64-bit value representing the number of
3564: 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
3565: */
3566: FILETIME ft;
3567: static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000;
3568: #ifdef SQLITE_TEST
3569: static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000;
3570: #endif
3571: /* 2^32 - to avoid use of LL and warnings in gcc */
3572: static const sqlite3_int64 max32BitValue =
3573: (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
3574:
3575: #if SQLITE_OS_WINCE
3576: SYSTEMTIME time;
3577: osGetSystemTime(&time);
3578: /* if SystemTimeToFileTime() fails, it returns zero. */
3579: if (!osSystemTimeToFileTime(&time,&ft)){
3580: return SQLITE_ERROR;
3581: }
3582: #else
3583: osGetSystemTimeAsFileTime( &ft );
3584: #endif
3585:
3586: *piNow = winFiletimeEpoch +
3587: ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) +
3588: (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000;
3589:
3590: #ifdef SQLITE_TEST
3591: if( sqlite3_current_time ){
3592: *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch;
3593: }
3594: #endif
3595: UNUSED_PARAMETER(pVfs);
3596: return SQLITE_OK;
3597: }
3598:
3599: /*
3600: ** Find the current time (in Universal Coordinated Time). Write the
3601: ** current time and date as a Julian Day number into *prNow and
3602: ** return 0. Return 1 if the time and date cannot be found.
3603: */
3604: static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){
3605: int rc;
3606: sqlite3_int64 i;
3607: rc = winCurrentTimeInt64(pVfs, &i);
3608: if( !rc ){
3609: *prNow = i/86400000.0;
3610: }
3611: return rc;
3612: }
3613:
3614: /*
3615: ** The idea is that this function works like a combination of
3616: ** GetLastError() and FormatMessage() on Windows (or errno and
3617: ** strerror_r() on Unix). After an error is returned by an OS
3618: ** function, SQLite calls this function with zBuf pointing to
3619: ** a buffer of nBuf bytes. The OS layer should populate the
3620: ** buffer with a nul-terminated UTF-8 encoded error message
3621: ** describing the last IO error to have occurred within the calling
3622: ** thread.
3623: **
3624: ** If the error message is too large for the supplied buffer,
3625: ** it should be truncated. The return value of xGetLastError
3626: ** is zero if the error message fits in the buffer, or non-zero
3627: ** otherwise (if the message was truncated). If non-zero is returned,
3628: ** then it is not necessary to include the nul-terminator character
3629: ** in the output buffer.
3630: **
3631: ** Not supplying an error message will have no adverse effect
3632: ** on SQLite. It is fine to have an implementation that never
3633: ** returns an error message:
3634: **
3635: ** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
3636: ** assert(zBuf[0]=='\0');
3637: ** return 0;
3638: ** }
3639: **
3640: ** However if an error message is supplied, it will be incorporated
3641: ** by sqlite into the error message available to the user using
3642: ** sqlite3_errmsg(), possibly making IO errors easier to debug.
3643: */
3644: static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
3645: UNUSED_PARAMETER(pVfs);
3646: return getLastErrorMsg(osGetLastError(), nBuf, zBuf);
3647: }
3648:
3649: /*
3650: ** Initialize and deinitialize the operating system interface.
3651: */
3652: int sqlite3_os_init(void){
3653: static sqlite3_vfs winVfs = {
3654: 3, /* iVersion */
3655: sizeof(winFile), /* szOsFile */
3656: MAX_PATH, /* mxPathname */
3657: 0, /* pNext */
3658: "win32", /* zName */
3659: 0, /* pAppData */
3660: winOpen, /* xOpen */
3661: winDelete, /* xDelete */
3662: winAccess, /* xAccess */
3663: winFullPathname, /* xFullPathname */
3664: winDlOpen, /* xDlOpen */
3665: winDlError, /* xDlError */
3666: winDlSym, /* xDlSym */
3667: winDlClose, /* xDlClose */
3668: winRandomness, /* xRandomness */
3669: winSleep, /* xSleep */
3670: winCurrentTime, /* xCurrentTime */
3671: winGetLastError, /* xGetLastError */
3672: winCurrentTimeInt64, /* xCurrentTimeInt64 */
3673: winSetSystemCall, /* xSetSystemCall */
3674: winGetSystemCall, /* xGetSystemCall */
3675: winNextSystemCall, /* xNextSystemCall */
3676: };
3677:
3678: /* Double-check that the aSyscall[] array has been constructed
3679: ** correctly. See ticket [bb3a86e890c8e96ab] */
3680: assert( ArraySize(aSyscall)==60 );
3681:
3682: #ifndef SQLITE_OMIT_WAL
3683: /* get memory map allocation granularity */
3684: memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
3685: osGetSystemInfo(&winSysInfo);
3686: assert(winSysInfo.dwAllocationGranularity > 0);
3687: #endif
3688:
3689: sqlite3_vfs_register(&winVfs, 1);
3690: return SQLITE_OK;
3691: }
3692:
3693: int sqlite3_os_end(void){
3694: return SQLITE_OK;
3695: }
3696:
3697: #endif /* SQLITE_OS_WIN */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>