OLD | NEW |
| (Empty) |
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 /* | |
19 ** Include code that is common to all os_*.c files | |
20 */ | |
21 #include "os_common.h" | |
22 | |
23 /* | |
24 ** Include the header file for the Windows VFS. | |
25 */ | |
26 #include "os_win.h" | |
27 | |
28 /* | |
29 ** Compiling and using WAL mode requires several APIs that are only | |
30 ** available in Windows platforms based on the NT kernel. | |
31 */ | |
32 #if !SQLITE_OS_WINNT && !defined(SQLITE_OMIT_WAL) | |
33 # error "WAL mode requires support from the Windows NT kernel, compile\ | |
34 with SQLITE_OMIT_WAL." | |
35 #endif | |
36 | |
37 #if !SQLITE_OS_WINNT && SQLITE_MAX_MMAP_SIZE>0 | |
38 # error "Memory mapped files require support from the Windows NT kernel,\ | |
39 compile with SQLITE_MAX_MMAP_SIZE=0." | |
40 #endif | |
41 | |
42 /* | |
43 ** Are most of the Win32 ANSI APIs available (i.e. with certain exceptions | |
44 ** based on the sub-platform)? | |
45 */ | |
46 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(SQLITE_WIN32_NO_ANSI) | |
47 # define SQLITE_WIN32_HAS_ANSI | |
48 #endif | |
49 | |
50 /* | |
51 ** Are most of the Win32 Unicode APIs available (i.e. with certain exceptions | |
52 ** based on the sub-platform)? | |
53 */ | |
54 #if (SQLITE_OS_WINCE || SQLITE_OS_WINNT || SQLITE_OS_WINRT) && \ | |
55 !defined(SQLITE_WIN32_NO_WIDE) | |
56 # define SQLITE_WIN32_HAS_WIDE | |
57 #endif | |
58 | |
59 /* | |
60 ** Make sure at least one set of Win32 APIs is available. | |
61 */ | |
62 #if !defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_WIN32_HAS_WIDE) | |
63 # error "At least one of SQLITE_WIN32_HAS_ANSI and SQLITE_WIN32_HAS_WIDE\ | |
64 must be defined." | |
65 #endif | |
66 | |
67 /* | |
68 ** Define the required Windows SDK version constants if they are not | |
69 ** already available. | |
70 */ | |
71 #ifndef NTDDI_WIN8 | |
72 # define NTDDI_WIN8 0x06020000 | |
73 #endif | |
74 | |
75 #ifndef NTDDI_WINBLUE | |
76 # define NTDDI_WINBLUE 0x06030000 | |
77 #endif | |
78 | |
79 /* | |
80 ** Check to see if the GetVersionEx[AW] functions are deprecated on the | |
81 ** target system. GetVersionEx was first deprecated in Win8.1. | |
82 */ | |
83 #ifndef SQLITE_WIN32_GETVERSIONEX | |
84 # if defined(NTDDI_VERSION) && NTDDI_VERSION >= NTDDI_WINBLUE | |
85 # define SQLITE_WIN32_GETVERSIONEX 0 /* GetVersionEx() is deprecated */ | |
86 # else | |
87 # define SQLITE_WIN32_GETVERSIONEX 1 /* GetVersionEx() is current */ | |
88 # endif | |
89 #endif | |
90 | |
91 /* | |
92 ** This constant should already be defined (in the "WinDef.h" SDK file). | |
93 */ | |
94 #ifndef MAX_PATH | |
95 # define MAX_PATH (260) | |
96 #endif | |
97 | |
98 /* | |
99 ** Maximum pathname length (in chars) for Win32. This should normally be | |
100 ** MAX_PATH. | |
101 */ | |
102 #ifndef SQLITE_WIN32_MAX_PATH_CHARS | |
103 # define SQLITE_WIN32_MAX_PATH_CHARS (MAX_PATH) | |
104 #endif | |
105 | |
106 /* | |
107 ** This constant should already be defined (in the "WinNT.h" SDK file). | |
108 */ | |
109 #ifndef UNICODE_STRING_MAX_CHARS | |
110 # define UNICODE_STRING_MAX_CHARS (32767) | |
111 #endif | |
112 | |
113 /* | |
114 ** Maximum pathname length (in chars) for WinNT. This should normally be | |
115 ** UNICODE_STRING_MAX_CHARS. | |
116 */ | |
117 #ifndef SQLITE_WINNT_MAX_PATH_CHARS | |
118 # define SQLITE_WINNT_MAX_PATH_CHARS (UNICODE_STRING_MAX_CHARS) | |
119 #endif | |
120 | |
121 /* | |
122 ** Maximum pathname length (in bytes) for Win32. The MAX_PATH macro is in | |
123 ** characters, so we allocate 4 bytes per character assuming worst-case of | |
124 ** 4-bytes-per-character for UTF8. | |
125 */ | |
126 #ifndef SQLITE_WIN32_MAX_PATH_BYTES | |
127 # define SQLITE_WIN32_MAX_PATH_BYTES (SQLITE_WIN32_MAX_PATH_CHARS*4) | |
128 #endif | |
129 | |
130 /* | |
131 ** Maximum pathname length (in bytes) for WinNT. This should normally be | |
132 ** UNICODE_STRING_MAX_CHARS * sizeof(WCHAR). | |
133 */ | |
134 #ifndef SQLITE_WINNT_MAX_PATH_BYTES | |
135 # define SQLITE_WINNT_MAX_PATH_BYTES \ | |
136 (sizeof(WCHAR) * SQLITE_WINNT_MAX_PATH_CHARS) | |
137 #endif | |
138 | |
139 /* | |
140 ** Maximum error message length (in chars) for WinRT. | |
141 */ | |
142 #ifndef SQLITE_WIN32_MAX_ERRMSG_CHARS | |
143 # define SQLITE_WIN32_MAX_ERRMSG_CHARS (1024) | |
144 #endif | |
145 | |
146 /* | |
147 ** Returns non-zero if the character should be treated as a directory | |
148 ** separator. | |
149 */ | |
150 #ifndef winIsDirSep | |
151 # define winIsDirSep(a) (((a) == '/') || ((a) == '\\')) | |
152 #endif | |
153 | |
154 /* | |
155 ** This macro is used when a local variable is set to a value that is | |
156 ** [sometimes] not used by the code (e.g. via conditional compilation). | |
157 */ | |
158 #ifndef UNUSED_VARIABLE_VALUE | |
159 # define UNUSED_VARIABLE_VALUE(x) (void)(x) | |
160 #endif | |
161 | |
162 /* | |
163 ** Returns the character that should be used as the directory separator. | |
164 */ | |
165 #ifndef winGetDirSep | |
166 # define winGetDirSep() '\\' | |
167 #endif | |
168 | |
169 /* | |
170 ** Do we need to manually define the Win32 file mapping APIs for use with WAL | |
171 ** mode or memory mapped files (e.g. these APIs are available in the Windows | |
172 ** CE SDK; however, they are not present in the header file)? | |
173 */ | |
174 #if SQLITE_WIN32_FILEMAPPING_API && \ | |
175 (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) | |
176 /* | |
177 ** Two of the file mapping APIs are different under WinRT. Figure out which | |
178 ** set we need. | |
179 */ | |
180 #if SQLITE_OS_WINRT | |
181 WINBASEAPI HANDLE WINAPI CreateFileMappingFromApp(HANDLE, \ | |
182 LPSECURITY_ATTRIBUTES, ULONG, ULONG64, LPCWSTR); | |
183 | |
184 WINBASEAPI LPVOID WINAPI MapViewOfFileFromApp(HANDLE, ULONG, ULONG64, SIZE_T); | |
185 #else | |
186 #if defined(SQLITE_WIN32_HAS_ANSI) | |
187 WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE, LPSECURITY_ATTRIBUTES, \ | |
188 DWORD, DWORD, DWORD, LPCSTR); | |
189 #endif /* defined(SQLITE_WIN32_HAS_ANSI) */ | |
190 | |
191 #if defined(SQLITE_WIN32_HAS_WIDE) | |
192 WINBASEAPI HANDLE WINAPI CreateFileMappingW(HANDLE, LPSECURITY_ATTRIBUTES, \ | |
193 DWORD, DWORD, DWORD, LPCWSTR); | |
194 #endif /* defined(SQLITE_WIN32_HAS_WIDE) */ | |
195 | |
196 WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T); | |
197 #endif /* SQLITE_OS_WINRT */ | |
198 | |
199 /* | |
200 ** These file mapping APIs are common to both Win32 and WinRT. | |
201 */ | |
202 | |
203 WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T); | |
204 WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID); | |
205 #endif /* SQLITE_WIN32_FILEMAPPING_API */ | |
206 | |
207 /* | |
208 ** Some Microsoft compilers lack this definition. | |
209 */ | |
210 #ifndef INVALID_FILE_ATTRIBUTES | |
211 # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) | |
212 #endif | |
213 | |
214 #ifndef FILE_FLAG_MASK | |
215 # define FILE_FLAG_MASK (0xFF3C0000) | |
216 #endif | |
217 | |
218 #ifndef FILE_ATTRIBUTE_MASK | |
219 # define FILE_ATTRIBUTE_MASK (0x0003FFF7) | |
220 #endif | |
221 | |
222 #ifndef SQLITE_OMIT_WAL | |
223 /* Forward references to structures used for WAL */ | |
224 typedef struct winShm winShm; /* A connection to shared-memory */ | |
225 typedef struct winShmNode winShmNode; /* A region of shared-memory */ | |
226 #endif | |
227 | |
228 /* | |
229 ** WinCE lacks native support for file locking so we have to fake it | |
230 ** with some code of our own. | |
231 */ | |
232 #if SQLITE_OS_WINCE | |
233 typedef struct winceLock { | |
234 int nReaders; /* Number of reader locks obtained */ | |
235 BOOL bPending; /* Indicates a pending lock has been obtained */ | |
236 BOOL bReserved; /* Indicates a reserved lock has been obtained */ | |
237 BOOL bExclusive; /* Indicates an exclusive lock has been obtained */ | |
238 } winceLock; | |
239 #endif | |
240 | |
241 /* | |
242 ** The winFile structure is a subclass of sqlite3_file* specific to the win32 | |
243 ** portability layer. | |
244 */ | |
245 typedef struct winFile winFile; | |
246 struct winFile { | |
247 const sqlite3_io_methods *pMethod; /*** Must be first ***/ | |
248 sqlite3_vfs *pVfs; /* The VFS used to open this file */ | |
249 HANDLE h; /* Handle for accessing the file */ | |
250 u8 locktype; /* Type of lock currently held on this file */ | |
251 short sharedLockByte; /* Randomly chosen byte used as a shared lock */ | |
252 u8 ctrlFlags; /* Flags. See WINFILE_* below */ | |
253 DWORD lastErrno; /* The Windows errno from the last I/O error */ | |
254 #ifndef SQLITE_OMIT_WAL | |
255 winShm *pShm; /* Instance of shared memory on this file */ | |
256 #endif | |
257 const char *zPath; /* Full pathname of this file */ | |
258 int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */ | |
259 #if SQLITE_OS_WINCE | |
260 LPWSTR zDeleteOnClose; /* Name of file to delete when closing */ | |
261 HANDLE hMutex; /* Mutex used to control access to shared lock */ | |
262 HANDLE hShared; /* Shared memory segment used for locking */ | |
263 winceLock local; /* Locks obtained by this instance of winFile */ | |
264 winceLock *shared; /* Global shared lock memory for the file */ | |
265 #endif | |
266 #if SQLITE_MAX_MMAP_SIZE>0 | |
267 int nFetchOut; /* Number of outstanding xFetch references */ | |
268 HANDLE hMap; /* Handle for accessing memory mapping */ | |
269 void *pMapRegion; /* Area memory mapped */ | |
270 sqlite3_int64 mmapSize; /* Usable size of mapped region */ | |
271 sqlite3_int64 mmapSizeActual; /* Actual size of mapped region */ | |
272 sqlite3_int64 mmapSizeMax; /* Configured FCNTL_MMAP_SIZE value */ | |
273 #endif | |
274 }; | |
275 | |
276 /* | |
277 ** Allowed values for winFile.ctrlFlags | |
278 */ | |
279 #define WINFILE_RDONLY 0x02 /* Connection is read only */ | |
280 #define WINFILE_PERSIST_WAL 0x04 /* Persistent WAL mode */ | |
281 #define WINFILE_PSOW 0x10 /* SQLITE_IOCAP_POWERSAFE_OVERWRITE */ | |
282 | |
283 /* | |
284 * The size of the buffer used by sqlite3_win32_write_debug(). | |
285 */ | |
286 #ifndef SQLITE_WIN32_DBG_BUF_SIZE | |
287 # define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD))) | |
288 #endif | |
289 | |
290 /* | |
291 * The value used with sqlite3_win32_set_directory() to specify that | |
292 * the data directory should be changed. | |
293 */ | |
294 #ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE | |
295 # define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1) | |
296 #endif | |
297 | |
298 /* | |
299 * The value used with sqlite3_win32_set_directory() to specify that | |
300 * the temporary directory should be changed. | |
301 */ | |
302 #ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE | |
303 # define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2) | |
304 #endif | |
305 | |
306 /* | |
307 * If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the | |
308 * various Win32 API heap functions instead of our own. | |
309 */ | |
310 #ifdef SQLITE_WIN32_MALLOC | |
311 | |
312 /* | |
313 * If this is non-zero, an isolated heap will be created by the native Win32 | |
314 * allocator subsystem; otherwise, the default process heap will be used. This | |
315 * setting has no effect when compiling for WinRT. By default, this is enabled | |
316 * and an isolated heap will be created to store all allocated data. | |
317 * | |
318 ****************************************************************************** | |
319 * WARNING: It is important to note that when this setting is non-zero and the | |
320 * winMemShutdown function is called (e.g. by the sqlite3_shutdown | |
321 * function), all data that was allocated using the isolated heap will | |
322 * be freed immediately and any attempt to access any of that freed | |
323 * data will almost certainly result in an immediate access violation. | |
324 ****************************************************************************** | |
325 */ | |
326 #ifndef SQLITE_WIN32_HEAP_CREATE | |
327 # define SQLITE_WIN32_HEAP_CREATE (TRUE) | |
328 #endif | |
329 | |
330 /* | |
331 * The initial size of the Win32-specific heap. This value may be zero. | |
332 */ | |
333 #ifndef SQLITE_WIN32_HEAP_INIT_SIZE | |
334 # define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_DEFAULT_CACHE_SIZE) * \ | |
335 (SQLITE_DEFAULT_PAGE_SIZE) + 4194304) | |
336 #endif | |
337 | |
338 /* | |
339 * The maximum size of the Win32-specific heap. This value may be zero. | |
340 */ | |
341 #ifndef SQLITE_WIN32_HEAP_MAX_SIZE | |
342 # define SQLITE_WIN32_HEAP_MAX_SIZE (0) | |
343 #endif | |
344 | |
345 /* | |
346 * The extra flags to use in calls to the Win32 heap APIs. This value may be | |
347 * zero for the default behavior. | |
348 */ | |
349 #ifndef SQLITE_WIN32_HEAP_FLAGS | |
350 # define SQLITE_WIN32_HEAP_FLAGS (0) | |
351 #endif | |
352 | |
353 | |
354 /* | |
355 ** The winMemData structure stores information required by the Win32-specific | |
356 ** sqlite3_mem_methods implementation. | |
357 */ | |
358 typedef struct winMemData winMemData; | |
359 struct winMemData { | |
360 #ifndef NDEBUG | |
361 u32 magic1; /* Magic number to detect structure corruption. */ | |
362 #endif | |
363 HANDLE hHeap; /* The handle to our heap. */ | |
364 BOOL bOwned; /* Do we own the heap (i.e. destroy it on shutdown)? */ | |
365 #ifndef NDEBUG | |
366 u32 magic2; /* Magic number to detect structure corruption. */ | |
367 #endif | |
368 }; | |
369 | |
370 #ifndef NDEBUG | |
371 #define WINMEM_MAGIC1 0x42b2830b | |
372 #define WINMEM_MAGIC2 0xbd4d7cf4 | |
373 #endif | |
374 | |
375 static struct winMemData win_mem_data = { | |
376 #ifndef NDEBUG | |
377 WINMEM_MAGIC1, | |
378 #endif | |
379 NULL, FALSE | |
380 #ifndef NDEBUG | |
381 ,WINMEM_MAGIC2 | |
382 #endif | |
383 }; | |
384 | |
385 #ifndef NDEBUG | |
386 #define winMemAssertMagic1() assert( win_mem_data.magic1==WINMEM_MAGIC1 ) | |
387 #define winMemAssertMagic2() assert( win_mem_data.magic2==WINMEM_MAGIC2 ) | |
388 #define winMemAssertMagic() winMemAssertMagic1(); winMemAssertMagic2(); | |
389 #else | |
390 #define winMemAssertMagic() | |
391 #endif | |
392 | |
393 #define winMemGetDataPtr() &win_mem_data | |
394 #define winMemGetHeap() win_mem_data.hHeap | |
395 #define winMemGetOwned() win_mem_data.bOwned | |
396 | |
397 static void *winMemMalloc(int nBytes); | |
398 static void winMemFree(void *pPrior); | |
399 static void *winMemRealloc(void *pPrior, int nBytes); | |
400 static int winMemSize(void *p); | |
401 static int winMemRoundup(int n); | |
402 static int winMemInit(void *pAppData); | |
403 static void winMemShutdown(void *pAppData); | |
404 | |
405 const sqlite3_mem_methods *sqlite3MemGetWin32(void); | |
406 #endif /* SQLITE_WIN32_MALLOC */ | |
407 | |
408 /* | |
409 ** The following variable is (normally) set once and never changes | |
410 ** thereafter. It records whether the operating system is Win9x | |
411 ** or WinNT. | |
412 ** | |
413 ** 0: Operating system unknown. | |
414 ** 1: Operating system is Win9x. | |
415 ** 2: Operating system is WinNT. | |
416 ** | |
417 ** In order to facilitate testing on a WinNT system, the test fixture | |
418 ** can manually set this value to 1 to emulate Win98 behavior. | |
419 */ | |
420 #ifdef SQLITE_TEST | |
421 LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; | |
422 #else | |
423 static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0; | |
424 #endif | |
425 | |
426 #ifndef SYSCALL | |
427 # define SYSCALL sqlite3_syscall_ptr | |
428 #endif | |
429 | |
430 /* | |
431 ** This function is not available on Windows CE or WinRT. | |
432 */ | |
433 | |
434 #if SQLITE_OS_WINCE || SQLITE_OS_WINRT | |
435 # define osAreFileApisANSI() 1 | |
436 #endif | |
437 | |
438 /* | |
439 ** Many system calls are accessed through pointer-to-functions so that | |
440 ** they may be overridden at runtime to facilitate fault injection during | |
441 ** testing and sandboxing. The following array holds the names and pointers | |
442 ** to all overrideable system calls. | |
443 */ | |
444 static struct win_syscall { | |
445 const char *zName; /* Name of the system call */ | |
446 sqlite3_syscall_ptr pCurrent; /* Current value of the system call */ | |
447 sqlite3_syscall_ptr pDefault; /* Default value */ | |
448 } aSyscall[] = { | |
449 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT | |
450 { "AreFileApisANSI", (SYSCALL)AreFileApisANSI, 0 }, | |
451 #else | |
452 { "AreFileApisANSI", (SYSCALL)0, 0 }, | |
453 #endif | |
454 | |
455 #ifndef osAreFileApisANSI | |
456 #define osAreFileApisANSI ((BOOL(WINAPI*)(VOID))aSyscall[0].pCurrent) | |
457 #endif | |
458 | |
459 #if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) | |
460 { "CharLowerW", (SYSCALL)CharLowerW, 0 }, | |
461 #else | |
462 { "CharLowerW", (SYSCALL)0, 0 }, | |
463 #endif | |
464 | |
465 #define osCharLowerW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[1].pCurrent) | |
466 | |
467 #if SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_WIDE) | |
468 { "CharUpperW", (SYSCALL)CharUpperW, 0 }, | |
469 #else | |
470 { "CharUpperW", (SYSCALL)0, 0 }, | |
471 #endif | |
472 | |
473 #define osCharUpperW ((LPWSTR(WINAPI*)(LPWSTR))aSyscall[2].pCurrent) | |
474 | |
475 { "CloseHandle", (SYSCALL)CloseHandle, 0 }, | |
476 | |
477 #define osCloseHandle ((BOOL(WINAPI*)(HANDLE))aSyscall[3].pCurrent) | |
478 | |
479 #if defined(SQLITE_WIN32_HAS_ANSI) | |
480 { "CreateFileA", (SYSCALL)CreateFileA, 0 }, | |
481 #else | |
482 { "CreateFileA", (SYSCALL)0, 0 }, | |
483 #endif | |
484 | |
485 #define osCreateFileA ((HANDLE(WINAPI*)(LPCSTR,DWORD,DWORD, \ | |
486 LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[4].pCurrent) | |
487 | |
488 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
489 { "CreateFileW", (SYSCALL)CreateFileW, 0 }, | |
490 #else | |
491 { "CreateFileW", (SYSCALL)0, 0 }, | |
492 #endif | |
493 | |
494 #define osCreateFileW ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD, \ | |
495 LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE))aSyscall[5].pCurrent) | |
496 | |
497 #if (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_ANSI) && \ | |
498 (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) | |
499 { "CreateFileMappingA", (SYSCALL)CreateFileMappingA, 0 }, | |
500 #else | |
501 { "CreateFileMappingA", (SYSCALL)0, 0 }, | |
502 #endif | |
503 | |
504 #define osCreateFileMappingA ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ | |
505 DWORD,DWORD,DWORD,LPCSTR))aSyscall[6].pCurrent) | |
506 | |
507 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ | |
508 (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) | |
509 { "CreateFileMappingW", (SYSCALL)CreateFileMappingW, 0 }, | |
510 #else | |
511 { "CreateFileMappingW", (SYSCALL)0, 0 }, | |
512 #endif | |
513 | |
514 #define osCreateFileMappingW ((HANDLE(WINAPI*)(HANDLE,LPSECURITY_ATTRIBUTES, \ | |
515 DWORD,DWORD,DWORD,LPCWSTR))aSyscall[7].pCurrent) | |
516 | |
517 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
518 { "CreateMutexW", (SYSCALL)CreateMutexW, 0 }, | |
519 #else | |
520 { "CreateMutexW", (SYSCALL)0, 0 }, | |
521 #endif | |
522 | |
523 #define osCreateMutexW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,BOOL, \ | |
524 LPCWSTR))aSyscall[8].pCurrent) | |
525 | |
526 #if defined(SQLITE_WIN32_HAS_ANSI) | |
527 { "DeleteFileA", (SYSCALL)DeleteFileA, 0 }, | |
528 #else | |
529 { "DeleteFileA", (SYSCALL)0, 0 }, | |
530 #endif | |
531 | |
532 #define osDeleteFileA ((BOOL(WINAPI*)(LPCSTR))aSyscall[9].pCurrent) | |
533 | |
534 #if defined(SQLITE_WIN32_HAS_WIDE) | |
535 { "DeleteFileW", (SYSCALL)DeleteFileW, 0 }, | |
536 #else | |
537 { "DeleteFileW", (SYSCALL)0, 0 }, | |
538 #endif | |
539 | |
540 #define osDeleteFileW ((BOOL(WINAPI*)(LPCWSTR))aSyscall[10].pCurrent) | |
541 | |
542 #if SQLITE_OS_WINCE | |
543 { "FileTimeToLocalFileTime", (SYSCALL)FileTimeToLocalFileTime, 0 }, | |
544 #else | |
545 { "FileTimeToLocalFileTime", (SYSCALL)0, 0 }, | |
546 #endif | |
547 | |
548 #define osFileTimeToLocalFileTime ((BOOL(WINAPI*)(CONST FILETIME*, \ | |
549 LPFILETIME))aSyscall[11].pCurrent) | |
550 | |
551 #if SQLITE_OS_WINCE | |
552 { "FileTimeToSystemTime", (SYSCALL)FileTimeToSystemTime, 0 }, | |
553 #else | |
554 { "FileTimeToSystemTime", (SYSCALL)0, 0 }, | |
555 #endif | |
556 | |
557 #define osFileTimeToSystemTime ((BOOL(WINAPI*)(CONST FILETIME*, \ | |
558 LPSYSTEMTIME))aSyscall[12].pCurrent) | |
559 | |
560 { "FlushFileBuffers", (SYSCALL)FlushFileBuffers, 0 }, | |
561 | |
562 #define osFlushFileBuffers ((BOOL(WINAPI*)(HANDLE))aSyscall[13].pCurrent) | |
563 | |
564 #if defined(SQLITE_WIN32_HAS_ANSI) | |
565 { "FormatMessageA", (SYSCALL)FormatMessageA, 0 }, | |
566 #else | |
567 { "FormatMessageA", (SYSCALL)0, 0 }, | |
568 #endif | |
569 | |
570 #define osFormatMessageA ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPSTR, \ | |
571 DWORD,va_list*))aSyscall[14].pCurrent) | |
572 | |
573 #if defined(SQLITE_WIN32_HAS_WIDE) | |
574 { "FormatMessageW", (SYSCALL)FormatMessageW, 0 }, | |
575 #else | |
576 { "FormatMessageW", (SYSCALL)0, 0 }, | |
577 #endif | |
578 | |
579 #define osFormatMessageW ((DWORD(WINAPI*)(DWORD,LPCVOID,DWORD,DWORD,LPWSTR, \ | |
580 DWORD,va_list*))aSyscall[15].pCurrent) | |
581 | |
582 #if !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
583 { "FreeLibrary", (SYSCALL)FreeLibrary, 0 }, | |
584 #else | |
585 { "FreeLibrary", (SYSCALL)0, 0 }, | |
586 #endif | |
587 | |
588 #define osFreeLibrary ((BOOL(WINAPI*)(HMODULE))aSyscall[16].pCurrent) | |
589 | |
590 { "GetCurrentProcessId", (SYSCALL)GetCurrentProcessId, 0 }, | |
591 | |
592 #define osGetCurrentProcessId ((DWORD(WINAPI*)(VOID))aSyscall[17].pCurrent) | |
593 | |
594 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) | |
595 { "GetDiskFreeSpaceA", (SYSCALL)GetDiskFreeSpaceA, 0 }, | |
596 #else | |
597 { "GetDiskFreeSpaceA", (SYSCALL)0, 0 }, | |
598 #endif | |
599 | |
600 #define osGetDiskFreeSpaceA ((BOOL(WINAPI*)(LPCSTR,LPDWORD,LPDWORD,LPDWORD, \ | |
601 LPDWORD))aSyscall[18].pCurrent) | |
602 | |
603 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
604 { "GetDiskFreeSpaceW", (SYSCALL)GetDiskFreeSpaceW, 0 }, | |
605 #else | |
606 { "GetDiskFreeSpaceW", (SYSCALL)0, 0 }, | |
607 #endif | |
608 | |
609 #define osGetDiskFreeSpaceW ((BOOL(WINAPI*)(LPCWSTR,LPDWORD,LPDWORD,LPDWORD, \ | |
610 LPDWORD))aSyscall[19].pCurrent) | |
611 | |
612 #if defined(SQLITE_WIN32_HAS_ANSI) | |
613 { "GetFileAttributesA", (SYSCALL)GetFileAttributesA, 0 }, | |
614 #else | |
615 { "GetFileAttributesA", (SYSCALL)0, 0 }, | |
616 #endif | |
617 | |
618 #define osGetFileAttributesA ((DWORD(WINAPI*)(LPCSTR))aSyscall[20].pCurrent) | |
619 | |
620 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
621 { "GetFileAttributesW", (SYSCALL)GetFileAttributesW, 0 }, | |
622 #else | |
623 { "GetFileAttributesW", (SYSCALL)0, 0 }, | |
624 #endif | |
625 | |
626 #define osGetFileAttributesW ((DWORD(WINAPI*)(LPCWSTR))aSyscall[21].pCurrent) | |
627 | |
628 #if defined(SQLITE_WIN32_HAS_WIDE) | |
629 { "GetFileAttributesExW", (SYSCALL)GetFileAttributesExW, 0 }, | |
630 #else | |
631 { "GetFileAttributesExW", (SYSCALL)0, 0 }, | |
632 #endif | |
633 | |
634 #define osGetFileAttributesExW ((BOOL(WINAPI*)(LPCWSTR,GET_FILEEX_INFO_LEVELS, \ | |
635 LPVOID))aSyscall[22].pCurrent) | |
636 | |
637 #if !SQLITE_OS_WINRT | |
638 { "GetFileSize", (SYSCALL)GetFileSize, 0 }, | |
639 #else | |
640 { "GetFileSize", (SYSCALL)0, 0 }, | |
641 #endif | |
642 | |
643 #define osGetFileSize ((DWORD(WINAPI*)(HANDLE,LPDWORD))aSyscall[23].pCurrent) | |
644 | |
645 #if !SQLITE_OS_WINCE && defined(SQLITE_WIN32_HAS_ANSI) | |
646 { "GetFullPathNameA", (SYSCALL)GetFullPathNameA, 0 }, | |
647 #else | |
648 { "GetFullPathNameA", (SYSCALL)0, 0 }, | |
649 #endif | |
650 | |
651 #define osGetFullPathNameA ((DWORD(WINAPI*)(LPCSTR,DWORD,LPSTR, \ | |
652 LPSTR*))aSyscall[24].pCurrent) | |
653 | |
654 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
655 { "GetFullPathNameW", (SYSCALL)GetFullPathNameW, 0 }, | |
656 #else | |
657 { "GetFullPathNameW", (SYSCALL)0, 0 }, | |
658 #endif | |
659 | |
660 #define osGetFullPathNameW ((DWORD(WINAPI*)(LPCWSTR,DWORD,LPWSTR, \ | |
661 LPWSTR*))aSyscall[25].pCurrent) | |
662 | |
663 { "GetLastError", (SYSCALL)GetLastError, 0 }, | |
664 | |
665 #define osGetLastError ((DWORD(WINAPI*)(VOID))aSyscall[26].pCurrent) | |
666 | |
667 #if !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
668 #if SQLITE_OS_WINCE | |
669 /* The GetProcAddressA() routine is only available on Windows CE. */ | |
670 { "GetProcAddressA", (SYSCALL)GetProcAddressA, 0 }, | |
671 #else | |
672 /* All other Windows platforms expect GetProcAddress() to take | |
673 ** an ANSI string regardless of the _UNICODE setting */ | |
674 { "GetProcAddressA", (SYSCALL)GetProcAddress, 0 }, | |
675 #endif | |
676 #else | |
677 { "GetProcAddressA", (SYSCALL)0, 0 }, | |
678 #endif | |
679 | |
680 #define osGetProcAddressA ((FARPROC(WINAPI*)(HMODULE, \ | |
681 LPCSTR))aSyscall[27].pCurrent) | |
682 | |
683 #if !SQLITE_OS_WINRT | |
684 { "GetSystemInfo", (SYSCALL)GetSystemInfo, 0 }, | |
685 #else | |
686 { "GetSystemInfo", (SYSCALL)0, 0 }, | |
687 #endif | |
688 | |
689 #define osGetSystemInfo ((VOID(WINAPI*)(LPSYSTEM_INFO))aSyscall[28].pCurrent) | |
690 | |
691 { "GetSystemTime", (SYSCALL)GetSystemTime, 0 }, | |
692 | |
693 #define osGetSystemTime ((VOID(WINAPI*)(LPSYSTEMTIME))aSyscall[29].pCurrent) | |
694 | |
695 #if !SQLITE_OS_WINCE | |
696 { "GetSystemTimeAsFileTime", (SYSCALL)GetSystemTimeAsFileTime, 0 }, | |
697 #else | |
698 { "GetSystemTimeAsFileTime", (SYSCALL)0, 0 }, | |
699 #endif | |
700 | |
701 #define osGetSystemTimeAsFileTime ((VOID(WINAPI*)( \ | |
702 LPFILETIME))aSyscall[30].pCurrent) | |
703 | |
704 #if defined(SQLITE_WIN32_HAS_ANSI) | |
705 { "GetTempPathA", (SYSCALL)GetTempPathA, 0 }, | |
706 #else | |
707 { "GetTempPathA", (SYSCALL)0, 0 }, | |
708 #endif | |
709 | |
710 #define osGetTempPathA ((DWORD(WINAPI*)(DWORD,LPSTR))aSyscall[31].pCurrent) | |
711 | |
712 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) | |
713 { "GetTempPathW", (SYSCALL)GetTempPathW, 0 }, | |
714 #else | |
715 { "GetTempPathW", (SYSCALL)0, 0 }, | |
716 #endif | |
717 | |
718 #define osGetTempPathW ((DWORD(WINAPI*)(DWORD,LPWSTR))aSyscall[32].pCurrent) | |
719 | |
720 #if !SQLITE_OS_WINRT | |
721 { "GetTickCount", (SYSCALL)GetTickCount, 0 }, | |
722 #else | |
723 { "GetTickCount", (SYSCALL)0, 0 }, | |
724 #endif | |
725 | |
726 #define osGetTickCount ((DWORD(WINAPI*)(VOID))aSyscall[33].pCurrent) | |
727 | |
728 #if defined(SQLITE_WIN32_HAS_ANSI) && defined(SQLITE_WIN32_GETVERSIONEX) && \ | |
729 SQLITE_WIN32_GETVERSIONEX | |
730 { "GetVersionExA", (SYSCALL)GetVersionExA, 0 }, | |
731 #else | |
732 { "GetVersionExA", (SYSCALL)0, 0 }, | |
733 #endif | |
734 | |
735 #define osGetVersionExA ((BOOL(WINAPI*)( \ | |
736 LPOSVERSIONINFOA))aSyscall[34].pCurrent) | |
737 | |
738 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ | |
739 defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX | |
740 { "GetVersionExW", (SYSCALL)GetVersionExW, 0 }, | |
741 #else | |
742 { "GetVersionExW", (SYSCALL)0, 0 }, | |
743 #endif | |
744 | |
745 #define osGetVersionExW ((BOOL(WINAPI*)( \ | |
746 LPOSVERSIONINFOW))aSyscall[35].pCurrent) | |
747 | |
748 { "HeapAlloc", (SYSCALL)HeapAlloc, 0 }, | |
749 | |
750 #define osHeapAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD, \ | |
751 SIZE_T))aSyscall[36].pCurrent) | |
752 | |
753 #if !SQLITE_OS_WINRT | |
754 { "HeapCreate", (SYSCALL)HeapCreate, 0 }, | |
755 #else | |
756 { "HeapCreate", (SYSCALL)0, 0 }, | |
757 #endif | |
758 | |
759 #define osHeapCreate ((HANDLE(WINAPI*)(DWORD,SIZE_T, \ | |
760 SIZE_T))aSyscall[37].pCurrent) | |
761 | |
762 #if !SQLITE_OS_WINRT | |
763 { "HeapDestroy", (SYSCALL)HeapDestroy, 0 }, | |
764 #else | |
765 { "HeapDestroy", (SYSCALL)0, 0 }, | |
766 #endif | |
767 | |
768 #define osHeapDestroy ((BOOL(WINAPI*)(HANDLE))aSyscall[38].pCurrent) | |
769 | |
770 { "HeapFree", (SYSCALL)HeapFree, 0 }, | |
771 | |
772 #define osHeapFree ((BOOL(WINAPI*)(HANDLE,DWORD,LPVOID))aSyscall[39].pCurrent) | |
773 | |
774 { "HeapReAlloc", (SYSCALL)HeapReAlloc, 0 }, | |
775 | |
776 #define osHeapReAlloc ((LPVOID(WINAPI*)(HANDLE,DWORD,LPVOID, \ | |
777 SIZE_T))aSyscall[40].pCurrent) | |
778 | |
779 { "HeapSize", (SYSCALL)HeapSize, 0 }, | |
780 | |
781 #define osHeapSize ((SIZE_T(WINAPI*)(HANDLE,DWORD, \ | |
782 LPCVOID))aSyscall[41].pCurrent) | |
783 | |
784 #if !SQLITE_OS_WINRT | |
785 { "HeapValidate", (SYSCALL)HeapValidate, 0 }, | |
786 #else | |
787 { "HeapValidate", (SYSCALL)0, 0 }, | |
788 #endif | |
789 | |
790 #define osHeapValidate ((BOOL(WINAPI*)(HANDLE,DWORD, \ | |
791 LPCVOID))aSyscall[42].pCurrent) | |
792 | |
793 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT | |
794 { "HeapCompact", (SYSCALL)HeapCompact, 0 }, | |
795 #else | |
796 { "HeapCompact", (SYSCALL)0, 0 }, | |
797 #endif | |
798 | |
799 #define osHeapCompact ((UINT(WINAPI*)(HANDLE,DWORD))aSyscall[43].pCurrent) | |
800 | |
801 #if defined(SQLITE_WIN32_HAS_ANSI) && !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
802 { "LoadLibraryA", (SYSCALL)LoadLibraryA, 0 }, | |
803 #else | |
804 { "LoadLibraryA", (SYSCALL)0, 0 }, | |
805 #endif | |
806 | |
807 #define osLoadLibraryA ((HMODULE(WINAPI*)(LPCSTR))aSyscall[44].pCurrent) | |
808 | |
809 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE) && \ | |
810 !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
811 { "LoadLibraryW", (SYSCALL)LoadLibraryW, 0 }, | |
812 #else | |
813 { "LoadLibraryW", (SYSCALL)0, 0 }, | |
814 #endif | |
815 | |
816 #define osLoadLibraryW ((HMODULE(WINAPI*)(LPCWSTR))aSyscall[45].pCurrent) | |
817 | |
818 #if !SQLITE_OS_WINRT | |
819 { "LocalFree", (SYSCALL)LocalFree, 0 }, | |
820 #else | |
821 { "LocalFree", (SYSCALL)0, 0 }, | |
822 #endif | |
823 | |
824 #define osLocalFree ((HLOCAL(WINAPI*)(HLOCAL))aSyscall[46].pCurrent) | |
825 | |
826 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT | |
827 { "LockFile", (SYSCALL)LockFile, 0 }, | |
828 #else | |
829 { "LockFile", (SYSCALL)0, 0 }, | |
830 #endif | |
831 | |
832 #ifndef osLockFile | |
833 #define osLockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ | |
834 DWORD))aSyscall[47].pCurrent) | |
835 #endif | |
836 | |
837 #if !SQLITE_OS_WINCE | |
838 { "LockFileEx", (SYSCALL)LockFileEx, 0 }, | |
839 #else | |
840 { "LockFileEx", (SYSCALL)0, 0 }, | |
841 #endif | |
842 | |
843 #ifndef osLockFileEx | |
844 #define osLockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD,DWORD, \ | |
845 LPOVERLAPPED))aSyscall[48].pCurrent) | |
846 #endif | |
847 | |
848 #if SQLITE_OS_WINCE || (!SQLITE_OS_WINRT && \ | |
849 (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0)) | |
850 { "MapViewOfFile", (SYSCALL)MapViewOfFile, 0 }, | |
851 #else | |
852 { "MapViewOfFile", (SYSCALL)0, 0 }, | |
853 #endif | |
854 | |
855 #define osMapViewOfFile ((LPVOID(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ | |
856 SIZE_T))aSyscall[49].pCurrent) | |
857 | |
858 { "MultiByteToWideChar", (SYSCALL)MultiByteToWideChar, 0 }, | |
859 | |
860 #define osMultiByteToWideChar ((int(WINAPI*)(UINT,DWORD,LPCSTR,int,LPWSTR, \ | |
861 int))aSyscall[50].pCurrent) | |
862 | |
863 { "QueryPerformanceCounter", (SYSCALL)QueryPerformanceCounter, 0 }, | |
864 | |
865 #define osQueryPerformanceCounter ((BOOL(WINAPI*)( \ | |
866 LARGE_INTEGER*))aSyscall[51].pCurrent) | |
867 | |
868 { "ReadFile", (SYSCALL)ReadFile, 0 }, | |
869 | |
870 #define osReadFile ((BOOL(WINAPI*)(HANDLE,LPVOID,DWORD,LPDWORD, \ | |
871 LPOVERLAPPED))aSyscall[52].pCurrent) | |
872 | |
873 { "SetEndOfFile", (SYSCALL)SetEndOfFile, 0 }, | |
874 | |
875 #define osSetEndOfFile ((BOOL(WINAPI*)(HANDLE))aSyscall[53].pCurrent) | |
876 | |
877 #if !SQLITE_OS_WINRT | |
878 { "SetFilePointer", (SYSCALL)SetFilePointer, 0 }, | |
879 #else | |
880 { "SetFilePointer", (SYSCALL)0, 0 }, | |
881 #endif | |
882 | |
883 #define osSetFilePointer ((DWORD(WINAPI*)(HANDLE,LONG,PLONG, \ | |
884 DWORD))aSyscall[54].pCurrent) | |
885 | |
886 #if !SQLITE_OS_WINRT | |
887 { "Sleep", (SYSCALL)Sleep, 0 }, | |
888 #else | |
889 { "Sleep", (SYSCALL)0, 0 }, | |
890 #endif | |
891 | |
892 #define osSleep ((VOID(WINAPI*)(DWORD))aSyscall[55].pCurrent) | |
893 | |
894 { "SystemTimeToFileTime", (SYSCALL)SystemTimeToFileTime, 0 }, | |
895 | |
896 #define osSystemTimeToFileTime ((BOOL(WINAPI*)(CONST SYSTEMTIME*, \ | |
897 LPFILETIME))aSyscall[56].pCurrent) | |
898 | |
899 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT | |
900 { "UnlockFile", (SYSCALL)UnlockFile, 0 }, | |
901 #else | |
902 { "UnlockFile", (SYSCALL)0, 0 }, | |
903 #endif | |
904 | |
905 #ifndef osUnlockFile | |
906 #define osUnlockFile ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ | |
907 DWORD))aSyscall[57].pCurrent) | |
908 #endif | |
909 | |
910 #if !SQLITE_OS_WINCE | |
911 { "UnlockFileEx", (SYSCALL)UnlockFileEx, 0 }, | |
912 #else | |
913 { "UnlockFileEx", (SYSCALL)0, 0 }, | |
914 #endif | |
915 | |
916 #define osUnlockFileEx ((BOOL(WINAPI*)(HANDLE,DWORD,DWORD,DWORD, \ | |
917 LPOVERLAPPED))aSyscall[58].pCurrent) | |
918 | |
919 #if SQLITE_OS_WINCE || !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 | |
920 { "UnmapViewOfFile", (SYSCALL)UnmapViewOfFile, 0 }, | |
921 #else | |
922 { "UnmapViewOfFile", (SYSCALL)0, 0 }, | |
923 #endif | |
924 | |
925 #define osUnmapViewOfFile ((BOOL(WINAPI*)(LPCVOID))aSyscall[59].pCurrent) | |
926 | |
927 { "WideCharToMultiByte", (SYSCALL)WideCharToMultiByte, 0 }, | |
928 | |
929 #define osWideCharToMultiByte ((int(WINAPI*)(UINT,DWORD,LPCWSTR,int,LPSTR,int, \ | |
930 LPCSTR,LPBOOL))aSyscall[60].pCurrent) | |
931 | |
932 { "WriteFile", (SYSCALL)WriteFile, 0 }, | |
933 | |
934 #define osWriteFile ((BOOL(WINAPI*)(HANDLE,LPCVOID,DWORD,LPDWORD, \ | |
935 LPOVERLAPPED))aSyscall[61].pCurrent) | |
936 | |
937 #if SQLITE_OS_WINRT | |
938 { "CreateEventExW", (SYSCALL)CreateEventExW, 0 }, | |
939 #else | |
940 { "CreateEventExW", (SYSCALL)0, 0 }, | |
941 #endif | |
942 | |
943 #define osCreateEventExW ((HANDLE(WINAPI*)(LPSECURITY_ATTRIBUTES,LPCWSTR, \ | |
944 DWORD,DWORD))aSyscall[62].pCurrent) | |
945 | |
946 #if !SQLITE_OS_WINRT | |
947 { "WaitForSingleObject", (SYSCALL)WaitForSingleObject, 0 }, | |
948 #else | |
949 { "WaitForSingleObject", (SYSCALL)0, 0 }, | |
950 #endif | |
951 | |
952 #define osWaitForSingleObject ((DWORD(WINAPI*)(HANDLE, \ | |
953 DWORD))aSyscall[63].pCurrent) | |
954 | |
955 #if !SQLITE_OS_WINCE | |
956 { "WaitForSingleObjectEx", (SYSCALL)WaitForSingleObjectEx, 0 }, | |
957 #else | |
958 { "WaitForSingleObjectEx", (SYSCALL)0, 0 }, | |
959 #endif | |
960 | |
961 #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ | |
962 BOOL))aSyscall[64].pCurrent) | |
963 | |
964 #if SQLITE_OS_WINRT | |
965 { "SetFilePointerEx", (SYSCALL)SetFilePointerEx, 0 }, | |
966 #else | |
967 { "SetFilePointerEx", (SYSCALL)0, 0 }, | |
968 #endif | |
969 | |
970 #define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \ | |
971 PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent) | |
972 | |
973 #if SQLITE_OS_WINRT | |
974 { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 }, | |
975 #else | |
976 { "GetFileInformationByHandleEx", (SYSCALL)0, 0 }, | |
977 #endif | |
978 | |
979 #define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \ | |
980 FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent) | |
981 | |
982 #if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) | |
983 { "MapViewOfFileFromApp", (SYSCALL)MapViewOfFileFromApp, 0 }, | |
984 #else | |
985 { "MapViewOfFileFromApp", (SYSCALL)0, 0 }, | |
986 #endif | |
987 | |
988 #define osMapViewOfFileFromApp ((LPVOID(WINAPI*)(HANDLE,ULONG,ULONG64, \ | |
989 SIZE_T))aSyscall[67].pCurrent) | |
990 | |
991 #if SQLITE_OS_WINRT | |
992 { "CreateFile2", (SYSCALL)CreateFile2, 0 }, | |
993 #else | |
994 { "CreateFile2", (SYSCALL)0, 0 }, | |
995 #endif | |
996 | |
997 #define osCreateFile2 ((HANDLE(WINAPI*)(LPCWSTR,DWORD,DWORD,DWORD, \ | |
998 LPCREATEFILE2_EXTENDED_PARAMETERS))aSyscall[68].pCurrent) | |
999 | |
1000 #if SQLITE_OS_WINRT && !defined(SQLITE_OMIT_LOAD_EXTENSION) | |
1001 { "LoadPackagedLibrary", (SYSCALL)LoadPackagedLibrary, 0 }, | |
1002 #else | |
1003 { "LoadPackagedLibrary", (SYSCALL)0, 0 }, | |
1004 #endif | |
1005 | |
1006 #define osLoadPackagedLibrary ((HMODULE(WINAPI*)(LPCWSTR, \ | |
1007 DWORD))aSyscall[69].pCurrent) | |
1008 | |
1009 #if SQLITE_OS_WINRT | |
1010 { "GetTickCount64", (SYSCALL)GetTickCount64, 0 }, | |
1011 #else | |
1012 { "GetTickCount64", (SYSCALL)0, 0 }, | |
1013 #endif | |
1014 | |
1015 #define osGetTickCount64 ((ULONGLONG(WINAPI*)(VOID))aSyscall[70].pCurrent) | |
1016 | |
1017 #if SQLITE_OS_WINRT | |
1018 { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, | |
1019 #else | |
1020 { "GetNativeSystemInfo", (SYSCALL)0, 0 }, | |
1021 #endif | |
1022 | |
1023 #define osGetNativeSystemInfo ((VOID(WINAPI*)( \ | |
1024 LPSYSTEM_INFO))aSyscall[71].pCurrent) | |
1025 | |
1026 #if defined(SQLITE_WIN32_HAS_ANSI) | |
1027 { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, | |
1028 #else | |
1029 { "OutputDebugStringA", (SYSCALL)0, 0 }, | |
1030 #endif | |
1031 | |
1032 #define osOutputDebugStringA ((VOID(WINAPI*)(LPCSTR))aSyscall[72].pCurrent) | |
1033 | |
1034 #if defined(SQLITE_WIN32_HAS_WIDE) | |
1035 { "OutputDebugStringW", (SYSCALL)OutputDebugStringW, 0 }, | |
1036 #else | |
1037 { "OutputDebugStringW", (SYSCALL)0, 0 }, | |
1038 #endif | |
1039 | |
1040 #define osOutputDebugStringW ((VOID(WINAPI*)(LPCWSTR))aSyscall[73].pCurrent) | |
1041 | |
1042 { "GetProcessHeap", (SYSCALL)GetProcessHeap, 0 }, | |
1043 | |
1044 #define osGetProcessHeap ((HANDLE(WINAPI*)(VOID))aSyscall[74].pCurrent) | |
1045 | |
1046 #if SQLITE_OS_WINRT && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) | |
1047 { "CreateFileMappingFromApp", (SYSCALL)CreateFileMappingFromApp, 0 }, | |
1048 #else | |
1049 { "CreateFileMappingFromApp", (SYSCALL)0, 0 }, | |
1050 #endif | |
1051 | |
1052 #define osCreateFileMappingFromApp ((HANDLE(WINAPI*)(HANDLE, \ | |
1053 LPSECURITY_ATTRIBUTES,ULONG,ULONG64,LPCWSTR))aSyscall[75].pCurrent) | |
1054 | |
1055 /* | |
1056 ** NOTE: On some sub-platforms, the InterlockedCompareExchange "function" | |
1057 ** is really just a macro that uses a compiler intrinsic (e.g. x64). | |
1058 ** So do not try to make this is into a redefinable interface. | |
1059 */ | |
1060 #if defined(InterlockedCompareExchange) | |
1061 { "InterlockedCompareExchange", (SYSCALL)0, 0 }, | |
1062 | |
1063 #define osInterlockedCompareExchange InterlockedCompareExchange | |
1064 #else | |
1065 { "InterlockedCompareExchange", (SYSCALL)InterlockedCompareExchange, 0 }, | |
1066 | |
1067 #define osInterlockedCompareExchange ((LONG(WINAPI*)(LONG \ | |
1068 SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent) | |
1069 #endif /* defined(InterlockedCompareExchange) */ | |
1070 | |
1071 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID | |
1072 { "UuidCreate", (SYSCALL)UuidCreate, 0 }, | |
1073 #else | |
1074 { "UuidCreate", (SYSCALL)0, 0 }, | |
1075 #endif | |
1076 | |
1077 #define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent) | |
1078 | |
1079 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID | |
1080 { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 }, | |
1081 #else | |
1082 { "UuidCreateSequential", (SYSCALL)0, 0 }, | |
1083 #endif | |
1084 | |
1085 #define osUuidCreateSequential \ | |
1086 ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent) | |
1087 | |
1088 #if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0 | |
1089 { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 }, | |
1090 #else | |
1091 { "FlushViewOfFile", (SYSCALL)0, 0 }, | |
1092 #endif | |
1093 | |
1094 #define osFlushViewOfFile \ | |
1095 ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent) | |
1096 | |
1097 }; /* End of the overrideable system calls */ | |
1098 | |
1099 /* | |
1100 ** This is the xSetSystemCall() method of sqlite3_vfs for all of the | |
1101 ** "win32" VFSes. Return SQLITE_OK opon successfully updating the | |
1102 ** system call pointer, or SQLITE_NOTFOUND if there is no configurable | |
1103 ** system call named zName. | |
1104 */ | |
1105 static int winSetSystemCall( | |
1106 sqlite3_vfs *pNotUsed, /* The VFS pointer. Not used */ | |
1107 const char *zName, /* Name of system call to override */ | |
1108 sqlite3_syscall_ptr pNewFunc /* Pointer to new system call value */ | |
1109 ){ | |
1110 unsigned int i; | |
1111 int rc = SQLITE_NOTFOUND; | |
1112 | |
1113 UNUSED_PARAMETER(pNotUsed); | |
1114 if( zName==0 ){ | |
1115 /* If no zName is given, restore all system calls to their default | |
1116 ** settings and return NULL | |
1117 */ | |
1118 rc = SQLITE_OK; | |
1119 for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){ | |
1120 if( aSyscall[i].pDefault ){ | |
1121 aSyscall[i].pCurrent = aSyscall[i].pDefault; | |
1122 } | |
1123 } | |
1124 }else{ | |
1125 /* If zName is specified, operate on only the one system call | |
1126 ** specified. | |
1127 */ | |
1128 for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){ | |
1129 if( strcmp(zName, aSyscall[i].zName)==0 ){ | |
1130 if( aSyscall[i].pDefault==0 ){ | |
1131 aSyscall[i].pDefault = aSyscall[i].pCurrent; | |
1132 } | |
1133 rc = SQLITE_OK; | |
1134 if( pNewFunc==0 ) pNewFunc = aSyscall[i].pDefault; | |
1135 aSyscall[i].pCurrent = pNewFunc; | |
1136 break; | |
1137 } | |
1138 } | |
1139 } | |
1140 return rc; | |
1141 } | |
1142 | |
1143 /* | |
1144 ** Return the value of a system call. Return NULL if zName is not a | |
1145 ** recognized system call name. NULL is also returned if the system call | |
1146 ** is currently undefined. | |
1147 */ | |
1148 static sqlite3_syscall_ptr winGetSystemCall( | |
1149 sqlite3_vfs *pNotUsed, | |
1150 const char *zName | |
1151 ){ | |
1152 unsigned int i; | |
1153 | |
1154 UNUSED_PARAMETER(pNotUsed); | |
1155 for(i=0; i<sizeof(aSyscall)/sizeof(aSyscall[0]); i++){ | |
1156 if( strcmp(zName, aSyscall[i].zName)==0 ) return aSyscall[i].pCurrent; | |
1157 } | |
1158 return 0; | |
1159 } | |
1160 | |
1161 /* | |
1162 ** Return the name of the first system call after zName. If zName==NULL | |
1163 ** then return the name of the first system call. Return NULL if zName | |
1164 ** is the last system call or if zName is not the name of a valid | |
1165 ** system call. | |
1166 */ | |
1167 static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){ | |
1168 int i = -1; | |
1169 | |
1170 UNUSED_PARAMETER(p); | |
1171 if( zName ){ | |
1172 for(i=0; i<ArraySize(aSyscall)-1; i++){ | |
1173 if( strcmp(zName, aSyscall[i].zName)==0 ) break; | |
1174 } | |
1175 } | |
1176 for(i++; i<ArraySize(aSyscall); i++){ | |
1177 if( aSyscall[i].pCurrent!=0 ) return aSyscall[i].zName; | |
1178 } | |
1179 return 0; | |
1180 } | |
1181 | |
1182 #ifdef SQLITE_WIN32_MALLOC | |
1183 /* | |
1184 ** If a Win32 native heap has been configured, this function will attempt to | |
1185 ** compact it. Upon success, SQLITE_OK will be returned. Upon failure, one | |
1186 ** of SQLITE_NOMEM, SQLITE_ERROR, or SQLITE_NOTFOUND will be returned. The | |
1187 ** "pnLargest" argument, if non-zero, will be used to return the size of the | |
1188 ** largest committed free block in the heap, in bytes. | |
1189 */ | |
1190 int sqlite3_win32_compact_heap(LPUINT pnLargest){ | |
1191 int rc = SQLITE_OK; | |
1192 UINT nLargest = 0; | |
1193 HANDLE hHeap; | |
1194 | |
1195 winMemAssertMagic(); | |
1196 hHeap = winMemGetHeap(); | |
1197 assert( hHeap!=0 ); | |
1198 assert( hHeap!=INVALID_HANDLE_VALUE ); | |
1199 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1200 assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); | |
1201 #endif | |
1202 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT | |
1203 if( (nLargest=osHeapCompact(hHeap, SQLITE_WIN32_HEAP_FLAGS))==0 ){ | |
1204 DWORD lastErrno = osGetLastError(); | |
1205 if( lastErrno==NO_ERROR ){ | |
1206 sqlite3_log(SQLITE_NOMEM, "failed to HeapCompact (no space), heap=%p", | |
1207 (void*)hHeap); | |
1208 rc = SQLITE_NOMEM; | |
1209 }else{ | |
1210 sqlite3_log(SQLITE_ERROR, "failed to HeapCompact (%lu), heap=%p", | |
1211 osGetLastError(), (void*)hHeap); | |
1212 rc = SQLITE_ERROR; | |
1213 } | |
1214 } | |
1215 #else | |
1216 sqlite3_log(SQLITE_NOTFOUND, "failed to HeapCompact, heap=%p", | |
1217 (void*)hHeap); | |
1218 rc = SQLITE_NOTFOUND; | |
1219 #endif | |
1220 if( pnLargest ) *pnLargest = nLargest; | |
1221 return rc; | |
1222 } | |
1223 | |
1224 /* | |
1225 ** If a Win32 native heap has been configured, this function will attempt to | |
1226 ** destroy and recreate it. If the Win32 native heap is not isolated and/or | |
1227 ** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will | |
1228 ** be returned and no changes will be made to the Win32 native heap. | |
1229 */ | |
1230 int sqlite3_win32_reset_heap(){ | |
1231 int rc; | |
1232 MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */ | |
1233 MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */ | |
1234 MUTEX_LOGIC( pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); ) | |
1235 MUTEX_LOGIC( pMem = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM); ) | |
1236 sqlite3_mutex_enter(pMaster); | |
1237 sqlite3_mutex_enter(pMem); | |
1238 winMemAssertMagic(); | |
1239 if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){ | |
1240 /* | |
1241 ** At this point, there should be no outstanding memory allocations on | |
1242 ** the heap. Also, since both the master and memsys locks are currently | |
1243 ** being held by us, no other function (i.e. from another thread) should | |
1244 ** be able to even access the heap. Attempt to destroy and recreate our | |
1245 ** isolated Win32 native heap now. | |
1246 */ | |
1247 assert( winMemGetHeap()!=NULL ); | |
1248 assert( winMemGetOwned() ); | |
1249 assert( sqlite3_memory_used()==0 ); | |
1250 winMemShutdown(winMemGetDataPtr()); | |
1251 assert( winMemGetHeap()==NULL ); | |
1252 assert( !winMemGetOwned() ); | |
1253 assert( sqlite3_memory_used()==0 ); | |
1254 rc = winMemInit(winMemGetDataPtr()); | |
1255 assert( rc!=SQLITE_OK || winMemGetHeap()!=NULL ); | |
1256 assert( rc!=SQLITE_OK || winMemGetOwned() ); | |
1257 assert( rc!=SQLITE_OK || sqlite3_memory_used()==0 ); | |
1258 }else{ | |
1259 /* | |
1260 ** The Win32 native heap cannot be modified because it may be in use. | |
1261 */ | |
1262 rc = SQLITE_BUSY; | |
1263 } | |
1264 sqlite3_mutex_leave(pMem); | |
1265 sqlite3_mutex_leave(pMaster); | |
1266 return rc; | |
1267 } | |
1268 #endif /* SQLITE_WIN32_MALLOC */ | |
1269 | |
1270 /* | |
1271 ** This function outputs the specified (ANSI) string to the Win32 debugger | |
1272 ** (if available). | |
1273 */ | |
1274 | |
1275 void sqlite3_win32_write_debug(const char *zBuf, int nBuf){ | |
1276 char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE]; | |
1277 int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */ | |
1278 if( nMin<-1 ) nMin = -1; /* all negative values become -1. */ | |
1279 assert( nMin==-1 || nMin==0 || nMin<SQLITE_WIN32_DBG_BUF_SIZE ); | |
1280 #if defined(SQLITE_WIN32_HAS_ANSI) | |
1281 if( nMin>0 ){ | |
1282 memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); | |
1283 memcpy(zDbgBuf, zBuf, nMin); | |
1284 osOutputDebugStringA(zDbgBuf); | |
1285 }else{ | |
1286 osOutputDebugStringA(zBuf); | |
1287 } | |
1288 #elif defined(SQLITE_WIN32_HAS_WIDE) | |
1289 memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); | |
1290 if ( osMultiByteToWideChar( | |
1291 osAreFileApisANSI() ? CP_ACP : CP_OEMCP, 0, zBuf, | |
1292 nMin, (LPWSTR)zDbgBuf, SQLITE_WIN32_DBG_BUF_SIZE/sizeof(WCHAR))<=0 ){ | |
1293 return; | |
1294 } | |
1295 osOutputDebugStringW((LPCWSTR)zDbgBuf); | |
1296 #else | |
1297 if( nMin>0 ){ | |
1298 memset(zDbgBuf, 0, SQLITE_WIN32_DBG_BUF_SIZE); | |
1299 memcpy(zDbgBuf, zBuf, nMin); | |
1300 fprintf(stderr, "%s", zDbgBuf); | |
1301 }else{ | |
1302 fprintf(stderr, "%s", zBuf); | |
1303 } | |
1304 #endif | |
1305 } | |
1306 | |
1307 /* | |
1308 ** The following routine suspends the current thread for at least ms | |
1309 ** milliseconds. This is equivalent to the Win32 Sleep() interface. | |
1310 */ | |
1311 #if SQLITE_OS_WINRT | |
1312 static HANDLE sleepObj = NULL; | |
1313 #endif | |
1314 | |
1315 void sqlite3_win32_sleep(DWORD milliseconds){ | |
1316 #if SQLITE_OS_WINRT | |
1317 if ( sleepObj==NULL ){ | |
1318 sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET, | |
1319 SYNCHRONIZE); | |
1320 } | |
1321 assert( sleepObj!=NULL ); | |
1322 osWaitForSingleObjectEx(sleepObj, milliseconds, FALSE); | |
1323 #else | |
1324 osSleep(milliseconds); | |
1325 #endif | |
1326 } | |
1327 | |
1328 #if SQLITE_MAX_WORKER_THREADS>0 && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \ | |
1329 SQLITE_THREADSAFE>0 | |
1330 DWORD sqlite3Win32Wait(HANDLE hObject){ | |
1331 DWORD rc; | |
1332 while( (rc = osWaitForSingleObjectEx(hObject, INFINITE, | |
1333 TRUE))==WAIT_IO_COMPLETION ){} | |
1334 return rc; | |
1335 } | |
1336 #endif | |
1337 | |
1338 /* | |
1339 ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP, | |
1340 ** or WinCE. Return false (zero) for Win95, Win98, or WinME. | |
1341 ** | |
1342 ** Here is an interesting observation: Win95, Win98, and WinME lack | |
1343 ** the LockFileEx() API. But we can still statically link against that | |
1344 ** API as long as we don't call it when running Win95/98/ME. A call to | |
1345 ** this routine is used to determine if the host is Win95/98/ME or | |
1346 ** WinNT/2K/XP so that we will know whether or not we can safely call | |
1347 ** the LockFileEx() API. | |
1348 */ | |
1349 | |
1350 #if !defined(SQLITE_WIN32_GETVERSIONEX) || !SQLITE_WIN32_GETVERSIONEX | |
1351 # define osIsNT() (1) | |
1352 #elif SQLITE_OS_WINCE || SQLITE_OS_WINRT || !defined(SQLITE_WIN32_HAS_ANSI) | |
1353 # define osIsNT() (1) | |
1354 #elif !defined(SQLITE_WIN32_HAS_WIDE) | |
1355 # define osIsNT() (0) | |
1356 #else | |
1357 # define osIsNT() ((sqlite3_os_type==2) || sqlite3_win32_is_nt()) | |
1358 #endif | |
1359 | |
1360 /* | |
1361 ** This function determines if the machine is running a version of Windows | |
1362 ** based on the NT kernel. | |
1363 */ | |
1364 int sqlite3_win32_is_nt(void){ | |
1365 #if SQLITE_OS_WINRT | |
1366 /* | |
1367 ** NOTE: The WinRT sub-platform is always assumed to be based on the NT | |
1368 ** kernel. | |
1369 */ | |
1370 return 1; | |
1371 #elif defined(SQLITE_WIN32_GETVERSIONEX) && SQLITE_WIN32_GETVERSIONEX | |
1372 if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){ | |
1373 #if defined(SQLITE_WIN32_HAS_ANSI) | |
1374 OSVERSIONINFOA sInfo; | |
1375 sInfo.dwOSVersionInfoSize = sizeof(sInfo); | |
1376 osGetVersionExA(&sInfo); | |
1377 osInterlockedCompareExchange(&sqlite3_os_type, | |
1378 (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); | |
1379 #elif defined(SQLITE_WIN32_HAS_WIDE) | |
1380 OSVERSIONINFOW sInfo; | |
1381 sInfo.dwOSVersionInfoSize = sizeof(sInfo); | |
1382 osGetVersionExW(&sInfo); | |
1383 osInterlockedCompareExchange(&sqlite3_os_type, | |
1384 (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0); | |
1385 #endif | |
1386 } | |
1387 return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; | |
1388 #elif SQLITE_TEST | |
1389 return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2; | |
1390 #else | |
1391 /* | |
1392 ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are | |
1393 ** deprecated are always assumed to be based on the NT kernel. | |
1394 */ | |
1395 return 1; | |
1396 #endif | |
1397 } | |
1398 | |
1399 #ifdef SQLITE_WIN32_MALLOC | |
1400 /* | |
1401 ** Allocate nBytes of memory. | |
1402 */ | |
1403 static void *winMemMalloc(int nBytes){ | |
1404 HANDLE hHeap; | |
1405 void *p; | |
1406 | |
1407 winMemAssertMagic(); | |
1408 hHeap = winMemGetHeap(); | |
1409 assert( hHeap!=0 ); | |
1410 assert( hHeap!=INVALID_HANDLE_VALUE ); | |
1411 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1412 assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); | |
1413 #endif | |
1414 assert( nBytes>=0 ); | |
1415 p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); | |
1416 if( !p ){ | |
1417 sqlite3_log(SQLITE_NOMEM, "failed to HeapAlloc %u bytes (%lu), heap=%p", | |
1418 nBytes, osGetLastError(), (void*)hHeap); | |
1419 } | |
1420 return p; | |
1421 } | |
1422 | |
1423 /* | |
1424 ** Free memory. | |
1425 */ | |
1426 static void winMemFree(void *pPrior){ | |
1427 HANDLE hHeap; | |
1428 | |
1429 winMemAssertMagic(); | |
1430 hHeap = winMemGetHeap(); | |
1431 assert( hHeap!=0 ); | |
1432 assert( hHeap!=INVALID_HANDLE_VALUE ); | |
1433 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1434 assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); | |
1435 #endif | |
1436 if( !pPrior ) return; /* Passing NULL to HeapFree is undefined. */ | |
1437 if( !osHeapFree(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ){ | |
1438 sqlite3_log(SQLITE_NOMEM, "failed to HeapFree block %p (%lu), heap=%p", | |
1439 pPrior, osGetLastError(), (void*)hHeap); | |
1440 } | |
1441 } | |
1442 | |
1443 /* | |
1444 ** Change the size of an existing memory allocation | |
1445 */ | |
1446 static void *winMemRealloc(void *pPrior, int nBytes){ | |
1447 HANDLE hHeap; | |
1448 void *p; | |
1449 | |
1450 winMemAssertMagic(); | |
1451 hHeap = winMemGetHeap(); | |
1452 assert( hHeap!=0 ); | |
1453 assert( hHeap!=INVALID_HANDLE_VALUE ); | |
1454 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1455 assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior) ); | |
1456 #endif | |
1457 assert( nBytes>=0 ); | |
1458 if( !pPrior ){ | |
1459 p = osHeapAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, (SIZE_T)nBytes); | |
1460 }else{ | |
1461 p = osHeapReAlloc(hHeap, SQLITE_WIN32_HEAP_FLAGS, pPrior, (SIZE_T)nBytes); | |
1462 } | |
1463 if( !p ){ | |
1464 sqlite3_log(SQLITE_NOMEM, "failed to %s %u bytes (%lu), heap=%p", | |
1465 pPrior ? "HeapReAlloc" : "HeapAlloc", nBytes, osGetLastError(), | |
1466 (void*)hHeap); | |
1467 } | |
1468 return p; | |
1469 } | |
1470 | |
1471 /* | |
1472 ** Return the size of an outstanding allocation, in bytes. | |
1473 */ | |
1474 static int winMemSize(void *p){ | |
1475 HANDLE hHeap; | |
1476 SIZE_T n; | |
1477 | |
1478 winMemAssertMagic(); | |
1479 hHeap = winMemGetHeap(); | |
1480 assert( hHeap!=0 ); | |
1481 assert( hHeap!=INVALID_HANDLE_VALUE ); | |
1482 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1483 assert( osHeapValidate(hHeap, SQLITE_WIN32_HEAP_FLAGS, p) ); | |
1484 #endif | |
1485 if( !p ) return 0; | |
1486 n = osHeapSize(hHeap, SQLITE_WIN32_HEAP_FLAGS, p); | |
1487 if( n==(SIZE_T)-1 ){ | |
1488 sqlite3_log(SQLITE_NOMEM, "failed to HeapSize block %p (%lu), heap=%p", | |
1489 p, osGetLastError(), (void*)hHeap); | |
1490 return 0; | |
1491 } | |
1492 return (int)n; | |
1493 } | |
1494 | |
1495 /* | |
1496 ** Round up a request size to the next valid allocation size. | |
1497 */ | |
1498 static int winMemRoundup(int n){ | |
1499 return n; | |
1500 } | |
1501 | |
1502 /* | |
1503 ** Initialize this module. | |
1504 */ | |
1505 static int winMemInit(void *pAppData){ | |
1506 winMemData *pWinMemData = (winMemData *)pAppData; | |
1507 | |
1508 if( !pWinMemData ) return SQLITE_ERROR; | |
1509 assert( pWinMemData->magic1==WINMEM_MAGIC1 ); | |
1510 assert( pWinMemData->magic2==WINMEM_MAGIC2 ); | |
1511 | |
1512 #if !SQLITE_OS_WINRT && SQLITE_WIN32_HEAP_CREATE | |
1513 if( !pWinMemData->hHeap ){ | |
1514 DWORD dwInitialSize = SQLITE_WIN32_HEAP_INIT_SIZE; | |
1515 DWORD dwMaximumSize = (DWORD)sqlite3GlobalConfig.nHeap; | |
1516 if( dwMaximumSize==0 ){ | |
1517 dwMaximumSize = SQLITE_WIN32_HEAP_MAX_SIZE; | |
1518 }else if( dwInitialSize>dwMaximumSize ){ | |
1519 dwInitialSize = dwMaximumSize; | |
1520 } | |
1521 pWinMemData->hHeap = osHeapCreate(SQLITE_WIN32_HEAP_FLAGS, | |
1522 dwInitialSize, dwMaximumSize); | |
1523 if( !pWinMemData->hHeap ){ | |
1524 sqlite3_log(SQLITE_NOMEM, | |
1525 "failed to HeapCreate (%lu), flags=%u, initSize=%lu, maxSize=%lu", | |
1526 osGetLastError(), SQLITE_WIN32_HEAP_FLAGS, dwInitialSize, | |
1527 dwMaximumSize); | |
1528 return SQLITE_NOMEM; | |
1529 } | |
1530 pWinMemData->bOwned = TRUE; | |
1531 assert( pWinMemData->bOwned ); | |
1532 } | |
1533 #else | |
1534 pWinMemData->hHeap = osGetProcessHeap(); | |
1535 if( !pWinMemData->hHeap ){ | |
1536 sqlite3_log(SQLITE_NOMEM, | |
1537 "failed to GetProcessHeap (%lu)", osGetLastError()); | |
1538 return SQLITE_NOMEM; | |
1539 } | |
1540 pWinMemData->bOwned = FALSE; | |
1541 assert( !pWinMemData->bOwned ); | |
1542 #endif | |
1543 assert( pWinMemData->hHeap!=0 ); | |
1544 assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); | |
1545 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1546 assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); | |
1547 #endif | |
1548 return SQLITE_OK; | |
1549 } | |
1550 | |
1551 /* | |
1552 ** Deinitialize this module. | |
1553 */ | |
1554 static void winMemShutdown(void *pAppData){ | |
1555 winMemData *pWinMemData = (winMemData *)pAppData; | |
1556 | |
1557 if( !pWinMemData ) return; | |
1558 assert( pWinMemData->magic1==WINMEM_MAGIC1 ); | |
1559 assert( pWinMemData->magic2==WINMEM_MAGIC2 ); | |
1560 | |
1561 if( pWinMemData->hHeap ){ | |
1562 assert( pWinMemData->hHeap!=INVALID_HANDLE_VALUE ); | |
1563 #if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_MALLOC_VALIDATE) | |
1564 assert( osHeapValidate(pWinMemData->hHeap, SQLITE_WIN32_HEAP_FLAGS, NULL) ); | |
1565 #endif | |
1566 if( pWinMemData->bOwned ){ | |
1567 if( !osHeapDestroy(pWinMemData->hHeap) ){ | |
1568 sqlite3_log(SQLITE_NOMEM, "failed to HeapDestroy (%lu), heap=%p", | |
1569 osGetLastError(), (void*)pWinMemData->hHeap); | |
1570 } | |
1571 pWinMemData->bOwned = FALSE; | |
1572 } | |
1573 pWinMemData->hHeap = NULL; | |
1574 } | |
1575 } | |
1576 | |
1577 /* | |
1578 ** Populate the low-level memory allocation function pointers in | |
1579 ** sqlite3GlobalConfig.m with pointers to the routines in this file. The | |
1580 ** arguments specify the block of memory to manage. | |
1581 ** | |
1582 ** This routine is only called by sqlite3_config(), and therefore | |
1583 ** is not required to be threadsafe (it is not). | |
1584 */ | |
1585 const sqlite3_mem_methods *sqlite3MemGetWin32(void){ | |
1586 static const sqlite3_mem_methods winMemMethods = { | |
1587 winMemMalloc, | |
1588 winMemFree, | |
1589 winMemRealloc, | |
1590 winMemSize, | |
1591 winMemRoundup, | |
1592 winMemInit, | |
1593 winMemShutdown, | |
1594 &win_mem_data | |
1595 }; | |
1596 return &winMemMethods; | |
1597 } | |
1598 | |
1599 void sqlite3MemSetDefault(void){ | |
1600 sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetWin32()); | |
1601 } | |
1602 #endif /* SQLITE_WIN32_MALLOC */ | |
1603 | |
1604 /* | |
1605 ** Convert a UTF-8 string to Microsoft Unicode (UTF-16?). | |
1606 ** | |
1607 ** Space to hold the returned string is obtained from malloc. | |
1608 */ | |
1609 static LPWSTR winUtf8ToUnicode(const char *zFilename){ | |
1610 int nChar; | |
1611 LPWSTR zWideFilename; | |
1612 | |
1613 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0); | |
1614 if( nChar==0 ){ | |
1615 return 0; | |
1616 } | |
1617 zWideFilename = sqlite3MallocZero( nChar*sizeof(zWideFilename[0]) ); | |
1618 if( zWideFilename==0 ){ | |
1619 return 0; | |
1620 } | |
1621 nChar = osMultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, | |
1622 nChar); | |
1623 if( nChar==0 ){ | |
1624 sqlite3_free(zWideFilename); | |
1625 zWideFilename = 0; | |
1626 } | |
1627 return zWideFilename; | |
1628 } | |
1629 | |
1630 /* | |
1631 ** Convert Microsoft Unicode to UTF-8. Space to hold the returned string is | |
1632 ** obtained from sqlite3_malloc(). | |
1633 */ | |
1634 static char *winUnicodeToUtf8(LPCWSTR zWideFilename){ | |
1635 int nByte; | |
1636 char *zFilename; | |
1637 | |
1638 nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0); | |
1639 if( nByte == 0 ){ | |
1640 return 0; | |
1641 } | |
1642 zFilename = sqlite3MallocZero( nByte ); | |
1643 if( zFilename==0 ){ | |
1644 return 0; | |
1645 } | |
1646 nByte = osWideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte, | |
1647 0, 0); | |
1648 if( nByte == 0 ){ | |
1649 sqlite3_free(zFilename); | |
1650 zFilename = 0; | |
1651 } | |
1652 return zFilename; | |
1653 } | |
1654 | |
1655 /* | |
1656 ** Convert an ANSI string to Microsoft Unicode, based on the | |
1657 ** current codepage settings for file apis. | |
1658 ** | |
1659 ** Space to hold the returned string is obtained | |
1660 ** from sqlite3_malloc. | |
1661 */ | |
1662 static LPWSTR winMbcsToUnicode(const char *zFilename){ | |
1663 int nByte; | |
1664 LPWSTR zMbcsFilename; | |
1665 int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
1666 | |
1667 nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, NULL, | |
1668 0)*sizeof(WCHAR); | |
1669 if( nByte==0 ){ | |
1670 return 0; | |
1671 } | |
1672 zMbcsFilename = sqlite3MallocZero( nByte*sizeof(zMbcsFilename[0]) ); | |
1673 if( zMbcsFilename==0 ){ | |
1674 return 0; | |
1675 } | |
1676 nByte = osMultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, | |
1677 nByte); | |
1678 if( nByte==0 ){ | |
1679 sqlite3_free(zMbcsFilename); | |
1680 zMbcsFilename = 0; | |
1681 } | |
1682 return zMbcsFilename; | |
1683 } | |
1684 | |
1685 /* | |
1686 ** Convert Microsoft Unicode to multi-byte character string, based on the | |
1687 ** user's ANSI codepage. | |
1688 ** | |
1689 ** Space to hold the returned string is obtained from | |
1690 ** sqlite3_malloc(). | |
1691 */ | |
1692 static char *winUnicodeToMbcs(LPCWSTR zWideFilename){ | |
1693 int nByte; | |
1694 char *zFilename; | |
1695 int codepage = osAreFileApisANSI() ? CP_ACP : CP_OEMCP; | |
1696 | |
1697 nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0); | |
1698 if( nByte == 0 ){ | |
1699 return 0; | |
1700 } | |
1701 zFilename = sqlite3MallocZero( nByte ); | |
1702 if( zFilename==0 ){ | |
1703 return 0; | |
1704 } | |
1705 nByte = osWideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, | |
1706 nByte, 0, 0); | |
1707 if( nByte == 0 ){ | |
1708 sqlite3_free(zFilename); | |
1709 zFilename = 0; | |
1710 } | |
1711 return zFilename; | |
1712 } | |
1713 | |
1714 /* | |
1715 ** Convert multibyte character string to UTF-8. Space to hold the | |
1716 ** returned string is obtained from sqlite3_malloc(). | |
1717 */ | |
1718 char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){ | |
1719 char *zFilenameUtf8; | |
1720 LPWSTR zTmpWide; | |
1721 | |
1722 zTmpWide = winMbcsToUnicode(zFilename); | |
1723 if( zTmpWide==0 ){ | |
1724 return 0; | |
1725 } | |
1726 zFilenameUtf8 = winUnicodeToUtf8(zTmpWide); | |
1727 sqlite3_free(zTmpWide); | |
1728 return zFilenameUtf8; | |
1729 } | |
1730 | |
1731 /* | |
1732 ** Convert UTF-8 to multibyte character string. Space to hold the | |
1733 ** returned string is obtained from sqlite3_malloc(). | |
1734 */ | |
1735 char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){ | |
1736 char *zFilenameMbcs; | |
1737 LPWSTR zTmpWide; | |
1738 | |
1739 zTmpWide = winUtf8ToUnicode(zFilename); | |
1740 if( zTmpWide==0 ){ | |
1741 return 0; | |
1742 } | |
1743 zFilenameMbcs = winUnicodeToMbcs(zTmpWide); | |
1744 sqlite3_free(zTmpWide); | |
1745 return zFilenameMbcs; | |
1746 } | |
1747 | |
1748 /* | |
1749 ** This function sets the data directory or the temporary directory based on | |
1750 ** the provided arguments. The type argument must be 1 in order to set the | |
1751 ** data directory or 2 in order to set the temporary directory. The zValue | |
1752 ** argument is the name of the directory to use. The return value will be | |
1753 ** SQLITE_OK if successful. | |
1754 */ | |
1755 int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){ | |
1756 char **ppDirectory = 0; | |
1757 #ifndef SQLITE_OMIT_AUTOINIT | |
1758 int rc = sqlite3_initialize(); | |
1759 if( rc ) return rc; | |
1760 #endif | |
1761 if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ | |
1762 ppDirectory = &sqlite3_data_directory; | |
1763 }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ | |
1764 ppDirectory = &sqlite3_temp_directory; | |
1765 } | |
1766 assert( !ppDirectory || type==SQLITE_WIN32_DATA_DIRECTORY_TYPE | |
1767 || type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE | |
1768 ); | |
1769 assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) ); | |
1770 if( ppDirectory ){ | |
1771 char *zValueUtf8 = 0; | |
1772 if( zValue && zValue[0] ){ | |
1773 zValueUtf8 = winUnicodeToUtf8(zValue); | |
1774 if ( zValueUtf8==0 ){ | |
1775 return SQLITE_NOMEM; | |
1776 } | |
1777 } | |
1778 sqlite3_free(*ppDirectory); | |
1779 *ppDirectory = zValueUtf8; | |
1780 return SQLITE_OK; | |
1781 } | |
1782 return SQLITE_ERROR; | |
1783 } | |
1784 | |
1785 /* | |
1786 ** The return value of winGetLastErrorMsg | |
1787 ** is zero if the error message fits in the buffer, or non-zero | |
1788 ** otherwise (if the message was truncated). | |
1789 */ | |
1790 static int winGetLastErrorMsg(DWORD lastErrno, int nBuf, char *zBuf){ | |
1791 /* FormatMessage returns 0 on failure. Otherwise it | |
1792 ** returns the number of TCHARs written to the output | |
1793 ** buffer, excluding the terminating null char. | |
1794 */ | |
1795 DWORD dwLen = 0; | |
1796 char *zOut = 0; | |
1797 | |
1798 if( osIsNT() ){ | |
1799 #if SQLITE_OS_WINRT | |
1800 WCHAR zTempWide[SQLITE_WIN32_MAX_ERRMSG_CHARS+1]; | |
1801 dwLen = osFormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | | |
1802 FORMAT_MESSAGE_IGNORE_INSERTS, | |
1803 NULL, | |
1804 lastErrno, | |
1805 0, | |
1806 zTempWide, | |
1807 SQLITE_WIN32_MAX_ERRMSG_CHARS, | |
1808 0); | |
1809 #else | |
1810 LPWSTR zTempWide = NULL; | |
1811 dwLen = osFormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
1812 FORMAT_MESSAGE_FROM_SYSTEM | | |
1813 FORMAT_MESSAGE_IGNORE_INSERTS, | |
1814 NULL, | |
1815 lastErrno, | |
1816 0, | |
1817 (LPWSTR) &zTempWide, | |
1818 0, | |
1819 0); | |
1820 #endif | |
1821 if( dwLen > 0 ){ | |
1822 /* allocate a buffer and convert to UTF8 */ | |
1823 sqlite3BeginBenignMalloc(); | |
1824 zOut = winUnicodeToUtf8(zTempWide); | |
1825 sqlite3EndBenignMalloc(); | |
1826 #if !SQLITE_OS_WINRT | |
1827 /* free the system buffer allocated by FormatMessage */ | |
1828 osLocalFree(zTempWide); | |
1829 #endif | |
1830 } | |
1831 } | |
1832 #ifdef SQLITE_WIN32_HAS_ANSI | |
1833 else{ | |
1834 char *zTemp = NULL; | |
1835 dwLen = osFormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | | |
1836 FORMAT_MESSAGE_FROM_SYSTEM | | |
1837 FORMAT_MESSAGE_IGNORE_INSERTS, | |
1838 NULL, | |
1839 lastErrno, | |
1840 0, | |
1841 (LPSTR) &zTemp, | |
1842 0, | |
1843 0); | |
1844 if( dwLen > 0 ){ | |
1845 /* allocate a buffer and convert to UTF8 */ | |
1846 sqlite3BeginBenignMalloc(); | |
1847 zOut = sqlite3_win32_mbcs_to_utf8(zTemp); | |
1848 sqlite3EndBenignMalloc(); | |
1849 /* free the system buffer allocated by FormatMessage */ | |
1850 osLocalFree(zTemp); | |
1851 } | |
1852 } | |
1853 #endif | |
1854 if( 0 == dwLen ){ | |
1855 sqlite3_snprintf(nBuf, zBuf, "OsError 0x%lx (%lu)", lastErrno, lastErrno); | |
1856 }else{ | |
1857 /* copy a maximum of nBuf chars to output buffer */ | |
1858 sqlite3_snprintf(nBuf, zBuf, "%s", zOut); | |
1859 /* free the UTF8 buffer */ | |
1860 sqlite3_free(zOut); | |
1861 } | |
1862 return 0; | |
1863 } | |
1864 | |
1865 /* | |
1866 ** | |
1867 ** This function - winLogErrorAtLine() - is only ever called via the macro | |
1868 ** winLogError(). | |
1869 ** | |
1870 ** This routine is invoked after an error occurs in an OS function. | |
1871 ** It logs a message using sqlite3_log() containing the current value of | |
1872 ** error code and, if possible, the human-readable equivalent from | |
1873 ** FormatMessage. | |
1874 ** | |
1875 ** The first argument passed to the macro should be the error code that | |
1876 ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN). | |
1877 ** The two subsequent arguments should be the name of the OS function that | |
1878 ** failed and the associated file-system path, if any. | |
1879 */ | |
1880 #define winLogError(a,b,c,d) winLogErrorAtLine(a,b,c,d,__LINE__) | |
1881 static int winLogErrorAtLine( | |
1882 int errcode, /* SQLite error code */ | |
1883 DWORD lastErrno, /* Win32 last error */ | |
1884 const char *zFunc, /* Name of OS function that failed */ | |
1885 const char *zPath, /* File path associated with error */ | |
1886 int iLine /* Source line number where error occurred */ | |
1887 ){ | |
1888 char zMsg[500]; /* Human readable error text */ | |
1889 int i; /* Loop counter */ | |
1890 | |
1891 zMsg[0] = 0; | |
1892 winGetLastErrorMsg(lastErrno, sizeof(zMsg), zMsg); | |
1893 assert( errcode!=SQLITE_OK ); | |
1894 if( zPath==0 ) zPath = ""; | |
1895 for(i=0; zMsg[i] && zMsg[i]!='\r' && zMsg[i]!='\n'; i++){} | |
1896 zMsg[i] = 0; | |
1897 sqlite3_log(errcode, | |
1898 "os_win.c:%d: (%lu) %s(%s) - %s", | |
1899 iLine, lastErrno, zFunc, zPath, zMsg | |
1900 ); | |
1901 | |
1902 return errcode; | |
1903 } | |
1904 | |
1905 /* | |
1906 ** The number of times that a ReadFile(), WriteFile(), and DeleteFile() | |
1907 ** will be retried following a locking error - probably caused by | |
1908 ** antivirus software. Also the initial delay before the first retry. | |
1909 ** The delay increases linearly with each retry. | |
1910 */ | |
1911 #ifndef SQLITE_WIN32_IOERR_RETRY | |
1912 # define SQLITE_WIN32_IOERR_RETRY 10 | |
1913 #endif | |
1914 #ifndef SQLITE_WIN32_IOERR_RETRY_DELAY | |
1915 # define SQLITE_WIN32_IOERR_RETRY_DELAY 25 | |
1916 #endif | |
1917 static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY; | |
1918 static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY; | |
1919 | |
1920 /* | |
1921 ** The "winIoerrCanRetry1" macro is used to determine if a particular I/O | |
1922 ** error code obtained via GetLastError() is eligible to be retried. It | |
1923 ** must accept the error code DWORD as its only argument and should return | |
1924 ** non-zero if the error code is transient in nature and the operation | |
1925 ** responsible for generating the original error might succeed upon being | |
1926 ** retried. The argument to this macro should be a variable. | |
1927 ** | |
1928 ** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it | |
1929 ** is defined, it will be consulted only when the macro "winIoerrCanRetry1" | |
1930 ** returns zero. The "winIoerrCanRetry2" macro is completely optional and | |
1931 ** may be used to include additional error codes in the set that should | |
1932 ** result in the failing I/O operation being retried by the caller. If | |
1933 ** defined, the "winIoerrCanRetry2" macro must exhibit external semantics | |
1934 ** identical to those of the "winIoerrCanRetry1" macro. | |
1935 */ | |
1936 #if !defined(winIoerrCanRetry1) | |
1937 #define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \ | |
1938 ((a)==ERROR_SHARING_VIOLATION) || \ | |
1939 ((a)==ERROR_LOCK_VIOLATION) || \ | |
1940 ((a)==ERROR_DEV_NOT_EXIST) || \ | |
1941 ((a)==ERROR_NETNAME_DELETED) || \ | |
1942 ((a)==ERROR_SEM_TIMEOUT) || \ | |
1943 ((a)==ERROR_NETWORK_UNREACHABLE)) | |
1944 #endif | |
1945 | |
1946 /* | |
1947 ** If a ReadFile() or WriteFile() error occurs, invoke this routine | |
1948 ** to see if it should be retried. Return TRUE to retry. Return FALSE | |
1949 ** to give up with an error. | |
1950 */ | |
1951 static int winRetryIoerr(int *pnRetry, DWORD *pError){ | |
1952 DWORD e = osGetLastError(); | |
1953 if( *pnRetry>=winIoerrRetry ){ | |
1954 if( pError ){ | |
1955 *pError = e; | |
1956 } | |
1957 return 0; | |
1958 } | |
1959 if( winIoerrCanRetry1(e) ){ | |
1960 sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); | |
1961 ++*pnRetry; | |
1962 return 1; | |
1963 } | |
1964 #if defined(winIoerrCanRetry2) | |
1965 else if( winIoerrCanRetry2(e) ){ | |
1966 sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry)); | |
1967 ++*pnRetry; | |
1968 return 1; | |
1969 } | |
1970 #endif | |
1971 if( pError ){ | |
1972 *pError = e; | |
1973 } | |
1974 return 0; | |
1975 } | |
1976 | |
1977 /* | |
1978 ** Log a I/O error retry episode. | |
1979 */ | |
1980 static void winLogIoerr(int nRetry, int lineno){ | |
1981 if( nRetry ){ | |
1982 sqlite3_log(SQLITE_NOTICE, | |
1983 "delayed %dms for lock/sharing conflict at line %d", | |
1984 winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno | |
1985 ); | |
1986 } | |
1987 } | |
1988 | |
1989 #if SQLITE_OS_WINCE | |
1990 /************************************************************************* | |
1991 ** This section contains code for WinCE only. | |
1992 */ | |
1993 #if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API | |
1994 /* | |
1995 ** The MSVC CRT on Windows CE may not have a localtime() function. So | |
1996 ** create a substitute. | |
1997 */ | |
1998 #include <time.h> | |
1999 struct tm *__cdecl localtime(const time_t *t) | |
2000 { | |
2001 static struct tm y; | |
2002 FILETIME uTm, lTm; | |
2003 SYSTEMTIME pTm; | |
2004 sqlite3_int64 t64; | |
2005 t64 = *t; | |
2006 t64 = (t64 + 11644473600)*10000000; | |
2007 uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF); | |
2008 uTm.dwHighDateTime= (DWORD)(t64 >> 32); | |
2009 osFileTimeToLocalFileTime(&uTm,&lTm); | |
2010 osFileTimeToSystemTime(&lTm,&pTm); | |
2011 y.tm_year = pTm.wYear - 1900; | |
2012 y.tm_mon = pTm.wMonth - 1; | |
2013 y.tm_wday = pTm.wDayOfWeek; | |
2014 y.tm_mday = pTm.wDay; | |
2015 y.tm_hour = pTm.wHour; | |
2016 y.tm_min = pTm.wMinute; | |
2017 y.tm_sec = pTm.wSecond; | |
2018 return &y; | |
2019 } | |
2020 #endif | |
2021 | |
2022 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)] | |
2023 | |
2024 /* | |
2025 ** Acquire a lock on the handle h | |
2026 */ | |
2027 static void winceMutexAcquire(HANDLE h){ | |
2028 DWORD dwErr; | |
2029 do { | |
2030 dwErr = osWaitForSingleObject(h, INFINITE); | |
2031 } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED); | |
2032 } | |
2033 /* | |
2034 ** Release a lock acquired by winceMutexAcquire() | |
2035 */ | |
2036 #define winceMutexRelease(h) ReleaseMutex(h) | |
2037 | |
2038 /* | |
2039 ** Create the mutex and shared memory used for locking in the file | |
2040 ** descriptor pFile | |
2041 */ | |
2042 static int winceCreateLock(const char *zFilename, winFile *pFile){ | |
2043 LPWSTR zTok; | |
2044 LPWSTR zName; | |
2045 DWORD lastErrno; | |
2046 BOOL bLogged = FALSE; | |
2047 BOOL bInit = TRUE; | |
2048 | |
2049 zName = winUtf8ToUnicode(zFilename); | |
2050 if( zName==0 ){ | |
2051 /* out of memory */ | |
2052 return SQLITE_IOERR_NOMEM; | |
2053 } | |
2054 | |
2055 /* Initialize the local lockdata */ | |
2056 memset(&pFile->local, 0, sizeof(pFile->local)); | |
2057 | |
2058 /* Replace the backslashes from the filename and lowercase it | |
2059 ** to derive a mutex name. */ | |
2060 zTok = osCharLowerW(zName); | |
2061 for (;*zTok;zTok++){ | |
2062 if (*zTok == '\\') *zTok = '_'; | |
2063 } | |
2064 | |
2065 /* Create/open the named mutex */ | |
2066 pFile->hMutex = osCreateMutexW(NULL, FALSE, zName); | |
2067 if (!pFile->hMutex){ | |
2068 pFile->lastErrno = osGetLastError(); | |
2069 sqlite3_free(zName); | |
2070 return winLogError(SQLITE_IOERR, pFile->lastErrno, | |
2071 "winceCreateLock1", zFilename); | |
2072 } | |
2073 | |
2074 /* Acquire the mutex before continuing */ | |
2075 winceMutexAcquire(pFile->hMutex); | |
2076 | |
2077 /* Since the names of named mutexes, semaphores, file mappings etc are | |
2078 ** case-sensitive, take advantage of that by uppercasing the mutex name | |
2079 ** and using that as the shared filemapping name. | |
2080 */ | |
2081 osCharUpperW(zName); | |
2082 pFile->hShared = osCreateFileMappingW(INVALID_HANDLE_VALUE, NULL, | |
2083 PAGE_READWRITE, 0, sizeof(winceLock), | |
2084 zName); | |
2085 | |
2086 /* Set a flag that indicates we're the first to create the memory so it | |
2087 ** must be zero-initialized */ | |
2088 lastErrno = osGetLastError(); | |
2089 if (lastErrno == ERROR_ALREADY_EXISTS){ | |
2090 bInit = FALSE; | |
2091 } | |
2092 | |
2093 sqlite3_free(zName); | |
2094 | |
2095 /* If we succeeded in making the shared memory handle, map it. */ | |
2096 if( pFile->hShared ){ | |
2097 pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, | |
2098 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); | |
2099 /* If mapping failed, close the shared memory handle and erase it */ | |
2100 if( !pFile->shared ){ | |
2101 pFile->lastErrno = osGetLastError(); | |
2102 winLogError(SQLITE_IOERR, pFile->lastErrno, | |
2103 "winceCreateLock2", zFilename); | |
2104 bLogged = TRUE; | |
2105 osCloseHandle(pFile->hShared); | |
2106 pFile->hShared = NULL; | |
2107 } | |
2108 } | |
2109 | |
2110 /* If shared memory could not be created, then close the mutex and fail */ | |
2111 if( pFile->hShared==NULL ){ | |
2112 if( !bLogged ){ | |
2113 pFile->lastErrno = lastErrno; | |
2114 winLogError(SQLITE_IOERR, pFile->lastErrno, | |
2115 "winceCreateLock3", zFilename); | |
2116 bLogged = TRUE; | |
2117 } | |
2118 winceMutexRelease(pFile->hMutex); | |
2119 osCloseHandle(pFile->hMutex); | |
2120 pFile->hMutex = NULL; | |
2121 return SQLITE_IOERR; | |
2122 } | |
2123 | |
2124 /* Initialize the shared memory if we're supposed to */ | |
2125 if( bInit ){ | |
2126 memset(pFile->shared, 0, sizeof(winceLock)); | |
2127 } | |
2128 | |
2129 winceMutexRelease(pFile->hMutex); | |
2130 return SQLITE_OK; | |
2131 } | |
2132 | |
2133 /* | |
2134 ** Destroy the part of winFile that deals with wince locks | |
2135 */ | |
2136 static void winceDestroyLock(winFile *pFile){ | |
2137 if (pFile->hMutex){ | |
2138 /* Acquire the mutex */ | |
2139 winceMutexAcquire(pFile->hMutex); | |
2140 | |
2141 /* The following blocks should probably assert in debug mode, but they | |
2142 are to cleanup in case any locks remained open */ | |
2143 if (pFile->local.nReaders){ | |
2144 pFile->shared->nReaders --; | |
2145 } | |
2146 if (pFile->local.bReserved){ | |
2147 pFile->shared->bReserved = FALSE; | |
2148 } | |
2149 if (pFile->local.bPending){ | |
2150 pFile->shared->bPending = FALSE; | |
2151 } | |
2152 if (pFile->local.bExclusive){ | |
2153 pFile->shared->bExclusive = FALSE; | |
2154 } | |
2155 | |
2156 /* De-reference and close our copy of the shared memory handle */ | |
2157 osUnmapViewOfFile(pFile->shared); | |
2158 osCloseHandle(pFile->hShared); | |
2159 | |
2160 /* Done with the mutex */ | |
2161 winceMutexRelease(pFile->hMutex); | |
2162 osCloseHandle(pFile->hMutex); | |
2163 pFile->hMutex = NULL; | |
2164 } | |
2165 } | |
2166 | |
2167 /* | |
2168 ** An implementation of the LockFile() API of Windows for CE | |
2169 */ | |
2170 static BOOL winceLockFile( | |
2171 LPHANDLE phFile, | |
2172 DWORD dwFileOffsetLow, | |
2173 DWORD dwFileOffsetHigh, | |
2174 DWORD nNumberOfBytesToLockLow, | |
2175 DWORD nNumberOfBytesToLockHigh | |
2176 ){ | |
2177 winFile *pFile = HANDLE_TO_WINFILE(phFile); | |
2178 BOOL bReturn = FALSE; | |
2179 | |
2180 UNUSED_PARAMETER(dwFileOffsetHigh); | |
2181 UNUSED_PARAMETER(nNumberOfBytesToLockHigh); | |
2182 | |
2183 if (!pFile->hMutex) return TRUE; | |
2184 winceMutexAcquire(pFile->hMutex); | |
2185 | |
2186 /* Wanting an exclusive lock? */ | |
2187 if (dwFileOffsetLow == (DWORD)SHARED_FIRST | |
2188 && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){ | |
2189 if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){ | |
2190 pFile->shared->bExclusive = TRUE; | |
2191 pFile->local.bExclusive = TRUE; | |
2192 bReturn = TRUE; | |
2193 } | |
2194 } | |
2195 | |
2196 /* Want a read-only lock? */ | |
2197 else if (dwFileOffsetLow == (DWORD)SHARED_FIRST && | |
2198 nNumberOfBytesToLockLow == 1){ | |
2199 if (pFile->shared->bExclusive == 0){ | |
2200 pFile->local.nReaders ++; | |
2201 if (pFile->local.nReaders == 1){ | |
2202 pFile->shared->nReaders ++; | |
2203 } | |
2204 bReturn = TRUE; | |
2205 } | |
2206 } | |
2207 | |
2208 /* Want a pending lock? */ | |
2209 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE | |
2210 && nNumberOfBytesToLockLow == 1){ | |
2211 /* If no pending lock has been acquired, then acquire it */ | |
2212 if (pFile->shared->bPending == 0) { | |
2213 pFile->shared->bPending = TRUE; | |
2214 pFile->local.bPending = TRUE; | |
2215 bReturn = TRUE; | |
2216 } | |
2217 } | |
2218 | |
2219 /* Want a reserved lock? */ | |
2220 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE | |
2221 && nNumberOfBytesToLockLow == 1){ | |
2222 if (pFile->shared->bReserved == 0) { | |
2223 pFile->shared->bReserved = TRUE; | |
2224 pFile->local.bReserved = TRUE; | |
2225 bReturn = TRUE; | |
2226 } | |
2227 } | |
2228 | |
2229 winceMutexRelease(pFile->hMutex); | |
2230 return bReturn; | |
2231 } | |
2232 | |
2233 /* | |
2234 ** An implementation of the UnlockFile API of Windows for CE | |
2235 */ | |
2236 static BOOL winceUnlockFile( | |
2237 LPHANDLE phFile, | |
2238 DWORD dwFileOffsetLow, | |
2239 DWORD dwFileOffsetHigh, | |
2240 DWORD nNumberOfBytesToUnlockLow, | |
2241 DWORD nNumberOfBytesToUnlockHigh | |
2242 ){ | |
2243 winFile *pFile = HANDLE_TO_WINFILE(phFile); | |
2244 BOOL bReturn = FALSE; | |
2245 | |
2246 UNUSED_PARAMETER(dwFileOffsetHigh); | |
2247 UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh); | |
2248 | |
2249 if (!pFile->hMutex) return TRUE; | |
2250 winceMutexAcquire(pFile->hMutex); | |
2251 | |
2252 /* Releasing a reader lock or an exclusive lock */ | |
2253 if (dwFileOffsetLow == (DWORD)SHARED_FIRST){ | |
2254 /* Did we have an exclusive lock? */ | |
2255 if (pFile->local.bExclusive){ | |
2256 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE); | |
2257 pFile->local.bExclusive = FALSE; | |
2258 pFile->shared->bExclusive = FALSE; | |
2259 bReturn = TRUE; | |
2260 } | |
2261 | |
2262 /* Did we just have a reader lock? */ | |
2263 else if (pFile->local.nReaders){ | |
2264 assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE | |
2265 || nNumberOfBytesToUnlockLow == 1); | |
2266 pFile->local.nReaders --; | |
2267 if (pFile->local.nReaders == 0) | |
2268 { | |
2269 pFile->shared->nReaders --; | |
2270 } | |
2271 bReturn = TRUE; | |
2272 } | |
2273 } | |
2274 | |
2275 /* Releasing a pending lock */ | |
2276 else if (dwFileOffsetLow == (DWORD)PENDING_BYTE | |
2277 && nNumberOfBytesToUnlockLow == 1){ | |
2278 if (pFile->local.bPending){ | |
2279 pFile->local.bPending = FALSE; | |
2280 pFile->shared->bPending = FALSE; | |
2281 bReturn = TRUE; | |
2282 } | |
2283 } | |
2284 /* Releasing a reserved lock */ | |
2285 else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE | |
2286 && nNumberOfBytesToUnlockLow == 1){ | |
2287 if (pFile->local.bReserved) { | |
2288 pFile->local.bReserved = FALSE; | |
2289 pFile->shared->bReserved = FALSE; | |
2290 bReturn = TRUE; | |
2291 } | |
2292 } | |
2293 | |
2294 winceMutexRelease(pFile->hMutex); | |
2295 return bReturn; | |
2296 } | |
2297 /* | |
2298 ** End of the special code for wince | |
2299 *****************************************************************************/ | |
2300 #endif /* SQLITE_OS_WINCE */ | |
2301 | |
2302 /* | |
2303 ** Lock a file region. | |
2304 */ | |
2305 static BOOL winLockFile( | |
2306 LPHANDLE phFile, | |
2307 DWORD flags, | |
2308 DWORD offsetLow, | |
2309 DWORD offsetHigh, | |
2310 DWORD numBytesLow, | |
2311 DWORD numBytesHigh | |
2312 ){ | |
2313 #if SQLITE_OS_WINCE | |
2314 /* | |
2315 ** NOTE: Windows CE is handled differently here due its lack of the Win32 | |
2316 ** API LockFile. | |
2317 */ | |
2318 return winceLockFile(phFile, offsetLow, offsetHigh, | |
2319 numBytesLow, numBytesHigh); | |
2320 #else | |
2321 if( osIsNT() ){ | |
2322 OVERLAPPED ovlp; | |
2323 memset(&ovlp, 0, sizeof(OVERLAPPED)); | |
2324 ovlp.Offset = offsetLow; | |
2325 ovlp.OffsetHigh = offsetHigh; | |
2326 return osLockFileEx(*phFile, flags, 0, numBytesLow, numBytesHigh, &ovlp); | |
2327 }else{ | |
2328 return osLockFile(*phFile, offsetLow, offsetHigh, numBytesLow, | |
2329 numBytesHigh); | |
2330 } | |
2331 #endif | |
2332 } | |
2333 | |
2334 /* | |
2335 ** Unlock a file region. | |
2336 */ | |
2337 static BOOL winUnlockFile( | |
2338 LPHANDLE phFile, | |
2339 DWORD offsetLow, | |
2340 DWORD offsetHigh, | |
2341 DWORD numBytesLow, | |
2342 DWORD numBytesHigh | |
2343 ){ | |
2344 #if SQLITE_OS_WINCE | |
2345 /* | |
2346 ** NOTE: Windows CE is handled differently here due its lack of the Win32 | |
2347 ** API UnlockFile. | |
2348 */ | |
2349 return winceUnlockFile(phFile, offsetLow, offsetHigh, | |
2350 numBytesLow, numBytesHigh); | |
2351 #else | |
2352 if( osIsNT() ){ | |
2353 OVERLAPPED ovlp; | |
2354 memset(&ovlp, 0, sizeof(OVERLAPPED)); | |
2355 ovlp.Offset = offsetLow; | |
2356 ovlp.OffsetHigh = offsetHigh; | |
2357 return osUnlockFileEx(*phFile, 0, numBytesLow, numBytesHigh, &ovlp); | |
2358 }else{ | |
2359 return osUnlockFile(*phFile, offsetLow, offsetHigh, numBytesLow, | |
2360 numBytesHigh); | |
2361 } | |
2362 #endif | |
2363 } | |
2364 | |
2365 /***************************************************************************** | |
2366 ** The next group of routines implement the I/O methods specified | |
2367 ** by the sqlite3_io_methods object. | |
2368 ******************************************************************************/ | |
2369 | |
2370 /* | |
2371 ** Some Microsoft compilers lack this definition. | |
2372 */ | |
2373 #ifndef INVALID_SET_FILE_POINTER | |
2374 # define INVALID_SET_FILE_POINTER ((DWORD)-1) | |
2375 #endif | |
2376 | |
2377 /* | |
2378 ** Move the current position of the file handle passed as the first | |
2379 ** argument to offset iOffset within the file. If successful, return 0. | |
2380 ** Otherwise, set pFile->lastErrno and return non-zero. | |
2381 */ | |
2382 static int winSeekFile(winFile *pFile, sqlite3_int64 iOffset){ | |
2383 #if !SQLITE_OS_WINRT | |
2384 LONG upperBits; /* Most sig. 32 bits of new offset */ | |
2385 LONG lowerBits; /* Least sig. 32 bits of new offset */ | |
2386 DWORD dwRet; /* Value returned by SetFilePointer() */ | |
2387 DWORD lastErrno; /* Value returned by GetLastError() */ | |
2388 | |
2389 OSTRACE(("SEEK file=%p, offset=%lld\n", pFile->h, iOffset)); | |
2390 | |
2391 upperBits = (LONG)((iOffset>>32) & 0x7fffffff); | |
2392 lowerBits = (LONG)(iOffset & 0xffffffff); | |
2393 | |
2394 /* API oddity: If successful, SetFilePointer() returns a dword | |
2395 ** containing the lower 32-bits of the new file-offset. Or, if it fails, | |
2396 ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, | |
2397 ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine | |
2398 ** whether an error has actually occurred, it is also necessary to call | |
2399 ** GetLastError(). | |
2400 */ | |
2401 dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN); | |
2402 | |
2403 if( (dwRet==INVALID_SET_FILE_POINTER | |
2404 && ((lastErrno = osGetLastError())!=NO_ERROR)) ){ | |
2405 pFile->lastErrno = lastErrno; | |
2406 winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, | |
2407 "winSeekFile", pFile->zPath); | |
2408 OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); | |
2409 return 1; | |
2410 } | |
2411 | |
2412 OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); | |
2413 return 0; | |
2414 #else | |
2415 /* | |
2416 ** Same as above, except that this implementation works for WinRT. | |
2417 */ | |
2418 | |
2419 LARGE_INTEGER x; /* The new offset */ | |
2420 BOOL bRet; /* Value returned by SetFilePointerEx() */ | |
2421 | |
2422 x.QuadPart = iOffset; | |
2423 bRet = osSetFilePointerEx(pFile->h, x, 0, FILE_BEGIN); | |
2424 | |
2425 if(!bRet){ | |
2426 pFile->lastErrno = osGetLastError(); | |
2427 winLogError(SQLITE_IOERR_SEEK, pFile->lastErrno, | |
2428 "winSeekFile", pFile->zPath); | |
2429 OSTRACE(("SEEK file=%p, rc=SQLITE_IOERR_SEEK\n", pFile->h)); | |
2430 return 1; | |
2431 } | |
2432 | |
2433 OSTRACE(("SEEK file=%p, rc=SQLITE_OK\n", pFile->h)); | |
2434 return 0; | |
2435 #endif | |
2436 } | |
2437 | |
2438 #if SQLITE_MAX_MMAP_SIZE>0 | |
2439 /* Forward references to VFS helper methods used for memory mapped files */ | |
2440 static int winMapfile(winFile*, sqlite3_int64); | |
2441 static int winUnmapfile(winFile*); | |
2442 #endif | |
2443 | |
2444 /* | |
2445 ** Close a file. | |
2446 ** | |
2447 ** It is reported that an attempt to close a handle might sometimes | |
2448 ** fail. This is a very unreasonable result, but Windows is notorious | |
2449 ** for being unreasonable so I do not doubt that it might happen. If | |
2450 ** the close fails, we pause for 100 milliseconds and try again. As | |
2451 ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before | |
2452 ** giving up and returning an error. | |
2453 */ | |
2454 #define MX_CLOSE_ATTEMPT 3 | |
2455 static int winClose(sqlite3_file *id){ | |
2456 int rc, cnt = 0; | |
2457 winFile *pFile = (winFile*)id; | |
2458 | |
2459 assert( id!=0 ); | |
2460 #ifndef SQLITE_OMIT_WAL | |
2461 assert( pFile->pShm==0 ); | |
2462 #endif | |
2463 assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE ); | |
2464 OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n", | |
2465 osGetCurrentProcessId(), pFile, pFile->h)); | |
2466 | |
2467 #if SQLITE_MAX_MMAP_SIZE>0 | |
2468 winUnmapfile(pFile); | |
2469 #endif | |
2470 | |
2471 do{ | |
2472 rc = osCloseHandle(pFile->h); | |
2473 /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */ | |
2474 }while( rc==0 && ++cnt < MX_CLOSE_ATTEMPT && (sqlite3_win32_sleep(100), 1) ); | |
2475 #if SQLITE_OS_WINCE | |
2476 #define WINCE_DELETION_ATTEMPTS 3 | |
2477 winceDestroyLock(pFile); | |
2478 if( pFile->zDeleteOnClose ){ | |
2479 int cnt = 0; | |
2480 while( | |
2481 osDeleteFileW(pFile->zDeleteOnClose)==0 | |
2482 && osGetFileAttributesW(pFile->zDeleteOnClose)!=0xffffffff | |
2483 && cnt++ < WINCE_DELETION_ATTEMPTS | |
2484 ){ | |
2485 sqlite3_win32_sleep(100); /* Wait a little before trying again */ | |
2486 } | |
2487 sqlite3_free(pFile->zDeleteOnClose); | |
2488 } | |
2489 #endif | |
2490 if( rc ){ | |
2491 pFile->h = NULL; | |
2492 } | |
2493 OpenCounter(-1); | |
2494 OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n", | |
2495 osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed")); | |
2496 return rc ? SQLITE_OK | |
2497 : winLogError(SQLITE_IOERR_CLOSE, osGetLastError(), | |
2498 "winClose", pFile->zPath); | |
2499 } | |
2500 | |
2501 /* | |
2502 ** Read data from a file into a buffer. Return SQLITE_OK if all | |
2503 ** bytes were read successfully and SQLITE_IOERR if anything goes | |
2504 ** wrong. | |
2505 */ | |
2506 static int winRead( | |
2507 sqlite3_file *id, /* File to read from */ | |
2508 void *pBuf, /* Write content into this buffer */ | |
2509 int amt, /* Number of bytes to read */ | |
2510 sqlite3_int64 offset /* Begin reading at this offset */ | |
2511 ){ | |
2512 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2513 OVERLAPPED overlapped; /* The offset for ReadFile. */ | |
2514 #endif | |
2515 winFile *pFile = (winFile*)id; /* file handle */ | |
2516 DWORD nRead; /* Number of bytes actually read from file */ | |
2517 int nRetry = 0; /* Number of retrys */ | |
2518 | |
2519 assert( id!=0 ); | |
2520 assert( amt>0 ); | |
2521 assert( offset>=0 ); | |
2522 SimulateIOError(return SQLITE_IOERR_READ); | |
2523 OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " | |
2524 "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, | |
2525 pFile->h, pBuf, amt, offset, pFile->locktype)); | |
2526 | |
2527 #if SQLITE_MAX_MMAP_SIZE>0 | |
2528 /* Deal with as much of this read request as possible by transfering | |
2529 ** data from the memory mapping using memcpy(). */ | |
2530 if( offset<pFile->mmapSize ){ | |
2531 if( offset+amt <= pFile->mmapSize ){ | |
2532 memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt); | |
2533 OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2534 osGetCurrentProcessId(), pFile, pFile->h)); | |
2535 return SQLITE_OK; | |
2536 }else{ | |
2537 int nCopy = (int)(pFile->mmapSize - offset); | |
2538 memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], nCopy); | |
2539 pBuf = &((u8 *)pBuf)[nCopy]; | |
2540 amt -= nCopy; | |
2541 offset += nCopy; | |
2542 } | |
2543 } | |
2544 #endif | |
2545 | |
2546 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2547 if( winSeekFile(pFile, offset) ){ | |
2548 OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", | |
2549 osGetCurrentProcessId(), pFile, pFile->h)); | |
2550 return SQLITE_FULL; | |
2551 } | |
2552 while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){ | |
2553 #else | |
2554 memset(&overlapped, 0, sizeof(OVERLAPPED)); | |
2555 overlapped.Offset = (LONG)(offset & 0xffffffff); | |
2556 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); | |
2557 while( !osReadFile(pFile->h, pBuf, amt, &nRead, &overlapped) && | |
2558 osGetLastError()!=ERROR_HANDLE_EOF ){ | |
2559 #endif | |
2560 DWORD lastErrno; | |
2561 if( winRetryIoerr(&nRetry, &lastErrno) ) continue; | |
2562 pFile->lastErrno = lastErrno; | |
2563 OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n", | |
2564 osGetCurrentProcessId(), pFile, pFile->h)); | |
2565 return winLogError(SQLITE_IOERR_READ, pFile->lastErrno, | |
2566 "winRead", pFile->zPath); | |
2567 } | |
2568 winLogIoerr(nRetry, __LINE__); | |
2569 if( nRead<(DWORD)amt ){ | |
2570 /* Unread parts of the buffer must be zero-filled */ | |
2571 memset(&((char*)pBuf)[nRead], 0, amt-nRead); | |
2572 OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n", | |
2573 osGetCurrentProcessId(), pFile, pFile->h)); | |
2574 return SQLITE_IOERR_SHORT_READ; | |
2575 } | |
2576 | |
2577 OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2578 osGetCurrentProcessId(), pFile, pFile->h)); | |
2579 return SQLITE_OK; | |
2580 } | |
2581 | |
2582 /* | |
2583 ** Write data from a buffer into a file. Return SQLITE_OK on success | |
2584 ** or some other error code on failure. | |
2585 */ | |
2586 static int winWrite( | |
2587 sqlite3_file *id, /* File to write into */ | |
2588 const void *pBuf, /* The bytes to be written */ | |
2589 int amt, /* Number of bytes to write */ | |
2590 sqlite3_int64 offset /* Offset into the file to begin writing at */ | |
2591 ){ | |
2592 int rc = 0; /* True if error has occurred, else false */ | |
2593 winFile *pFile = (winFile*)id; /* File handle */ | |
2594 int nRetry = 0; /* Number of retries */ | |
2595 | |
2596 assert( amt>0 ); | |
2597 assert( pFile ); | |
2598 SimulateIOError(return SQLITE_IOERR_WRITE); | |
2599 SimulateDiskfullError(return SQLITE_FULL); | |
2600 | |
2601 OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, " | |
2602 "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile, | |
2603 pFile->h, pBuf, amt, offset, pFile->locktype)); | |
2604 | |
2605 #if defined(SQLITE_MMAP_READWRITE) && SQLITE_MAX_MMAP_SIZE>0 | |
2606 /* Deal with as much of this write request as possible by transfering | |
2607 ** data from the memory mapping using memcpy(). */ | |
2608 if( offset<pFile->mmapSize ){ | |
2609 if( offset+amt <= pFile->mmapSize ){ | |
2610 memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt); | |
2611 OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2612 osGetCurrentProcessId(), pFile, pFile->h)); | |
2613 return SQLITE_OK; | |
2614 }else{ | |
2615 int nCopy = (int)(pFile->mmapSize - offset); | |
2616 memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, nCopy); | |
2617 pBuf = &((u8 *)pBuf)[nCopy]; | |
2618 amt -= nCopy; | |
2619 offset += nCopy; | |
2620 } | |
2621 } | |
2622 #endif | |
2623 | |
2624 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2625 rc = winSeekFile(pFile, offset); | |
2626 if( rc==0 ){ | |
2627 #else | |
2628 { | |
2629 #endif | |
2630 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2631 OVERLAPPED overlapped; /* The offset for WriteFile. */ | |
2632 #endif | |
2633 u8 *aRem = (u8 *)pBuf; /* Data yet to be written */ | |
2634 int nRem = amt; /* Number of bytes yet to be written */ | |
2635 DWORD nWrite; /* Bytes written by each WriteFile() call */ | |
2636 DWORD lastErrno = NO_ERROR; /* Value returned by GetLastError() */ | |
2637 | |
2638 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2639 memset(&overlapped, 0, sizeof(OVERLAPPED)); | |
2640 overlapped.Offset = (LONG)(offset & 0xffffffff); | |
2641 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); | |
2642 #endif | |
2643 | |
2644 while( nRem>0 ){ | |
2645 #if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2646 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ | |
2647 #else | |
2648 if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ | |
2649 #endif | |
2650 if( winRetryIoerr(&nRetry, &lastErrno) ) continue; | |
2651 break; | |
2652 } | |
2653 assert( nWrite==0 || nWrite<=(DWORD)nRem ); | |
2654 if( nWrite==0 || nWrite>(DWORD)nRem ){ | |
2655 lastErrno = osGetLastError(); | |
2656 break; | |
2657 } | |
2658 #if !SQLITE_OS_WINCE && !defined(SQLITE_WIN32_NO_OVERLAPPED) | |
2659 offset += nWrite; | |
2660 overlapped.Offset = (LONG)(offset & 0xffffffff); | |
2661 overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); | |
2662 #endif | |
2663 aRem += nWrite; | |
2664 nRem -= nWrite; | |
2665 } | |
2666 if( nRem>0 ){ | |
2667 pFile->lastErrno = lastErrno; | |
2668 rc = 1; | |
2669 } | |
2670 } | |
2671 | |
2672 if( rc ){ | |
2673 if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL ) | |
2674 || ( pFile->lastErrno==ERROR_DISK_FULL )){ | |
2675 OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n", | |
2676 osGetCurrentProcessId(), pFile, pFile->h)); | |
2677 return winLogError(SQLITE_FULL, pFile->lastErrno, | |
2678 "winWrite1", pFile->zPath); | |
2679 } | |
2680 OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n", | |
2681 osGetCurrentProcessId(), pFile, pFile->h)); | |
2682 return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno, | |
2683 "winWrite2", pFile->zPath); | |
2684 }else{ | |
2685 winLogIoerr(nRetry, __LINE__); | |
2686 } | |
2687 OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2688 osGetCurrentProcessId(), pFile, pFile->h)); | |
2689 return SQLITE_OK; | |
2690 } | |
2691 | |
2692 /* | |
2693 ** Truncate an open file to a specified size | |
2694 */ | |
2695 static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){ | |
2696 winFile *pFile = (winFile*)id; /* File handle object */ | |
2697 int rc = SQLITE_OK; /* Return code for this function */ | |
2698 DWORD lastErrno; | |
2699 | |
2700 assert( pFile ); | |
2701 SimulateIOError(return SQLITE_IOERR_TRUNCATE); | |
2702 OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n", | |
2703 osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype)); | |
2704 | |
2705 /* If the user has configured a chunk-size for this file, truncate the | |
2706 ** file so that it consists of an integer number of chunks (i.e. the | |
2707 ** actual file size after the operation may be larger than the requested | |
2708 ** size). | |
2709 */ | |
2710 if( pFile->szChunk>0 ){ | |
2711 nByte = ((nByte + pFile->szChunk - 1)/pFile->szChunk) * pFile->szChunk; | |
2712 } | |
2713 | |
2714 /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */ | |
2715 if( winSeekFile(pFile, nByte) ){ | |
2716 rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, | |
2717 "winTruncate1", pFile->zPath); | |
2718 }else if( 0==osSetEndOfFile(pFile->h) && | |
2719 ((lastErrno = osGetLastError())!=ERROR_USER_MAPPED_FILE) ){ | |
2720 pFile->lastErrno = lastErrno; | |
2721 rc = winLogError(SQLITE_IOERR_TRUNCATE, pFile->lastErrno, | |
2722 "winTruncate2", pFile->zPath); | |
2723 } | |
2724 | |
2725 #if SQLITE_MAX_MMAP_SIZE>0 | |
2726 /* If the file was truncated to a size smaller than the currently | |
2727 ** mapped region, reduce the effective mapping size as well. SQLite will | |
2728 ** use read() and write() to access data beyond this point from now on. | |
2729 */ | |
2730 if( pFile->pMapRegion && nByte<pFile->mmapSize ){ | |
2731 pFile->mmapSize = nByte; | |
2732 } | |
2733 #endif | |
2734 | |
2735 OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n", | |
2736 osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc))); | |
2737 return rc; | |
2738 } | |
2739 | |
2740 #ifdef SQLITE_TEST | |
2741 /* | |
2742 ** Count the number of fullsyncs and normal syncs. This is used to test | |
2743 ** that syncs and fullsyncs are occuring at the right times. | |
2744 */ | |
2745 int sqlite3_sync_count = 0; | |
2746 int sqlite3_fullsync_count = 0; | |
2747 #endif | |
2748 | |
2749 /* | |
2750 ** Make sure all writes to a particular file are committed to disk. | |
2751 */ | |
2752 static int winSync(sqlite3_file *id, int flags){ | |
2753 #ifndef SQLITE_NO_SYNC | |
2754 /* | |
2755 ** Used only when SQLITE_NO_SYNC is not defined. | |
2756 */ | |
2757 BOOL rc; | |
2758 #endif | |
2759 #if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \ | |
2760 defined(SQLITE_HAVE_OS_TRACE) | |
2761 /* | |
2762 ** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or | |
2763 ** OSTRACE() macros. | |
2764 */ | |
2765 winFile *pFile = (winFile*)id; | |
2766 #else | |
2767 UNUSED_PARAMETER(id); | |
2768 #endif | |
2769 | |
2770 assert( pFile ); | |
2771 /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */ | |
2772 assert((flags&0x0F)==SQLITE_SYNC_NORMAL | |
2773 || (flags&0x0F)==SQLITE_SYNC_FULL | |
2774 ); | |
2775 | |
2776 /* Unix cannot, but some systems may return SQLITE_FULL from here. This | |
2777 ** line is to test that doing so does not cause any problems. | |
2778 */ | |
2779 SimulateDiskfullError( return SQLITE_FULL ); | |
2780 | |
2781 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n", | |
2782 osGetCurrentProcessId(), pFile, pFile->h, flags, | |
2783 pFile->locktype)); | |
2784 | |
2785 #ifndef SQLITE_TEST | |
2786 UNUSED_PARAMETER(flags); | |
2787 #else | |
2788 if( (flags&0x0F)==SQLITE_SYNC_FULL ){ | |
2789 sqlite3_fullsync_count++; | |
2790 } | |
2791 sqlite3_sync_count++; | |
2792 #endif | |
2793 | |
2794 /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a | |
2795 ** no-op | |
2796 */ | |
2797 #ifdef SQLITE_NO_SYNC | |
2798 OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2799 osGetCurrentProcessId(), pFile, pFile->h)); | |
2800 return SQLITE_OK; | |
2801 #else | |
2802 #if SQLITE_MAX_MMAP_SIZE>0 | |
2803 if( pFile->pMapRegion ){ | |
2804 if( osFlushViewOfFile(pFile->pMapRegion, 0) ){ | |
2805 OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " | |
2806 "rc=SQLITE_OK\n", osGetCurrentProcessId(), | |
2807 pFile, pFile->pMapRegion)); | |
2808 }else{ | |
2809 pFile->lastErrno = osGetLastError(); | |
2810 OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, " | |
2811 "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), | |
2812 pFile, pFile->pMapRegion)); | |
2813 return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, | |
2814 "winSync1", pFile->zPath); | |
2815 } | |
2816 } | |
2817 #endif | |
2818 rc = osFlushFileBuffers(pFile->h); | |
2819 SimulateIOError( rc=FALSE ); | |
2820 if( rc ){ | |
2821 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n", | |
2822 osGetCurrentProcessId(), pFile, pFile->h)); | |
2823 return SQLITE_OK; | |
2824 }else{ | |
2825 pFile->lastErrno = osGetLastError(); | |
2826 OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n", | |
2827 osGetCurrentProcessId(), pFile, pFile->h)); | |
2828 return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno, | |
2829 "winSync2", pFile->zPath); | |
2830 } | |
2831 #endif | |
2832 } | |
2833 | |
2834 /* | |
2835 ** Determine the current size of a file in bytes | |
2836 */ | |
2837 static int winFileSize(sqlite3_file *id, sqlite3_int64 *pSize){ | |
2838 winFile *pFile = (winFile*)id; | |
2839 int rc = SQLITE_OK; | |
2840 | |
2841 assert( id!=0 ); | |
2842 assert( pSize!=0 ); | |
2843 SimulateIOError(return SQLITE_IOERR_FSTAT); | |
2844 OSTRACE(("SIZE file=%p, pSize=%p\n", pFile->h, pSize)); | |
2845 | |
2846 #if SQLITE_OS_WINRT | |
2847 { | |
2848 FILE_STANDARD_INFO info; | |
2849 if( osGetFileInformationByHandleEx(pFile->h, FileStandardInfo, | |
2850 &info, sizeof(info)) ){ | |
2851 *pSize = info.EndOfFile.QuadPart; | |
2852 }else{ | |
2853 pFile->lastErrno = osGetLastError(); | |
2854 rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, | |
2855 "winFileSize", pFile->zPath); | |
2856 } | |
2857 } | |
2858 #else | |
2859 { | |
2860 DWORD upperBits; | |
2861 DWORD lowerBits; | |
2862 DWORD lastErrno; | |
2863 | |
2864 lowerBits = osGetFileSize(pFile->h, &upperBits); | |
2865 *pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits; | |
2866 if( (lowerBits == INVALID_FILE_SIZE) | |
2867 && ((lastErrno = osGetLastError())!=NO_ERROR) ){ | |
2868 pFile->lastErrno = lastErrno; | |
2869 rc = winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno, | |
2870 "winFileSize", pFile->zPath); | |
2871 } | |
2872 } | |
2873 #endif | |
2874 OSTRACE(("SIZE file=%p, pSize=%p, *pSize=%lld, rc=%s\n", | |
2875 pFile->h, pSize, *pSize, sqlite3ErrName(rc))); | |
2876 return rc; | |
2877 } | |
2878 | |
2879 /* | |
2880 ** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems. | |
2881 */ | |
2882 #ifndef LOCKFILE_FAIL_IMMEDIATELY | |
2883 # define LOCKFILE_FAIL_IMMEDIATELY 1 | |
2884 #endif | |
2885 | |
2886 #ifndef LOCKFILE_EXCLUSIVE_LOCK | |
2887 # define LOCKFILE_EXCLUSIVE_LOCK 2 | |
2888 #endif | |
2889 | |
2890 /* | |
2891 ** Historically, SQLite has used both the LockFile and LockFileEx functions. | |
2892 ** When the LockFile function was used, it was always expected to fail | |
2893 ** immediately if the lock could not be obtained. Also, it always expected to | |
2894 ** obtain an exclusive lock. These flags are used with the LockFileEx function | |
2895 ** and reflect those expectations; therefore, they should not be changed. | |
2896 */ | |
2897 #ifndef SQLITE_LOCKFILE_FLAGS | |
2898 # define SQLITE_LOCKFILE_FLAGS (LOCKFILE_FAIL_IMMEDIATELY | \ | |
2899 LOCKFILE_EXCLUSIVE_LOCK) | |
2900 #endif | |
2901 | |
2902 /* | |
2903 ** Currently, SQLite never calls the LockFileEx function without wanting the | |
2904 ** call to fail immediately if the lock cannot be obtained. | |
2905 */ | |
2906 #ifndef SQLITE_LOCKFILEEX_FLAGS | |
2907 # define SQLITE_LOCKFILEEX_FLAGS (LOCKFILE_FAIL_IMMEDIATELY) | |
2908 #endif | |
2909 | |
2910 /* | |
2911 ** Acquire a reader lock. | |
2912 ** Different API routines are called depending on whether or not this | |
2913 ** is Win9x or WinNT. | |
2914 */ | |
2915 static int winGetReadLock(winFile *pFile){ | |
2916 int res; | |
2917 OSTRACE(("READ-LOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); | |
2918 if( osIsNT() ){ | |
2919 #if SQLITE_OS_WINCE | |
2920 /* | |
2921 ** NOTE: Windows CE is handled differently here due its lack of the Win32 | |
2922 ** API LockFileEx. | |
2923 */ | |
2924 res = winceLockFile(&pFile->h, SHARED_FIRST, 0, 1, 0); | |
2925 #else | |
2926 res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS, SHARED_FIRST, 0, | |
2927 SHARED_SIZE, 0); | |
2928 #endif | |
2929 } | |
2930 #ifdef SQLITE_WIN32_HAS_ANSI | |
2931 else{ | |
2932 int lk; | |
2933 sqlite3_randomness(sizeof(lk), &lk); | |
2934 pFile->sharedLockByte = (short)((lk & 0x7fffffff)%(SHARED_SIZE - 1)); | |
2935 res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, | |
2936 SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); | |
2937 } | |
2938 #endif | |
2939 if( res == 0 ){ | |
2940 pFile->lastErrno = osGetLastError(); | |
2941 /* No need to log a failure to lock */ | |
2942 } | |
2943 OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res)); | |
2944 return res; | |
2945 } | |
2946 | |
2947 /* | |
2948 ** Undo a readlock | |
2949 */ | |
2950 static int winUnlockReadLock(winFile *pFile){ | |
2951 int res; | |
2952 DWORD lastErrno; | |
2953 OSTRACE(("READ-UNLOCK file=%p, lock=%d\n", pFile->h, pFile->locktype)); | |
2954 if( osIsNT() ){ | |
2955 res = winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); | |
2956 } | |
2957 #ifdef SQLITE_WIN32_HAS_ANSI | |
2958 else{ | |
2959 res = winUnlockFile(&pFile->h, SHARED_FIRST+pFile->sharedLockByte, 0, 1, 0); | |
2960 } | |
2961 #endif | |
2962 if( res==0 && ((lastErrno = osGetLastError())!=ERROR_NOT_LOCKED) ){ | |
2963 pFile->lastErrno = lastErrno; | |
2964 winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno, | |
2965 "winUnlockReadLock", pFile->zPath); | |
2966 } | |
2967 OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res)); | |
2968 return res; | |
2969 } | |
2970 | |
2971 /* | |
2972 ** Lock the file with the lock specified by parameter locktype - one | |
2973 ** of the following: | |
2974 ** | |
2975 ** (1) SHARED_LOCK | |
2976 ** (2) RESERVED_LOCK | |
2977 ** (3) PENDING_LOCK | |
2978 ** (4) EXCLUSIVE_LOCK | |
2979 ** | |
2980 ** Sometimes when requesting one lock state, additional lock states | |
2981 ** are inserted in between. The locking might fail on one of the later | |
2982 ** transitions leaving the lock state different from what it started but | |
2983 ** still short of its goal. The following chart shows the allowed | |
2984 ** transitions and the inserted intermediate states: | |
2985 ** | |
2986 ** UNLOCKED -> SHARED | |
2987 ** SHARED -> RESERVED | |
2988 ** SHARED -> (PENDING) -> EXCLUSIVE | |
2989 ** RESERVED -> (PENDING) -> EXCLUSIVE | |
2990 ** PENDING -> EXCLUSIVE | |
2991 ** | |
2992 ** This routine will only increase a lock. The winUnlock() routine | |
2993 ** erases all locks at once and returns us immediately to locking level 0. | |
2994 ** It is not possible to lower the locking level one step at a time. You | |
2995 ** must go straight to locking level 0. | |
2996 */ | |
2997 static int winLock(sqlite3_file *id, int locktype){ | |
2998 int rc = SQLITE_OK; /* Return code from subroutines */ | |
2999 int res = 1; /* Result of a Windows lock call */ | |
3000 int newLocktype; /* Set pFile->locktype to this value before exiting */ | |
3001 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */ | |
3002 winFile *pFile = (winFile*)id; | |
3003 DWORD lastErrno = NO_ERROR; | |
3004 | |
3005 assert( id!=0 ); | |
3006 OSTRACE(("LOCK file=%p, oldLock=%d(%d), newLock=%d\n", | |
3007 pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); | |
3008 | |
3009 /* If there is already a lock of this type or more restrictive on the | |
3010 ** OsFile, do nothing. Don't use the end_lock: exit path, as | |
3011 ** sqlite3OsEnterMutex() hasn't been called yet. | |
3012 */ | |
3013 if( pFile->locktype>=locktype ){ | |
3014 OSTRACE(("LOCK-HELD file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3015 return SQLITE_OK; | |
3016 } | |
3017 | |
3018 /* Do not allow any kind of write-lock on a read-only database | |
3019 */ | |
3020 if( (pFile->ctrlFlags & WINFILE_RDONLY)!=0 && locktype>=RESERVED_LOCK ){ | |
3021 return SQLITE_IOERR_LOCK; | |
3022 } | |
3023 | |
3024 /* Make sure the locking sequence is correct | |
3025 */ | |
3026 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK ); | |
3027 assert( locktype!=PENDING_LOCK ); | |
3028 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK ); | |
3029 | |
3030 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or | |
3031 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of | |
3032 ** the PENDING_LOCK byte is temporary. | |
3033 */ | |
3034 newLocktype = pFile->locktype; | |
3035 if( (pFile->locktype==NO_LOCK) | |
3036 || ( (locktype==EXCLUSIVE_LOCK) | |
3037 && (pFile->locktype==RESERVED_LOCK)) | |
3038 ){ | |
3039 int cnt = 3; | |
3040 while( cnt-->0 && (res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, | |
3041 PENDING_BYTE, 0, 1, 0))==0 ){ | |
3042 /* Try 3 times to get the pending lock. This is needed to work | |
3043 ** around problems caused by indexing and/or anti-virus software on | |
3044 ** Windows systems. | |
3045 ** If you are using this code as a model for alternative VFSes, do not | |
3046 ** copy this retry logic. It is a hack intended for Windows only. | |
3047 */ | |
3048 lastErrno = osGetLastError(); | |
3049 OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n", | |
3050 pFile->h, cnt, res)); | |
3051 if( lastErrno==ERROR_INVALID_HANDLE ){ | |
3052 pFile->lastErrno = lastErrno; | |
3053 rc = SQLITE_IOERR_LOCK; | |
3054 OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n", | |
3055 pFile->h, cnt, sqlite3ErrName(rc))); | |
3056 return rc; | |
3057 } | |
3058 if( cnt ) sqlite3_win32_sleep(1); | |
3059 } | |
3060 gotPendingLock = res; | |
3061 if( !res ){ | |
3062 lastErrno = osGetLastError(); | |
3063 } | |
3064 } | |
3065 | |
3066 /* Acquire a shared lock | |
3067 */ | |
3068 if( locktype==SHARED_LOCK && res ){ | |
3069 assert( pFile->locktype==NO_LOCK ); | |
3070 res = winGetReadLock(pFile); | |
3071 if( res ){ | |
3072 newLocktype = SHARED_LOCK; | |
3073 }else{ | |
3074 lastErrno = osGetLastError(); | |
3075 } | |
3076 } | |
3077 | |
3078 /* Acquire a RESERVED lock | |
3079 */ | |
3080 if( locktype==RESERVED_LOCK && res ){ | |
3081 assert( pFile->locktype==SHARED_LOCK ); | |
3082 res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, RESERVED_BYTE, 0, 1, 0); | |
3083 if( res ){ | |
3084 newLocktype = RESERVED_LOCK; | |
3085 }else{ | |
3086 lastErrno = osGetLastError(); | |
3087 } | |
3088 } | |
3089 | |
3090 /* Acquire a PENDING lock | |
3091 */ | |
3092 if( locktype==EXCLUSIVE_LOCK && res ){ | |
3093 newLocktype = PENDING_LOCK; | |
3094 gotPendingLock = 0; | |
3095 } | |
3096 | |
3097 /* Acquire an EXCLUSIVE lock | |
3098 */ | |
3099 if( locktype==EXCLUSIVE_LOCK && res ){ | |
3100 assert( pFile->locktype>=SHARED_LOCK ); | |
3101 res = winUnlockReadLock(pFile); | |
3102 res = winLockFile(&pFile->h, SQLITE_LOCKFILE_FLAGS, SHARED_FIRST, 0, | |
3103 SHARED_SIZE, 0); | |
3104 if( res ){ | |
3105 newLocktype = EXCLUSIVE_LOCK; | |
3106 }else{ | |
3107 lastErrno = osGetLastError(); | |
3108 winGetReadLock(pFile); | |
3109 } | |
3110 } | |
3111 | |
3112 /* If we are holding a PENDING lock that ought to be released, then | |
3113 ** release it now. | |
3114 */ | |
3115 if( gotPendingLock && locktype==SHARED_LOCK ){ | |
3116 winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); | |
3117 } | |
3118 | |
3119 /* Update the state of the lock has held in the file descriptor then | |
3120 ** return the appropriate result code. | |
3121 */ | |
3122 if( res ){ | |
3123 rc = SQLITE_OK; | |
3124 }else{ | |
3125 pFile->lastErrno = lastErrno; | |
3126 rc = SQLITE_BUSY; | |
3127 OSTRACE(("LOCK-FAIL file=%p, wanted=%d, got=%d\n", | |
3128 pFile->h, locktype, newLocktype)); | |
3129 } | |
3130 pFile->locktype = (u8)newLocktype; | |
3131 OSTRACE(("LOCK file=%p, lock=%d, rc=%s\n", | |
3132 pFile->h, pFile->locktype, sqlite3ErrName(rc))); | |
3133 return rc; | |
3134 } | |
3135 | |
3136 /* | |
3137 ** This routine checks if there is a RESERVED lock held on the specified | |
3138 ** file by this or any other process. If such a lock is held, return | |
3139 ** non-zero, otherwise zero. | |
3140 */ | |
3141 static int winCheckReservedLock(sqlite3_file *id, int *pResOut){ | |
3142 int res; | |
3143 winFile *pFile = (winFile*)id; | |
3144 | |
3145 SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; ); | |
3146 OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p\n", pFile->h, pResOut)); | |
3147 | |
3148 assert( id!=0 ); | |
3149 if( pFile->locktype>=RESERVED_LOCK ){ | |
3150 res = 1; | |
3151 OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res)); | |
3152 }else{ | |
3153 res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE,0,1,0); | |
3154 if( res ){ | |
3155 winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); | |
3156 } | |
3157 res = !res; | |
3158 OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res)); | |
3159 } | |
3160 *pResOut = res; | |
3161 OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", | |
3162 pFile->h, pResOut, *pResOut)); | |
3163 return SQLITE_OK; | |
3164 } | |
3165 | |
3166 /* | |
3167 ** Lower the locking level on file descriptor id to locktype. locktype | |
3168 ** must be either NO_LOCK or SHARED_LOCK. | |
3169 ** | |
3170 ** If the locking level of the file descriptor is already at or below | |
3171 ** the requested locking level, this routine is a no-op. | |
3172 ** | |
3173 ** It is not possible for this routine to fail if the second argument | |
3174 ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine | |
3175 ** might return SQLITE_IOERR; | |
3176 */ | |
3177 static int winUnlock(sqlite3_file *id, int locktype){ | |
3178 int type; | |
3179 winFile *pFile = (winFile*)id; | |
3180 int rc = SQLITE_OK; | |
3181 assert( pFile!=0 ); | |
3182 assert( locktype<=SHARED_LOCK ); | |
3183 OSTRACE(("UNLOCK file=%p, oldLock=%d(%d), newLock=%d\n", | |
3184 pFile->h, pFile->locktype, pFile->sharedLockByte, locktype)); | |
3185 type = pFile->locktype; | |
3186 if( type>=EXCLUSIVE_LOCK ){ | |
3187 winUnlockFile(&pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0); | |
3188 if( locktype==SHARED_LOCK && !winGetReadLock(pFile) ){ | |
3189 /* This should never happen. We should always be able to | |
3190 ** reacquire the read lock */ | |
3191 rc = winLogError(SQLITE_IOERR_UNLOCK, osGetLastError(), | |
3192 "winUnlock", pFile->zPath); | |
3193 } | |
3194 } | |
3195 if( type>=RESERVED_LOCK ){ | |
3196 winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0); | |
3197 } | |
3198 if( locktype==NO_LOCK && type>=SHARED_LOCK ){ | |
3199 winUnlockReadLock(pFile); | |
3200 } | |
3201 if( type>=PENDING_LOCK ){ | |
3202 winUnlockFile(&pFile->h, PENDING_BYTE, 0, 1, 0); | |
3203 } | |
3204 pFile->locktype = (u8)locktype; | |
3205 OSTRACE(("UNLOCK file=%p, lock=%d, rc=%s\n", | |
3206 pFile->h, pFile->locktype, sqlite3ErrName(rc))); | |
3207 return rc; | |
3208 } | |
3209 | |
3210 /* | |
3211 ** If *pArg is initially negative then this is a query. Set *pArg to | |
3212 ** 1 or 0 depending on whether or not bit mask of pFile->ctrlFlags is set. | |
3213 ** | |
3214 ** If *pArg is 0 or 1, then clear or set the mask bit of pFile->ctrlFlags. | |
3215 */ | |
3216 static void winModeBit(winFile *pFile, unsigned char mask, int *pArg){ | |
3217 if( *pArg<0 ){ | |
3218 *pArg = (pFile->ctrlFlags & mask)!=0; | |
3219 }else if( (*pArg)==0 ){ | |
3220 pFile->ctrlFlags &= ~mask; | |
3221 }else{ | |
3222 pFile->ctrlFlags |= mask; | |
3223 } | |
3224 } | |
3225 | |
3226 /* Forward references to VFS helper methods used for temporary files */ | |
3227 static int winGetTempname(sqlite3_vfs *, char **); | |
3228 static int winIsDir(const void *); | |
3229 static BOOL winIsDriveLetterAndColon(const char *); | |
3230 | |
3231 /* | |
3232 ** Control and query of the open file handle. | |
3233 */ | |
3234 static int winFileControl(sqlite3_file *id, int op, void *pArg){ | |
3235 winFile *pFile = (winFile*)id; | |
3236 OSTRACE(("FCNTL file=%p, op=%d, pArg=%p\n", pFile->h, op, pArg)); | |
3237 switch( op ){ | |
3238 case SQLITE_FCNTL_LOCKSTATE: { | |
3239 *(int*)pArg = pFile->locktype; | |
3240 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3241 return SQLITE_OK; | |
3242 } | |
3243 case SQLITE_LAST_ERRNO: { | |
3244 *(int*)pArg = (int)pFile->lastErrno; | |
3245 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3246 return SQLITE_OK; | |
3247 } | |
3248 case SQLITE_FCNTL_CHUNK_SIZE: { | |
3249 pFile->szChunk = *(int *)pArg; | |
3250 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3251 return SQLITE_OK; | |
3252 } | |
3253 case SQLITE_FCNTL_SIZE_HINT: { | |
3254 if( pFile->szChunk>0 ){ | |
3255 sqlite3_int64 oldSz; | |
3256 int rc = winFileSize(id, &oldSz); | |
3257 if( rc==SQLITE_OK ){ | |
3258 sqlite3_int64 newSz = *(sqlite3_int64*)pArg; | |
3259 if( newSz>oldSz ){ | |
3260 SimulateIOErrorBenign(1); | |
3261 rc = winTruncate(id, newSz); | |
3262 SimulateIOErrorBenign(0); | |
3263 } | |
3264 } | |
3265 OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); | |
3266 return rc; | |
3267 } | |
3268 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3269 return SQLITE_OK; | |
3270 } | |
3271 case SQLITE_FCNTL_PERSIST_WAL: { | |
3272 winModeBit(pFile, WINFILE_PERSIST_WAL, (int*)pArg); | |
3273 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3274 return SQLITE_OK; | |
3275 } | |
3276 case SQLITE_FCNTL_POWERSAFE_OVERWRITE: { | |
3277 winModeBit(pFile, WINFILE_PSOW, (int*)pArg); | |
3278 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3279 return SQLITE_OK; | |
3280 } | |
3281 case SQLITE_FCNTL_VFSNAME: { | |
3282 *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); | |
3283 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3284 return SQLITE_OK; | |
3285 } | |
3286 case SQLITE_FCNTL_WIN32_AV_RETRY: { | |
3287 int *a = (int*)pArg; | |
3288 if( a[0]>0 ){ | |
3289 winIoerrRetry = a[0]; | |
3290 }else{ | |
3291 a[0] = winIoerrRetry; | |
3292 } | |
3293 if( a[1]>0 ){ | |
3294 winIoerrRetryDelay = a[1]; | |
3295 }else{ | |
3296 a[1] = winIoerrRetryDelay; | |
3297 } | |
3298 OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h)); | |
3299 return SQLITE_OK; | |
3300 } | |
3301 #ifdef SQLITE_TEST | |
3302 case SQLITE_FCNTL_WIN32_SET_HANDLE: { | |
3303 LPHANDLE phFile = (LPHANDLE)pArg; | |
3304 HANDLE hOldFile = pFile->h; | |
3305 pFile->h = *phFile; | |
3306 *phFile = hOldFile; | |
3307 OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n", | |
3308 hOldFile, pFile->h)); | |
3309 return SQLITE_OK; | |
3310 } | |
3311 #endif | |
3312 case SQLITE_FCNTL_TEMPFILENAME: { | |
3313 char *zTFile = 0; | |
3314 int rc = winGetTempname(pFile->pVfs, &zTFile); | |
3315 if( rc==SQLITE_OK ){ | |
3316 *(char**)pArg = zTFile; | |
3317 } | |
3318 OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); | |
3319 return rc; | |
3320 } | |
3321 #if SQLITE_MAX_MMAP_SIZE>0 | |
3322 case SQLITE_FCNTL_MMAP_SIZE: { | |
3323 i64 newLimit = *(i64*)pArg; | |
3324 int rc = SQLITE_OK; | |
3325 if( newLimit>sqlite3GlobalConfig.mxMmap ){ | |
3326 newLimit = sqlite3GlobalConfig.mxMmap; | |
3327 } | |
3328 *(i64*)pArg = pFile->mmapSizeMax; | |
3329 if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){ | |
3330 pFile->mmapSizeMax = newLimit; | |
3331 if( pFile->mmapSize>0 ){ | |
3332 winUnmapfile(pFile); | |
3333 rc = winMapfile(pFile, -1); | |
3334 } | |
3335 } | |
3336 OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc))); | |
3337 return rc; | |
3338 } | |
3339 #endif | |
3340 } | |
3341 OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h)); | |
3342 return SQLITE_NOTFOUND; | |
3343 } | |
3344 | |
3345 /* | |
3346 ** Return the sector size in bytes of the underlying block device for | |
3347 ** the specified file. This is almost always 512 bytes, but may be | |
3348 ** larger for some devices. | |
3349 ** | |
3350 ** SQLite code assumes this function cannot fail. It also assumes that | |
3351 ** if two files are created in the same file-system directory (i.e. | |
3352 ** a database and its journal file) that the sector size will be the | |
3353 ** same for both. | |
3354 */ | |
3355 static int winSectorSize(sqlite3_file *id){ | |
3356 (void)id; | |
3357 return SQLITE_DEFAULT_SECTOR_SIZE; | |
3358 } | |
3359 | |
3360 /* | |
3361 ** Return a vector of device characteristics. | |
3362 */ | |
3363 static int winDeviceCharacteristics(sqlite3_file *id){ | |
3364 winFile *p = (winFile*)id; | |
3365 return SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN | | |
3366 ((p->ctrlFlags & WINFILE_PSOW)?SQLITE_IOCAP_POWERSAFE_OVERWRITE:0); | |
3367 } | |
3368 | |
3369 /* | |
3370 ** Windows will only let you create file view mappings | |
3371 ** on allocation size granularity boundaries. | |
3372 ** During sqlite3_os_init() we do a GetSystemInfo() | |
3373 ** to get the granularity size. | |
3374 */ | |
3375 static SYSTEM_INFO winSysInfo; | |
3376 | |
3377 #ifndef SQLITE_OMIT_WAL | |
3378 | |
3379 /* | |
3380 ** Helper functions to obtain and relinquish the global mutex. The | |
3381 ** global mutex is used to protect the winLockInfo objects used by | |
3382 ** this file, all of which may be shared by multiple threads. | |
3383 ** | |
3384 ** Function winShmMutexHeld() is used to assert() that the global mutex | |
3385 ** is held when required. This function is only used as part of assert() | |
3386 ** statements. e.g. | |
3387 ** | |
3388 ** winShmEnterMutex() | |
3389 ** assert( winShmMutexHeld() ); | |
3390 ** winShmLeaveMutex() | |
3391 */ | |
3392 static void winShmEnterMutex(void){ | |
3393 sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); | |
3394 } | |
3395 static void winShmLeaveMutex(void){ | |
3396 sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); | |
3397 } | |
3398 #ifndef NDEBUG | |
3399 static int winShmMutexHeld(void) { | |
3400 return sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_VFS1)); | |
3401 } | |
3402 #endif | |
3403 | |
3404 /* | |
3405 ** Object used to represent a single file opened and mmapped to provide | |
3406 ** shared memory. When multiple threads all reference the same | |
3407 ** log-summary, each thread has its own winFile object, but they all | |
3408 ** point to a single instance of this object. In other words, each | |
3409 ** log-summary is opened only once per process. | |
3410 ** | |
3411 ** winShmMutexHeld() must be true when creating or destroying | |
3412 ** this object or while reading or writing the following fields: | |
3413 ** | |
3414 ** nRef | |
3415 ** pNext | |
3416 ** | |
3417 ** The following fields are read-only after the object is created: | |
3418 ** | |
3419 ** fid | |
3420 ** zFilename | |
3421 ** | |
3422 ** Either winShmNode.mutex must be held or winShmNode.nRef==0 and | |
3423 ** winShmMutexHeld() is true when reading or writing any other field | |
3424 ** in this structure. | |
3425 ** | |
3426 */ | |
3427 struct winShmNode { | |
3428 sqlite3_mutex *mutex; /* Mutex to access this object */ | |
3429 char *zFilename; /* Name of the file */ | |
3430 winFile hFile; /* File handle from winOpen */ | |
3431 | |
3432 int szRegion; /* Size of shared-memory regions */ | |
3433 int nRegion; /* Size of array apRegion */ | |
3434 struct ShmRegion { | |
3435 HANDLE hMap; /* File handle from CreateFileMapping */ | |
3436 void *pMap; | |
3437 } *aRegion; | |
3438 DWORD lastErrno; /* The Windows errno from the last I/O error */ | |
3439 | |
3440 int nRef; /* Number of winShm objects pointing to this */ | |
3441 winShm *pFirst; /* All winShm objects pointing to this */ | |
3442 winShmNode *pNext; /* Next in list of all winShmNode objects */ | |
3443 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) | |
3444 u8 nextShmId; /* Next available winShm.id value */ | |
3445 #endif | |
3446 }; | |
3447 | |
3448 /* | |
3449 ** A global array of all winShmNode objects. | |
3450 ** | |
3451 ** The winShmMutexHeld() must be true while reading or writing this list. | |
3452 */ | |
3453 static winShmNode *winShmNodeList = 0; | |
3454 | |
3455 /* | |
3456 ** Structure used internally by this VFS to record the state of an | |
3457 ** open shared memory connection. | |
3458 ** | |
3459 ** The following fields are initialized when this object is created and | |
3460 ** are read-only thereafter: | |
3461 ** | |
3462 ** winShm.pShmNode | |
3463 ** winShm.id | |
3464 ** | |
3465 ** All other fields are read/write. The winShm.pShmNode->mutex must be held | |
3466 ** while accessing any read/write fields. | |
3467 */ | |
3468 struct winShm { | |
3469 winShmNode *pShmNode; /* The underlying winShmNode object */ | |
3470 winShm *pNext; /* Next winShm with the same winShmNode */ | |
3471 u8 hasMutex; /* True if holding the winShmNode mutex */ | |
3472 u16 sharedMask; /* Mask of shared locks held */ | |
3473 u16 exclMask; /* Mask of exclusive locks held */ | |
3474 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) | |
3475 u8 id; /* Id of this connection with its winShmNode */ | |
3476 #endif | |
3477 }; | |
3478 | |
3479 /* | |
3480 ** Constants used for locking | |
3481 */ | |
3482 #define WIN_SHM_BASE ((22+SQLITE_SHM_NLOCK)*4) /* first lock byte */ | |
3483 #define WIN_SHM_DMS (WIN_SHM_BASE+SQLITE_SHM_NLOCK) /* deadman switch */ | |
3484 | |
3485 /* | |
3486 ** Apply advisory locks for all n bytes beginning at ofst. | |
3487 */ | |
3488 #define _SHM_UNLCK 1 | |
3489 #define _SHM_RDLCK 2 | |
3490 #define _SHM_WRLCK 3 | |
3491 static int winShmSystemLock( | |
3492 winShmNode *pFile, /* Apply locks to this open shared-memory segment */ | |
3493 int lockType, /* _SHM_UNLCK, _SHM_RDLCK, or _SHM_WRLCK */ | |
3494 int ofst, /* Offset to first byte to be locked/unlocked */ | |
3495 int nByte /* Number of bytes to lock or unlock */ | |
3496 ){ | |
3497 int rc = 0; /* Result code form Lock/UnlockFileEx() */ | |
3498 | |
3499 /* Access to the winShmNode object is serialized by the caller */ | |
3500 assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 ); | |
3501 | |
3502 OSTRACE(("SHM-LOCK file=%p, lock=%d, offset=%d, size=%d\n", | |
3503 pFile->hFile.h, lockType, ofst, nByte)); | |
3504 | |
3505 /* Release/Acquire the system-level lock */ | |
3506 if( lockType==_SHM_UNLCK ){ | |
3507 rc = winUnlockFile(&pFile->hFile.h, ofst, 0, nByte, 0); | |
3508 }else{ | |
3509 /* Initialize the locking parameters */ | |
3510 DWORD dwFlags = LOCKFILE_FAIL_IMMEDIATELY; | |
3511 if( lockType == _SHM_WRLCK ) dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; | |
3512 rc = winLockFile(&pFile->hFile.h, dwFlags, ofst, 0, nByte, 0); | |
3513 } | |
3514 | |
3515 if( rc!= 0 ){ | |
3516 rc = SQLITE_OK; | |
3517 }else{ | |
3518 pFile->lastErrno = osGetLastError(); | |
3519 rc = SQLITE_BUSY; | |
3520 } | |
3521 | |
3522 OSTRACE(("SHM-LOCK file=%p, func=%s, errno=%lu, rc=%s\n", | |
3523 pFile->hFile.h, (lockType == _SHM_UNLCK) ? "winUnlockFile" : | |
3524 "winLockFile", pFile->lastErrno, sqlite3ErrName(rc))); | |
3525 | |
3526 return rc; | |
3527 } | |
3528 | |
3529 /* Forward references to VFS methods */ | |
3530 static int winOpen(sqlite3_vfs*,const char*,sqlite3_file*,int,int*); | |
3531 static int winDelete(sqlite3_vfs *,const char*,int); | |
3532 | |
3533 /* | |
3534 ** Purge the winShmNodeList list of all entries with winShmNode.nRef==0. | |
3535 ** | |
3536 ** This is not a VFS shared-memory method; it is a utility function called | |
3537 ** by VFS shared-memory methods. | |
3538 */ | |
3539 static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){ | |
3540 winShmNode **pp; | |
3541 winShmNode *p; | |
3542 assert( winShmMutexHeld() ); | |
3543 OSTRACE(("SHM-PURGE pid=%lu, deleteFlag=%d\n", | |
3544 osGetCurrentProcessId(), deleteFlag)); | |
3545 pp = &winShmNodeList; | |
3546 while( (p = *pp)!=0 ){ | |
3547 if( p->nRef==0 ){ | |
3548 int i; | |
3549 if( p->mutex ){ sqlite3_mutex_free(p->mutex); } | |
3550 for(i=0; i<p->nRegion; i++){ | |
3551 BOOL bRc = osUnmapViewOfFile(p->aRegion[i].pMap); | |
3552 OSTRACE(("SHM-PURGE-UNMAP pid=%lu, region=%d, rc=%s\n", | |
3553 osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); | |
3554 UNUSED_VARIABLE_VALUE(bRc); | |
3555 bRc = osCloseHandle(p->aRegion[i].hMap); | |
3556 OSTRACE(("SHM-PURGE-CLOSE pid=%lu, region=%d, rc=%s\n", | |
3557 osGetCurrentProcessId(), i, bRc ? "ok" : "failed")); | |
3558 UNUSED_VARIABLE_VALUE(bRc); | |
3559 } | |
3560 if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){ | |
3561 SimulateIOErrorBenign(1); | |
3562 winClose((sqlite3_file *)&p->hFile); | |
3563 SimulateIOErrorBenign(0); | |
3564 } | |
3565 if( deleteFlag ){ | |
3566 SimulateIOErrorBenign(1); | |
3567 sqlite3BeginBenignMalloc(); | |
3568 winDelete(pVfs, p->zFilename, 0); | |
3569 sqlite3EndBenignMalloc(); | |
3570 SimulateIOErrorBenign(0); | |
3571 } | |
3572 *pp = p->pNext; | |
3573 sqlite3_free(p->aRegion); | |
3574 sqlite3_free(p); | |
3575 }else{ | |
3576 pp = &p->pNext; | |
3577 } | |
3578 } | |
3579 } | |
3580 | |
3581 /* | |
3582 ** Open the shared-memory area associated with database file pDbFd. | |
3583 ** | |
3584 ** When opening a new shared-memory file, if no other instances of that | |
3585 ** file are currently open, in this process or in other processes, then | |
3586 ** the file must be truncated to zero length or have its header cleared. | |
3587 */ | |
3588 static int winOpenSharedMemory(winFile *pDbFd){ | |
3589 struct winShm *p; /* The connection to be opened */ | |
3590 struct winShmNode *pShmNode = 0; /* The underlying mmapped file */ | |
3591 int rc; /* Result code */ | |
3592 struct winShmNode *pNew; /* Newly allocated winShmNode */ | |
3593 int nName; /* Size of zName in bytes */ | |
3594 | |
3595 assert( pDbFd->pShm==0 ); /* Not previously opened */ | |
3596 | |
3597 /* Allocate space for the new sqlite3_shm object. Also speculatively | |
3598 ** allocate space for a new winShmNode and filename. | |
3599 */ | |
3600 p = sqlite3MallocZero( sizeof(*p) ); | |
3601 if( p==0 ) return SQLITE_IOERR_NOMEM; | |
3602 nName = sqlite3Strlen30(pDbFd->zPath); | |
3603 pNew = sqlite3MallocZero( sizeof(*pShmNode) + nName + 17 ); | |
3604 if( pNew==0 ){ | |
3605 sqlite3_free(p); | |
3606 return SQLITE_IOERR_NOMEM; | |
3607 } | |
3608 pNew->zFilename = (char*)&pNew[1]; | |
3609 sqlite3_snprintf(nName+15, pNew->zFilename, "%s-shm", pDbFd->zPath); | |
3610 sqlite3FileSuffix3(pDbFd->zPath, pNew->zFilename); | |
3611 | |
3612 /* Look to see if there is an existing winShmNode that can be used. | |
3613 ** If no matching winShmNode currently exists, create a new one. | |
3614 */ | |
3615 winShmEnterMutex(); | |
3616 for(pShmNode = winShmNodeList; pShmNode; pShmNode=pShmNode->pNext){ | |
3617 /* TBD need to come up with better match here. Perhaps | |
3618 ** use FILE_ID_BOTH_DIR_INFO Structure. | |
3619 */ | |
3620 if( sqlite3StrICmp(pShmNode->zFilename, pNew->zFilename)==0 ) break; | |
3621 } | |
3622 if( pShmNode ){ | |
3623 sqlite3_free(pNew); | |
3624 }else{ | |
3625 pShmNode = pNew; | |
3626 pNew = 0; | |
3627 ((winFile*)(&pShmNode->hFile))->h = INVALID_HANDLE_VALUE; | |
3628 pShmNode->pNext = winShmNodeList; | |
3629 winShmNodeList = pShmNode; | |
3630 | |
3631 pShmNode->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST); | |
3632 if( pShmNode->mutex==0 ){ | |
3633 rc = SQLITE_IOERR_NOMEM; | |
3634 goto shm_open_err; | |
3635 } | |
3636 | |
3637 rc = winOpen(pDbFd->pVfs, | |
3638 pShmNode->zFilename, /* Name of the file (UTF-8) */ | |
3639 (sqlite3_file*)&pShmNode->hFile, /* File handle here */ | |
3640 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, | |
3641 0); | |
3642 if( SQLITE_OK!=rc ){ | |
3643 goto shm_open_err; | |
3644 } | |
3645 | |
3646 /* Check to see if another process is holding the dead-man switch. | |
3647 ** If not, truncate the file to zero length. | |
3648 */ | |
3649 if( winShmSystemLock(pShmNode, _SHM_WRLCK, WIN_SHM_DMS, 1)==SQLITE_OK ){ | |
3650 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, 0); | |
3651 if( rc!=SQLITE_OK ){ | |
3652 rc = winLogError(SQLITE_IOERR_SHMOPEN, osGetLastError(), | |
3653 "winOpenShm", pDbFd->zPath); | |
3654 } | |
3655 } | |
3656 if( rc==SQLITE_OK ){ | |
3657 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); | |
3658 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, WIN_SHM_DMS, 1); | |
3659 } | |
3660 if( rc ) goto shm_open_err; | |
3661 } | |
3662 | |
3663 /* Make the new connection a child of the winShmNode */ | |
3664 p->pShmNode = pShmNode; | |
3665 #if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE) | |
3666 p->id = pShmNode->nextShmId++; | |
3667 #endif | |
3668 pShmNode->nRef++; | |
3669 pDbFd->pShm = p; | |
3670 winShmLeaveMutex(); | |
3671 | |
3672 /* The reference count on pShmNode has already been incremented under | |
3673 ** the cover of the winShmEnterMutex() mutex and the pointer from the | |
3674 ** new (struct winShm) object to the pShmNode has been set. All that is | |
3675 ** left to do is to link the new object into the linked list starting | |
3676 ** at pShmNode->pFirst. This must be done while holding the pShmNode->mutex | |
3677 ** mutex. | |
3678 */ | |
3679 sqlite3_mutex_enter(pShmNode->mutex); | |
3680 p->pNext = pShmNode->pFirst; | |
3681 pShmNode->pFirst = p; | |
3682 sqlite3_mutex_leave(pShmNode->mutex); | |
3683 return SQLITE_OK; | |
3684 | |
3685 /* Jump here on any error */ | |
3686 shm_open_err: | |
3687 winShmSystemLock(pShmNode, _SHM_UNLCK, WIN_SHM_DMS, 1); | |
3688 winShmPurge(pDbFd->pVfs, 0); /* This call frees pShmNode if required */ | |
3689 sqlite3_free(p); | |
3690 sqlite3_free(pNew); | |
3691 winShmLeaveMutex(); | |
3692 return rc; | |
3693 } | |
3694 | |
3695 /* | |
3696 ** Close a connection to shared-memory. Delete the underlying | |
3697 ** storage if deleteFlag is true. | |
3698 */ | |
3699 static int winShmUnmap( | |
3700 sqlite3_file *fd, /* Database holding shared memory */ | |
3701 int deleteFlag /* Delete after closing if true */ | |
3702 ){ | |
3703 winFile *pDbFd; /* Database holding shared-memory */ | |
3704 winShm *p; /* The connection to be closed */ | |
3705 winShmNode *pShmNode; /* The underlying shared-memory file */ | |
3706 winShm **pp; /* For looping over sibling connections */ | |
3707 | |
3708 pDbFd = (winFile*)fd; | |
3709 p = pDbFd->pShm; | |
3710 if( p==0 ) return SQLITE_OK; | |
3711 pShmNode = p->pShmNode; | |
3712 | |
3713 /* Remove connection p from the set of connections associated | |
3714 ** with pShmNode */ | |
3715 sqlite3_mutex_enter(pShmNode->mutex); | |
3716 for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){} | |
3717 *pp = p->pNext; | |
3718 | |
3719 /* Free the connection p */ | |
3720 sqlite3_free(p); | |
3721 pDbFd->pShm = 0; | |
3722 sqlite3_mutex_leave(pShmNode->mutex); | |
3723 | |
3724 /* If pShmNode->nRef has reached 0, then close the underlying | |
3725 ** shared-memory file, too */ | |
3726 winShmEnterMutex(); | |
3727 assert( pShmNode->nRef>0 ); | |
3728 pShmNode->nRef--; | |
3729 if( pShmNode->nRef==0 ){ | |
3730 winShmPurge(pDbFd->pVfs, deleteFlag); | |
3731 } | |
3732 winShmLeaveMutex(); | |
3733 | |
3734 return SQLITE_OK; | |
3735 } | |
3736 | |
3737 /* | |
3738 ** Change the lock state for a shared-memory segment. | |
3739 */ | |
3740 static int winShmLock( | |
3741 sqlite3_file *fd, /* Database file holding the shared memory */ | |
3742 int ofst, /* First lock to acquire or release */ | |
3743 int n, /* Number of locks to acquire or release */ | |
3744 int flags /* What to do with the lock */ | |
3745 ){ | |
3746 winFile *pDbFd = (winFile*)fd; /* Connection holding shared memory */ | |
3747 winShm *p = pDbFd->pShm; /* The shared memory being locked */ | |
3748 winShm *pX; /* For looping over all siblings */ | |
3749 winShmNode *pShmNode = p->pShmNode; | |
3750 int rc = SQLITE_OK; /* Result code */ | |
3751 u16 mask; /* Mask of locks to take or release */ | |
3752 | |
3753 assert( ofst>=0 && ofst+n<=SQLITE_SHM_NLOCK ); | |
3754 assert( n>=1 ); | |
3755 assert( flags==(SQLITE_SHM_LOCK | SQLITE_SHM_SHARED) | |
3756 || flags==(SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE) | |
3757 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED) | |
3758 || flags==(SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE) ); | |
3759 assert( n==1 || (flags & SQLITE_SHM_EXCLUSIVE)!=0 ); | |
3760 | |
3761 mask = (u16)((1U<<(ofst+n)) - (1U<<ofst)); | |
3762 assert( n>1 || mask==(1<<ofst) ); | |
3763 sqlite3_mutex_enter(pShmNode->mutex); | |
3764 if( flags & SQLITE_SHM_UNLOCK ){ | |
3765 u16 allMask = 0; /* Mask of locks held by siblings */ | |
3766 | |
3767 /* See if any siblings hold this same lock */ | |
3768 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ | |
3769 if( pX==p ) continue; | |
3770 assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 ); | |
3771 allMask |= pX->sharedMask; | |
3772 } | |
3773 | |
3774 /* Unlock the system-level locks */ | |
3775 if( (mask & allMask)==0 ){ | |
3776 rc = winShmSystemLock(pShmNode, _SHM_UNLCK, ofst+WIN_SHM_BASE, n); | |
3777 }else{ | |
3778 rc = SQLITE_OK; | |
3779 } | |
3780 | |
3781 /* Undo the local locks */ | |
3782 if( rc==SQLITE_OK ){ | |
3783 p->exclMask &= ~mask; | |
3784 p->sharedMask &= ~mask; | |
3785 } | |
3786 }else if( flags & SQLITE_SHM_SHARED ){ | |
3787 u16 allShared = 0; /* Union of locks held by connections other than "p" */ | |
3788 | |
3789 /* Find out which shared locks are already held by sibling connections. | |
3790 ** If any sibling already holds an exclusive lock, go ahead and return | |
3791 ** SQLITE_BUSY. | |
3792 */ | |
3793 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ | |
3794 if( (pX->exclMask & mask)!=0 ){ | |
3795 rc = SQLITE_BUSY; | |
3796 break; | |
3797 } | |
3798 allShared |= pX->sharedMask; | |
3799 } | |
3800 | |
3801 /* Get shared locks at the system level, if necessary */ | |
3802 if( rc==SQLITE_OK ){ | |
3803 if( (allShared & mask)==0 ){ | |
3804 rc = winShmSystemLock(pShmNode, _SHM_RDLCK, ofst+WIN_SHM_BASE, n); | |
3805 }else{ | |
3806 rc = SQLITE_OK; | |
3807 } | |
3808 } | |
3809 | |
3810 /* Get the local shared locks */ | |
3811 if( rc==SQLITE_OK ){ | |
3812 p->sharedMask |= mask; | |
3813 } | |
3814 }else{ | |
3815 /* Make sure no sibling connections hold locks that will block this | |
3816 ** lock. If any do, return SQLITE_BUSY right away. | |
3817 */ | |
3818 for(pX=pShmNode->pFirst; pX; pX=pX->pNext){ | |
3819 if( (pX->exclMask & mask)!=0 || (pX->sharedMask & mask)!=0 ){ | |
3820 rc = SQLITE_BUSY; | |
3821 break; | |
3822 } | |
3823 } | |
3824 | |
3825 /* Get the exclusive locks at the system level. Then if successful | |
3826 ** also mark the local connection as being locked. | |
3827 */ | |
3828 if( rc==SQLITE_OK ){ | |
3829 rc = winShmSystemLock(pShmNode, _SHM_WRLCK, ofst+WIN_SHM_BASE, n); | |
3830 if( rc==SQLITE_OK ){ | |
3831 assert( (p->sharedMask & mask)==0 ); | |
3832 p->exclMask |= mask; | |
3833 } | |
3834 } | |
3835 } | |
3836 sqlite3_mutex_leave(pShmNode->mutex); | |
3837 OSTRACE(("SHM-LOCK pid=%lu, id=%d, sharedMask=%03x, exclMask=%03x, rc=%s\n", | |
3838 osGetCurrentProcessId(), p->id, p->sharedMask, p->exclMask, | |
3839 sqlite3ErrName(rc))); | |
3840 return rc; | |
3841 } | |
3842 | |
3843 /* | |
3844 ** Implement a memory barrier or memory fence on shared memory. | |
3845 ** | |
3846 ** All loads and stores begun before the barrier must complete before | |
3847 ** any load or store begun after the barrier. | |
3848 */ | |
3849 static void winShmBarrier( | |
3850 sqlite3_file *fd /* Database holding the shared memory */ | |
3851 ){ | |
3852 UNUSED_PARAMETER(fd); | |
3853 sqlite3MemoryBarrier(); /* compiler-defined memory barrier */ | |
3854 winShmEnterMutex(); /* Also mutex, for redundancy */ | |
3855 winShmLeaveMutex(); | |
3856 } | |
3857 | |
3858 /* | |
3859 ** This function is called to obtain a pointer to region iRegion of the | |
3860 ** shared-memory associated with the database file fd. Shared-memory regions | |
3861 ** are numbered starting from zero. Each shared-memory region is szRegion | |
3862 ** bytes in size. | |
3863 ** | |
3864 ** If an error occurs, an error code is returned and *pp is set to NULL. | |
3865 ** | |
3866 ** Otherwise, if the isWrite parameter is 0 and the requested shared-memory | |
3867 ** region has not been allocated (by any client, including one running in a | |
3868 ** separate process), then *pp is set to NULL and SQLITE_OK returned. If | |
3869 ** isWrite is non-zero and the requested shared-memory region has not yet | |
3870 ** been allocated, it is allocated by this function. | |
3871 ** | |
3872 ** If the shared-memory region has already been allocated or is allocated by | |
3873 ** this call as described above, then it is mapped into this processes | |
3874 ** address space (if it is not already), *pp is set to point to the mapped | |
3875 ** memory and SQLITE_OK returned. | |
3876 */ | |
3877 static int winShmMap( | |
3878 sqlite3_file *fd, /* Handle open on database file */ | |
3879 int iRegion, /* Region to retrieve */ | |
3880 int szRegion, /* Size of regions */ | |
3881 int isWrite, /* True to extend file if necessary */ | |
3882 void volatile **pp /* OUT: Mapped memory */ | |
3883 ){ | |
3884 winFile *pDbFd = (winFile*)fd; | |
3885 winShm *pShm = pDbFd->pShm; | |
3886 winShmNode *pShmNode; | |
3887 int rc = SQLITE_OK; | |
3888 | |
3889 if( !pShm ){ | |
3890 rc = winOpenSharedMemory(pDbFd); | |
3891 if( rc!=SQLITE_OK ) return rc; | |
3892 pShm = pDbFd->pShm; | |
3893 } | |
3894 pShmNode = pShm->pShmNode; | |
3895 | |
3896 sqlite3_mutex_enter(pShmNode->mutex); | |
3897 assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 ); | |
3898 | |
3899 if( pShmNode->nRegion<=iRegion ){ | |
3900 struct ShmRegion *apNew; /* New aRegion[] array */ | |
3901 int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ | |
3902 sqlite3_int64 sz; /* Current size of wal-index file */ | |
3903 | |
3904 pShmNode->szRegion = szRegion; | |
3905 | |
3906 /* The requested region is not mapped into this processes address space. | |
3907 ** Check to see if it has been allocated (i.e. if the wal-index file is | |
3908 ** large enough to contain the requested region). | |
3909 */ | |
3910 rc = winFileSize((sqlite3_file *)&pShmNode->hFile, &sz); | |
3911 if( rc!=SQLITE_OK ){ | |
3912 rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), | |
3913 "winShmMap1", pDbFd->zPath); | |
3914 goto shmpage_out; | |
3915 } | |
3916 | |
3917 if( sz<nByte ){ | |
3918 /* The requested memory region does not exist. If isWrite is set to | |
3919 ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned. | |
3920 ** | |
3921 ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate | |
3922 ** the requested memory region. | |
3923 */ | |
3924 if( !isWrite ) goto shmpage_out; | |
3925 rc = winTruncate((sqlite3_file *)&pShmNode->hFile, nByte); | |
3926 if( rc!=SQLITE_OK ){ | |
3927 rc = winLogError(SQLITE_IOERR_SHMSIZE, osGetLastError(), | |
3928 "winShmMap2", pDbFd->zPath); | |
3929 goto shmpage_out; | |
3930 } | |
3931 } | |
3932 | |
3933 /* Map the requested memory region into this processes address space. */ | |
3934 apNew = (struct ShmRegion *)sqlite3_realloc64( | |
3935 pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) | |
3936 ); | |
3937 if( !apNew ){ | |
3938 rc = SQLITE_IOERR_NOMEM; | |
3939 goto shmpage_out; | |
3940 } | |
3941 pShmNode->aRegion = apNew; | |
3942 | |
3943 while( pShmNode->nRegion<=iRegion ){ | |
3944 HANDLE hMap = NULL; /* file-mapping handle */ | |
3945 void *pMap = 0; /* Mapped memory region */ | |
3946 | |
3947 #if SQLITE_OS_WINRT | |
3948 hMap = osCreateFileMappingFromApp(pShmNode->hFile.h, | |
3949 NULL, PAGE_READWRITE, nByte, NULL | |
3950 ); | |
3951 #elif defined(SQLITE_WIN32_HAS_WIDE) | |
3952 hMap = osCreateFileMappingW(pShmNode->hFile.h, | |
3953 NULL, PAGE_READWRITE, 0, nByte, NULL | |
3954 ); | |
3955 #elif defined(SQLITE_WIN32_HAS_ANSI) | |
3956 hMap = osCreateFileMappingA(pShmNode->hFile.h, | |
3957 NULL, PAGE_READWRITE, 0, nByte, NULL | |
3958 ); | |
3959 #endif | |
3960 OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", | |
3961 osGetCurrentProcessId(), pShmNode->nRegion, nByte, | |
3962 hMap ? "ok" : "failed")); | |
3963 if( hMap ){ | |
3964 int iOffset = pShmNode->nRegion*szRegion; | |
3965 int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; | |
3966 #if SQLITE_OS_WINRT | |
3967 pMap = osMapViewOfFileFromApp(hMap, FILE_MAP_WRITE | FILE_MAP_READ, | |
3968 iOffset - iOffsetShift, szRegion + iOffsetShift | |
3969 ); | |
3970 #else | |
3971 pMap = osMapViewOfFile(hMap, FILE_MAP_WRITE | FILE_MAP_READ, | |
3972 0, iOffset - iOffsetShift, szRegion + iOffsetShift | |
3973 ); | |
3974 #endif | |
3975 OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", | |
3976 osGetCurrentProcessId(), pShmNode->nRegion, iOffset, | |
3977 szRegion, pMap ? "ok" : "failed")); | |
3978 } | |
3979 if( !pMap ){ | |
3980 pShmNode->lastErrno = osGetLastError(); | |
3981 rc = winLogError(SQLITE_IOERR_SHMMAP, pShmNode->lastErrno, | |
3982 "winShmMap3", pDbFd->zPath); | |
3983 if( hMap ) osCloseHandle(hMap); | |
3984 goto shmpage_out; | |
3985 } | |
3986 | |
3987 pShmNode->aRegion[pShmNode->nRegion].pMap = pMap; | |
3988 pShmNode->aRegion[pShmNode->nRegion].hMap = hMap; | |
3989 pShmNode->nRegion++; | |
3990 } | |
3991 } | |
3992 | |
3993 shmpage_out: | |
3994 if( pShmNode->nRegion>iRegion ){ | |
3995 int iOffset = iRegion*szRegion; | |
3996 int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; | |
3997 char *p = (char *)pShmNode->aRegion[iRegion].pMap; | |
3998 *pp = (void *)&p[iOffsetShift]; | |
3999 }else{ | |
4000 *pp = 0; | |
4001 } | |
4002 sqlite3_mutex_leave(pShmNode->mutex); | |
4003 return rc; | |
4004 } | |
4005 | |
4006 #else | |
4007 # define winShmMap 0 | |
4008 # define winShmLock 0 | |
4009 # define winShmBarrier 0 | |
4010 # define winShmUnmap 0 | |
4011 #endif /* #ifndef SQLITE_OMIT_WAL */ | |
4012 | |
4013 /* | |
4014 ** Cleans up the mapped region of the specified file, if any. | |
4015 */ | |
4016 #if SQLITE_MAX_MMAP_SIZE>0 | |
4017 static int winUnmapfile(winFile *pFile){ | |
4018 assert( pFile!=0 ); | |
4019 OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, pMapRegion=%p, " | |
4020 "mmapSize=%lld, mmapSizeActual=%lld, mmapSizeMax=%lld\n", | |
4021 osGetCurrentProcessId(), pFile, pFile->hMap, pFile->pMapRegion, | |
4022 pFile->mmapSize, pFile->mmapSizeActual, pFile->mmapSizeMax)); | |
4023 if( pFile->pMapRegion ){ | |
4024 if( !osUnmapViewOfFile(pFile->pMapRegion) ){ | |
4025 pFile->lastErrno = osGetLastError(); | |
4026 OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, pMapRegion=%p, " | |
4027 "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(), pFile, | |
4028 pFile->pMapRegion)); | |
4029 return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, | |
4030 "winUnmapfile1", pFile->zPath); | |
4031 } | |
4032 pFile->pMapRegion = 0; | |
4033 pFile->mmapSize = 0; | |
4034 pFile->mmapSizeActual = 0; | |
4035 } | |
4036 if( pFile->hMap!=NULL ){ | |
4037 if( !osCloseHandle(pFile->hMap) ){ | |
4038 pFile->lastErrno = osGetLastError(); | |
4039 OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, hMap=%p, rc=SQLITE_IOERR_MMAP\n", | |
4040 osGetCurrentProcessId(), pFile, pFile->hMap)); | |
4041 return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno, | |
4042 "winUnmapfile2", pFile->zPath); | |
4043 } | |
4044 pFile->hMap = NULL; | |
4045 } | |
4046 OSTRACE(("UNMAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", | |
4047 osGetCurrentProcessId(), pFile)); | |
4048 return SQLITE_OK; | |
4049 } | |
4050 | |
4051 /* | |
4052 ** Memory map or remap the file opened by file-descriptor pFd (if the file | |
4053 ** is already mapped, the existing mapping is replaced by the new). Or, if | |
4054 ** there already exists a mapping for this file, and there are still | |
4055 ** outstanding xFetch() references to it, this function is a no-op. | |
4056 ** | |
4057 ** If parameter nByte is non-negative, then it is the requested size of | |
4058 ** the mapping to create. Otherwise, if nByte is less than zero, then the | |
4059 ** requested size is the size of the file on disk. The actual size of the | |
4060 ** created mapping is either the requested size or the value configured | |
4061 ** using SQLITE_FCNTL_MMAP_SIZE, whichever is smaller. | |
4062 ** | |
4063 ** SQLITE_OK is returned if no error occurs (even if the mapping is not | |
4064 ** recreated as a result of outstanding references) or an SQLite error | |
4065 ** code otherwise. | |
4066 */ | |
4067 static int winMapfile(winFile *pFd, sqlite3_int64 nByte){ | |
4068 sqlite3_int64 nMap = nByte; | |
4069 int rc; | |
4070 | |
4071 assert( nMap>=0 || pFd->nFetchOut==0 ); | |
4072 OSTRACE(("MAP-FILE pid=%lu, pFile=%p, size=%lld\n", | |
4073 osGetCurrentProcessId(), pFd, nByte)); | |
4074 | |
4075 if( pFd->nFetchOut>0 ) return SQLITE_OK; | |
4076 | |
4077 if( nMap<0 ){ | |
4078 rc = winFileSize((sqlite3_file*)pFd, &nMap); | |
4079 if( rc ){ | |
4080 OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_IOERR_FSTAT\n", | |
4081 osGetCurrentProcessId(), pFd)); | |
4082 return SQLITE_IOERR_FSTAT; | |
4083 } | |
4084 } | |
4085 if( nMap>pFd->mmapSizeMax ){ | |
4086 nMap = pFd->mmapSizeMax; | |
4087 } | |
4088 nMap &= ~(sqlite3_int64)(winSysInfo.dwPageSize - 1); | |
4089 | |
4090 if( nMap==0 && pFd->mmapSize>0 ){ | |
4091 winUnmapfile(pFd); | |
4092 } | |
4093 if( nMap!=pFd->mmapSize ){ | |
4094 void *pNew = 0; | |
4095 DWORD protect = PAGE_READONLY; | |
4096 DWORD flags = FILE_MAP_READ; | |
4097 | |
4098 winUnmapfile(pFd); | |
4099 #ifdef SQLITE_MMAP_READWRITE | |
4100 if( (pFd->ctrlFlags & WINFILE_RDONLY)==0 ){ | |
4101 protect = PAGE_READWRITE; | |
4102 flags |= FILE_MAP_WRITE; | |
4103 } | |
4104 #endif | |
4105 #if SQLITE_OS_WINRT | |
4106 pFd->hMap = osCreateFileMappingFromApp(pFd->h, NULL, protect, nMap, NULL); | |
4107 #elif defined(SQLITE_WIN32_HAS_WIDE) | |
4108 pFd->hMap = osCreateFileMappingW(pFd->h, NULL, protect, | |
4109 (DWORD)((nMap>>32) & 0xffffffff), | |
4110 (DWORD)(nMap & 0xffffffff), NULL); | |
4111 #elif defined(SQLITE_WIN32_HAS_ANSI) | |
4112 pFd->hMap = osCreateFileMappingA(pFd->h, NULL, protect, | |
4113 (DWORD)((nMap>>32) & 0xffffffff), | |
4114 (DWORD)(nMap & 0xffffffff), NULL); | |
4115 #endif | |
4116 if( pFd->hMap==NULL ){ | |
4117 pFd->lastErrno = osGetLastError(); | |
4118 rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, | |
4119 "winMapfile1", pFd->zPath); | |
4120 /* Log the error, but continue normal operation using xRead/xWrite */ | |
4121 OSTRACE(("MAP-FILE-CREATE pid=%lu, pFile=%p, rc=%s\n", | |
4122 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); | |
4123 return SQLITE_OK; | |
4124 } | |
4125 assert( (nMap % winSysInfo.dwPageSize)==0 ); | |
4126 assert( sizeof(SIZE_T)==sizeof(sqlite3_int64) || nMap<=0xffffffff ); | |
4127 #if SQLITE_OS_WINRT | |
4128 pNew = osMapViewOfFileFromApp(pFd->hMap, flags, 0, (SIZE_T)nMap); | |
4129 #else | |
4130 pNew = osMapViewOfFile(pFd->hMap, flags, 0, 0, (SIZE_T)nMap); | |
4131 #endif | |
4132 if( pNew==NULL ){ | |
4133 osCloseHandle(pFd->hMap); | |
4134 pFd->hMap = NULL; | |
4135 pFd->lastErrno = osGetLastError(); | |
4136 rc = winLogError(SQLITE_IOERR_MMAP, pFd->lastErrno, | |
4137 "winMapfile2", pFd->zPath); | |
4138 /* Log the error, but continue normal operation using xRead/xWrite */ | |
4139 OSTRACE(("MAP-FILE-MAP pid=%lu, pFile=%p, rc=%s\n", | |
4140 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); | |
4141 return SQLITE_OK; | |
4142 } | |
4143 pFd->pMapRegion = pNew; | |
4144 pFd->mmapSize = nMap; | |
4145 pFd->mmapSizeActual = nMap; | |
4146 } | |
4147 | |
4148 OSTRACE(("MAP-FILE pid=%lu, pFile=%p, rc=SQLITE_OK\n", | |
4149 osGetCurrentProcessId(), pFd)); | |
4150 return SQLITE_OK; | |
4151 } | |
4152 #endif /* SQLITE_MAX_MMAP_SIZE>0 */ | |
4153 | |
4154 /* | |
4155 ** If possible, return a pointer to a mapping of file fd starting at offset | |
4156 ** iOff. The mapping must be valid for at least nAmt bytes. | |
4157 ** | |
4158 ** If such a pointer can be obtained, store it in *pp and return SQLITE_OK. | |
4159 ** Or, if one cannot but no error occurs, set *pp to 0 and return SQLITE_OK. | |
4160 ** Finally, if an error does occur, return an SQLite error code. The final | |
4161 ** value of *pp is undefined in this case. | |
4162 ** | |
4163 ** If this function does return a pointer, the caller must eventually | |
4164 ** release the reference by calling winUnfetch(). | |
4165 */ | |
4166 static int winFetch(sqlite3_file *fd, i64 iOff, int nAmt, void **pp){ | |
4167 #if SQLITE_MAX_MMAP_SIZE>0 | |
4168 winFile *pFd = (winFile*)fd; /* The underlying database file */ | |
4169 #endif | |
4170 *pp = 0; | |
4171 | |
4172 OSTRACE(("FETCH pid=%lu, pFile=%p, offset=%lld, amount=%d, pp=%p\n", | |
4173 osGetCurrentProcessId(), fd, iOff, nAmt, pp)); | |
4174 | |
4175 #if SQLITE_MAX_MMAP_SIZE>0 | |
4176 if( pFd->mmapSizeMax>0 ){ | |
4177 if( pFd->pMapRegion==0 ){ | |
4178 int rc = winMapfile(pFd, -1); | |
4179 if( rc!=SQLITE_OK ){ | |
4180 OSTRACE(("FETCH pid=%lu, pFile=%p, rc=%s\n", | |
4181 osGetCurrentProcessId(), pFd, sqlite3ErrName(rc))); | |
4182 return rc; | |
4183 } | |
4184 } | |
4185 if( pFd->mmapSize >= iOff+nAmt ){ | |
4186 *pp = &((u8 *)pFd->pMapRegion)[iOff]; | |
4187 pFd->nFetchOut++; | |
4188 } | |
4189 } | |
4190 #endif | |
4191 | |
4192 OSTRACE(("FETCH pid=%lu, pFile=%p, pp=%p, *pp=%p, rc=SQLITE_OK\n", | |
4193 osGetCurrentProcessId(), fd, pp, *pp)); | |
4194 return SQLITE_OK; | |
4195 } | |
4196 | |
4197 /* | |
4198 ** If the third argument is non-NULL, then this function releases a | |
4199 ** reference obtained by an earlier call to winFetch(). The second | |
4200 ** argument passed to this function must be the same as the corresponding | |
4201 ** argument that was passed to the winFetch() invocation. | |
4202 ** | |
4203 ** Or, if the third argument is NULL, then this function is being called | |
4204 ** to inform the VFS layer that, according to POSIX, any existing mapping | |
4205 ** may now be invalid and should be unmapped. | |
4206 */ | |
4207 static int winUnfetch(sqlite3_file *fd, i64 iOff, void *p){ | |
4208 #if SQLITE_MAX_MMAP_SIZE>0 | |
4209 winFile *pFd = (winFile*)fd; /* The underlying database file */ | |
4210 | |
4211 /* If p==0 (unmap the entire file) then there must be no outstanding | |
4212 ** xFetch references. Or, if p!=0 (meaning it is an xFetch reference), | |
4213 ** then there must be at least one outstanding. */ | |
4214 assert( (p==0)==(pFd->nFetchOut==0) ); | |
4215 | |
4216 /* If p!=0, it must match the iOff value. */ | |
4217 assert( p==0 || p==&((u8 *)pFd->pMapRegion)[iOff] ); | |
4218 | |
4219 OSTRACE(("UNFETCH pid=%lu, pFile=%p, offset=%lld, p=%p\n", | |
4220 osGetCurrentProcessId(), pFd, iOff, p)); | |
4221 | |
4222 if( p ){ | |
4223 pFd->nFetchOut--; | |
4224 }else{ | |
4225 /* FIXME: If Windows truly always prevents truncating or deleting a | |
4226 ** file while a mapping is held, then the following winUnmapfile() call | |
4227 ** is unnecessary can be omitted - potentially improving | |
4228 ** performance. */ | |
4229 winUnmapfile(pFd); | |
4230 } | |
4231 | |
4232 assert( pFd->nFetchOut>=0 ); | |
4233 #endif | |
4234 | |
4235 OSTRACE(("UNFETCH pid=%lu, pFile=%p, rc=SQLITE_OK\n", | |
4236 osGetCurrentProcessId(), fd)); | |
4237 return SQLITE_OK; | |
4238 } | |
4239 | |
4240 /* | |
4241 ** Here ends the implementation of all sqlite3_file methods. | |
4242 ** | |
4243 ********************** End sqlite3_file Methods ******************************* | |
4244 ******************************************************************************/ | |
4245 | |
4246 /* | |
4247 ** This vector defines all the methods that can operate on an | |
4248 ** sqlite3_file for win32. | |
4249 */ | |
4250 static const sqlite3_io_methods winIoMethod = { | |
4251 3, /* iVersion */ | |
4252 winClose, /* xClose */ | |
4253 winRead, /* xRead */ | |
4254 winWrite, /* xWrite */ | |
4255 winTruncate, /* xTruncate */ | |
4256 winSync, /* xSync */ | |
4257 winFileSize, /* xFileSize */ | |
4258 winLock, /* xLock */ | |
4259 winUnlock, /* xUnlock */ | |
4260 winCheckReservedLock, /* xCheckReservedLock */ | |
4261 winFileControl, /* xFileControl */ | |
4262 winSectorSize, /* xSectorSize */ | |
4263 winDeviceCharacteristics, /* xDeviceCharacteristics */ | |
4264 winShmMap, /* xShmMap */ | |
4265 winShmLock, /* xShmLock */ | |
4266 winShmBarrier, /* xShmBarrier */ | |
4267 winShmUnmap, /* xShmUnmap */ | |
4268 winFetch, /* xFetch */ | |
4269 winUnfetch /* xUnfetch */ | |
4270 }; | |
4271 | |
4272 /**************************************************************************** | |
4273 **************************** sqlite3_vfs methods **************************** | |
4274 ** | |
4275 ** This division contains the implementation of methods on the | |
4276 ** sqlite3_vfs object. | |
4277 */ | |
4278 | |
4279 #if defined(__CYGWIN__) | |
4280 /* | |
4281 ** Convert a filename from whatever the underlying operating system | |
4282 ** supports for filenames into UTF-8. Space to hold the result is | |
4283 ** obtained from malloc and must be freed by the calling function. | |
4284 */ | |
4285 static char *winConvertToUtf8Filename(const void *zFilename){ | |
4286 char *zConverted = 0; | |
4287 if( osIsNT() ){ | |
4288 zConverted = winUnicodeToUtf8(zFilename); | |
4289 } | |
4290 #ifdef SQLITE_WIN32_HAS_ANSI | |
4291 else{ | |
4292 zConverted = sqlite3_win32_mbcs_to_utf8(zFilename); | |
4293 } | |
4294 #endif | |
4295 /* caller will handle out of memory */ | |
4296 return zConverted; | |
4297 } | |
4298 #endif | |
4299 | |
4300 /* | |
4301 ** Convert a UTF-8 filename into whatever form the underlying | |
4302 ** operating system wants filenames in. Space to hold the result | |
4303 ** is obtained from malloc and must be freed by the calling | |
4304 ** function. | |
4305 */ | |
4306 static void *winConvertFromUtf8Filename(const char *zFilename){ | |
4307 void *zConverted = 0; | |
4308 if( osIsNT() ){ | |
4309 zConverted = winUtf8ToUnicode(zFilename); | |
4310 } | |
4311 #ifdef SQLITE_WIN32_HAS_ANSI | |
4312 else{ | |
4313 zConverted = sqlite3_win32_utf8_to_mbcs(zFilename); | |
4314 } | |
4315 #endif | |
4316 /* caller will handle out of memory */ | |
4317 return zConverted; | |
4318 } | |
4319 | |
4320 /* | |
4321 ** This function returns non-zero if the specified UTF-8 string buffer | |
4322 ** ends with a directory separator character or one was successfully | |
4323 ** added to it. | |
4324 */ | |
4325 static int winMakeEndInDirSep(int nBuf, char *zBuf){ | |
4326 if( zBuf ){ | |
4327 int nLen = sqlite3Strlen30(zBuf); | |
4328 if( nLen>0 ){ | |
4329 if( winIsDirSep(zBuf[nLen-1]) ){ | |
4330 return 1; | |
4331 }else if( nLen+1<nBuf ){ | |
4332 zBuf[nLen] = winGetDirSep(); | |
4333 zBuf[nLen+1] = '\0'; | |
4334 return 1; | |
4335 } | |
4336 } | |
4337 } | |
4338 return 0; | |
4339 } | |
4340 | |
4341 /* | |
4342 ** Create a temporary file name and store the resulting pointer into pzBuf. | |
4343 ** The pointer returned in pzBuf must be freed via sqlite3_free(). | |
4344 */ | |
4345 static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){ | |
4346 static char zChars[] = | |
4347 "abcdefghijklmnopqrstuvwxyz" | |
4348 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
4349 "0123456789"; | |
4350 size_t i, j; | |
4351 int nPre = sqlite3Strlen30(SQLITE_TEMP_FILE_PREFIX); | |
4352 int nMax, nBuf, nDir, nLen; | |
4353 char *zBuf; | |
4354 | |
4355 /* It's odd to simulate an io-error here, but really this is just | |
4356 ** using the io-error infrastructure to test that SQLite handles this | |
4357 ** function failing. | |
4358 */ | |
4359 SimulateIOError( return SQLITE_IOERR ); | |
4360 | |
4361 /* Allocate a temporary buffer to store the fully qualified file | |
4362 ** name for the temporary file. If this fails, we cannot continue. | |
4363 */ | |
4364 nMax = pVfs->mxPathname; nBuf = nMax + 2; | |
4365 zBuf = sqlite3MallocZero( nBuf ); | |
4366 if( !zBuf ){ | |
4367 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4368 return SQLITE_IOERR_NOMEM; | |
4369 } | |
4370 | |
4371 /* Figure out the effective temporary directory. First, check if one | |
4372 ** has been explicitly set by the application; otherwise, use the one | |
4373 ** configured by the operating system. | |
4374 */ | |
4375 nDir = nMax - (nPre + 15); | |
4376 assert( nDir>0 ); | |
4377 if( sqlite3_temp_directory ){ | |
4378 int nDirLen = sqlite3Strlen30(sqlite3_temp_directory); | |
4379 if( nDirLen>0 ){ | |
4380 if( !winIsDirSep(sqlite3_temp_directory[nDirLen-1]) ){ | |
4381 nDirLen++; | |
4382 } | |
4383 if( nDirLen>nDir ){ | |
4384 sqlite3_free(zBuf); | |
4385 OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); | |
4386 return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); | |
4387 } | |
4388 sqlite3_snprintf(nMax, zBuf, "%s", sqlite3_temp_directory); | |
4389 } | |
4390 } | |
4391 #if defined(__CYGWIN__) | |
4392 else{ | |
4393 static const char *azDirs[] = { | |
4394 0, /* getenv("SQLITE_TMPDIR") */ | |
4395 0, /* getenv("TMPDIR") */ | |
4396 0, /* getenv("TMP") */ | |
4397 0, /* getenv("TEMP") */ | |
4398 0, /* getenv("USERPROFILE") */ | |
4399 "/var/tmp", | |
4400 "/usr/tmp", | |
4401 "/tmp", | |
4402 ".", | |
4403 0 /* List terminator */ | |
4404 }; | |
4405 unsigned int i; | |
4406 const char *zDir = 0; | |
4407 | |
4408 if( !azDirs[0] ) azDirs[0] = getenv("SQLITE_TMPDIR"); | |
4409 if( !azDirs[1] ) azDirs[1] = getenv("TMPDIR"); | |
4410 if( !azDirs[2] ) azDirs[2] = getenv("TMP"); | |
4411 if( !azDirs[3] ) azDirs[3] = getenv("TEMP"); | |
4412 if( !azDirs[4] ) azDirs[4] = getenv("USERPROFILE"); | |
4413 for(i=0; i<sizeof(azDirs)/sizeof(azDirs[0]); zDir=azDirs[i++]){ | |
4414 void *zConverted; | |
4415 if( zDir==0 ) continue; | |
4416 /* If the path starts with a drive letter followed by the colon | |
4417 ** character, assume it is already a native Win32 path; otherwise, | |
4418 ** it must be converted to a native Win32 path via the Cygwin API | |
4419 ** prior to using it. | |
4420 */ | |
4421 if( winIsDriveLetterAndColon(zDir) ){ | |
4422 zConverted = winConvertFromUtf8Filename(zDir); | |
4423 if( !zConverted ){ | |
4424 sqlite3_free(zBuf); | |
4425 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4426 return SQLITE_IOERR_NOMEM; | |
4427 } | |
4428 if( winIsDir(zConverted) ){ | |
4429 sqlite3_snprintf(nMax, zBuf, "%s", zDir); | |
4430 sqlite3_free(zConverted); | |
4431 break; | |
4432 } | |
4433 sqlite3_free(zConverted); | |
4434 }else{ | |
4435 zConverted = sqlite3MallocZero( nMax+1 ); | |
4436 if( !zConverted ){ | |
4437 sqlite3_free(zBuf); | |
4438 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4439 return SQLITE_IOERR_NOMEM; | |
4440 } | |
4441 if( cygwin_conv_path( | |
4442 osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir, | |
4443 zConverted, nMax+1)<0 ){ | |
4444 sqlite3_free(zConverted); | |
4445 sqlite3_free(zBuf); | |
4446 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n")); | |
4447 return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno, | |
4448 "winGetTempname2", zDir); | |
4449 } | |
4450 if( winIsDir(zConverted) ){ | |
4451 /* At this point, we know the candidate directory exists and should | |
4452 ** be used. However, we may need to convert the string containing | |
4453 ** its name into UTF-8 (i.e. if it is UTF-16 right now). | |
4454 */ | |
4455 char *zUtf8 = winConvertToUtf8Filename(zConverted); | |
4456 if( !zUtf8 ){ | |
4457 sqlite3_free(zConverted); | |
4458 sqlite3_free(zBuf); | |
4459 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4460 return SQLITE_IOERR_NOMEM; | |
4461 } | |
4462 sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); | |
4463 sqlite3_free(zUtf8); | |
4464 sqlite3_free(zConverted); | |
4465 break; | |
4466 } | |
4467 sqlite3_free(zConverted); | |
4468 } | |
4469 } | |
4470 } | |
4471 #elif !SQLITE_OS_WINRT && !defined(__CYGWIN__) | |
4472 else if( osIsNT() ){ | |
4473 char *zMulti; | |
4474 LPWSTR zWidePath = sqlite3MallocZero( nMax*sizeof(WCHAR) ); | |
4475 if( !zWidePath ){ | |
4476 sqlite3_free(zBuf); | |
4477 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4478 return SQLITE_IOERR_NOMEM; | |
4479 } | |
4480 if( osGetTempPathW(nMax, zWidePath)==0 ){ | |
4481 sqlite3_free(zWidePath); | |
4482 sqlite3_free(zBuf); | |
4483 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n")); | |
4484 return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), | |
4485 "winGetTempname2", 0); | |
4486 } | |
4487 zMulti = winUnicodeToUtf8(zWidePath); | |
4488 if( zMulti ){ | |
4489 sqlite3_snprintf(nMax, zBuf, "%s", zMulti); | |
4490 sqlite3_free(zMulti); | |
4491 sqlite3_free(zWidePath); | |
4492 }else{ | |
4493 sqlite3_free(zWidePath); | |
4494 sqlite3_free(zBuf); | |
4495 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4496 return SQLITE_IOERR_NOMEM; | |
4497 } | |
4498 } | |
4499 #ifdef SQLITE_WIN32_HAS_ANSI | |
4500 else{ | |
4501 char *zUtf8; | |
4502 char *zMbcsPath = sqlite3MallocZero( nMax ); | |
4503 if( !zMbcsPath ){ | |
4504 sqlite3_free(zBuf); | |
4505 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4506 return SQLITE_IOERR_NOMEM; | |
4507 } | |
4508 if( osGetTempPathA(nMax, zMbcsPath)==0 ){ | |
4509 sqlite3_free(zBuf); | |
4510 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_GETTEMPPATH\n")); | |
4511 return winLogError(SQLITE_IOERR_GETTEMPPATH, osGetLastError(), | |
4512 "winGetTempname3", 0); | |
4513 } | |
4514 zUtf8 = sqlite3_win32_mbcs_to_utf8(zMbcsPath); | |
4515 if( zUtf8 ){ | |
4516 sqlite3_snprintf(nMax, zBuf, "%s", zUtf8); | |
4517 sqlite3_free(zUtf8); | |
4518 }else{ | |
4519 sqlite3_free(zBuf); | |
4520 OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n")); | |
4521 return SQLITE_IOERR_NOMEM; | |
4522 } | |
4523 } | |
4524 #endif /* SQLITE_WIN32_HAS_ANSI */ | |
4525 #endif /* !SQLITE_OS_WINRT */ | |
4526 | |
4527 /* | |
4528 ** Check to make sure the temporary directory ends with an appropriate | |
4529 ** separator. If it does not and there is not enough space left to add | |
4530 ** one, fail. | |
4531 */ | |
4532 if( !winMakeEndInDirSep(nDir+1, zBuf) ){ | |
4533 sqlite3_free(zBuf); | |
4534 OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); | |
4535 return winLogError(SQLITE_ERROR, 0, "winGetTempname4", 0); | |
4536 } | |
4537 | |
4538 /* | |
4539 ** Check that the output buffer is large enough for the temporary file | |
4540 ** name in the following format: | |
4541 ** | |
4542 ** "<temporary_directory>/etilqs_XXXXXXXXXXXXXXX\0\0" | |
4543 ** | |
4544 ** If not, return SQLITE_ERROR. The number 17 is used here in order to | |
4545 ** account for the space used by the 15 character random suffix and the | |
4546 ** two trailing NUL characters. The final directory separator character | |
4547 ** has already added if it was not already present. | |
4548 */ | |
4549 nLen = sqlite3Strlen30(zBuf); | |
4550 if( (nLen + nPre + 17) > nBuf ){ | |
4551 sqlite3_free(zBuf); | |
4552 OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); | |
4553 return winLogError(SQLITE_ERROR, 0, "winGetTempname5", 0); | |
4554 } | |
4555 | |
4556 sqlite3_snprintf(nBuf-16-nLen, zBuf+nLen, SQLITE_TEMP_FILE_PREFIX); | |
4557 | |
4558 j = sqlite3Strlen30(zBuf); | |
4559 sqlite3_randomness(15, &zBuf[j]); | |
4560 for(i=0; i<15; i++, j++){ | |
4561 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ]; | |
4562 } | |
4563 zBuf[j] = 0; | |
4564 zBuf[j+1] = 0; | |
4565 *pzBuf = zBuf; | |
4566 | |
4567 OSTRACE(("TEMP-FILENAME name=%s, rc=SQLITE_OK\n", zBuf)); | |
4568 return SQLITE_OK; | |
4569 } | |
4570 | |
4571 /* | |
4572 ** Return TRUE if the named file is really a directory. Return false if | |
4573 ** it is something other than a directory, or if there is any kind of memory | |
4574 ** allocation failure. | |
4575 */ | |
4576 static int winIsDir(const void *zConverted){ | |
4577 DWORD attr; | |
4578 int rc = 0; | |
4579 DWORD lastErrno; | |
4580 | |
4581 if( osIsNT() ){ | |
4582 int cnt = 0; | |
4583 WIN32_FILE_ATTRIBUTE_DATA sAttrData; | |
4584 memset(&sAttrData, 0, sizeof(sAttrData)); | |
4585 while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, | |
4586 GetFileExInfoStandard, | |
4587 &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} | |
4588 if( !rc ){ | |
4589 return 0; /* Invalid name? */ | |
4590 } | |
4591 attr = sAttrData.dwFileAttributes; | |
4592 #if SQLITE_OS_WINCE==0 | |
4593 }else{ | |
4594 attr = osGetFileAttributesA((char*)zConverted); | |
4595 #endif | |
4596 } | |
4597 return (attr!=INVALID_FILE_ATTRIBUTES) && (attr&FILE_ATTRIBUTE_DIRECTORY); | |
4598 } | |
4599 | |
4600 /* | |
4601 ** Open a file. | |
4602 */ | |
4603 static int winOpen( | |
4604 sqlite3_vfs *pVfs, /* Used to get maximum path name length */ | |
4605 const char *zName, /* Name of the file (UTF-8) */ | |
4606 sqlite3_file *id, /* Write the SQLite file handle here */ | |
4607 int flags, /* Open mode flags */ | |
4608 int *pOutFlags /* Status return flags */ | |
4609 ){ | |
4610 HANDLE h; | |
4611 DWORD lastErrno = 0; | |
4612 DWORD dwDesiredAccess; | |
4613 DWORD dwShareMode; | |
4614 DWORD dwCreationDisposition; | |
4615 DWORD dwFlagsAndAttributes = 0; | |
4616 #if SQLITE_OS_WINCE | |
4617 int isTemp = 0; | |
4618 #endif | |
4619 winFile *pFile = (winFile*)id; | |
4620 void *zConverted; /* Filename in OS encoding */ | |
4621 const char *zUtf8Name = zName; /* Filename in UTF-8 encoding */ | |
4622 int cnt = 0; | |
4623 | |
4624 /* If argument zPath is a NULL pointer, this function is required to open | |
4625 ** a temporary file. Use this buffer to store the file name in. | |
4626 */ | |
4627 char *zTmpname = 0; /* For temporary filename, if necessary. */ | |
4628 | |
4629 int rc = SQLITE_OK; /* Function Return Code */ | |
4630 #if !defined(NDEBUG) || SQLITE_OS_WINCE | |
4631 int eType = flags&0xFFFFFF00; /* Type of file to open */ | |
4632 #endif | |
4633 | |
4634 int isExclusive = (flags & SQLITE_OPEN_EXCLUSIVE); | |
4635 int isDelete = (flags & SQLITE_OPEN_DELETEONCLOSE); | |
4636 int isCreate = (flags & SQLITE_OPEN_CREATE); | |
4637 int isReadonly = (flags & SQLITE_OPEN_READONLY); | |
4638 int isReadWrite = (flags & SQLITE_OPEN_READWRITE); | |
4639 | |
4640 #ifndef NDEBUG | |
4641 int isOpenJournal = (isCreate && ( | |
4642 eType==SQLITE_OPEN_MASTER_JOURNAL | |
4643 || eType==SQLITE_OPEN_MAIN_JOURNAL | |
4644 || eType==SQLITE_OPEN_WAL | |
4645 )); | |
4646 #endif | |
4647 | |
4648 OSTRACE(("OPEN name=%s, pFile=%p, flags=%x, pOutFlags=%p\n", | |
4649 zUtf8Name, id, flags, pOutFlags)); | |
4650 | |
4651 /* Check the following statements are true: | |
4652 ** | |
4653 ** (a) Exactly one of the READWRITE and READONLY flags must be set, and | |
4654 ** (b) if CREATE is set, then READWRITE must also be set, and | |
4655 ** (c) if EXCLUSIVE is set, then CREATE must also be set. | |
4656 ** (d) if DELETEONCLOSE is set, then CREATE must also be set. | |
4657 */ | |
4658 assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly)); | |
4659 assert(isCreate==0 || isReadWrite); | |
4660 assert(isExclusive==0 || isCreate); | |
4661 assert(isDelete==0 || isCreate); | |
4662 | |
4663 /* The main DB, main journal, WAL file and master journal are never | |
4664 ** automatically deleted. Nor are they ever temporary files. */ | |
4665 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB ); | |
4666 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL ); | |
4667 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL ); | |
4668 assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL ); | |
4669 | |
4670 /* Assert that the upper layer has set one of the "file-type" flags. */ | |
4671 assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB | |
4672 || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL | |
4673 || eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL | |
4674 || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL | |
4675 ); | |
4676 | |
4677 assert( pFile!=0 ); | |
4678 memset(pFile, 0, sizeof(winFile)); | |
4679 pFile->h = INVALID_HANDLE_VALUE; | |
4680 | |
4681 #if SQLITE_OS_WINRT | |
4682 if( !zUtf8Name && !sqlite3_temp_directory ){ | |
4683 sqlite3_log(SQLITE_ERROR, | |
4684 "sqlite3_temp_directory variable should be set for WinRT"); | |
4685 } | |
4686 #endif | |
4687 | |
4688 /* If the second argument to this function is NULL, generate a | |
4689 ** temporary file name to use | |
4690 */ | |
4691 if( !zUtf8Name ){ | |
4692 assert( isDelete && !isOpenJournal ); | |
4693 rc = winGetTempname(pVfs, &zTmpname); | |
4694 if( rc!=SQLITE_OK ){ | |
4695 OSTRACE(("OPEN name=%s, rc=%s", zUtf8Name, sqlite3ErrName(rc))); | |
4696 return rc; | |
4697 } | |
4698 zUtf8Name = zTmpname; | |
4699 } | |
4700 | |
4701 /* Database filenames are double-zero terminated if they are not | |
4702 ** URIs with parameters. Hence, they can always be passed into | |
4703 ** sqlite3_uri_parameter(). | |
4704 */ | |
4705 assert( (eType!=SQLITE_OPEN_MAIN_DB) || (flags & SQLITE_OPEN_URI) || | |
4706 zUtf8Name[sqlite3Strlen30(zUtf8Name)+1]==0 ); | |
4707 | |
4708 /* Convert the filename to the system encoding. */ | |
4709 zConverted = winConvertFromUtf8Filename(zUtf8Name); | |
4710 if( zConverted==0 ){ | |
4711 sqlite3_free(zTmpname); | |
4712 OSTRACE(("OPEN name=%s, rc=SQLITE_IOERR_NOMEM", zUtf8Name)); | |
4713 return SQLITE_IOERR_NOMEM; | |
4714 } | |
4715 | |
4716 if( winIsDir(zConverted) ){ | |
4717 sqlite3_free(zConverted); | |
4718 sqlite3_free(zTmpname); | |
4719 OSTRACE(("OPEN name=%s, rc=SQLITE_CANTOPEN_ISDIR", zUtf8Name)); | |
4720 return SQLITE_CANTOPEN_ISDIR; | |
4721 } | |
4722 | |
4723 if( isReadWrite ){ | |
4724 dwDesiredAccess = GENERIC_READ | GENERIC_WRITE; | |
4725 }else{ | |
4726 dwDesiredAccess = GENERIC_READ; | |
4727 } | |
4728 | |
4729 /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is | |
4730 ** created. SQLite doesn't use it to indicate "exclusive access" | |
4731 ** as it is usually understood. | |
4732 */ | |
4733 if( isExclusive ){ | |
4734 /* Creates a new file, only if it does not already exist. */ | |
4735 /* If the file exists, it fails. */ | |
4736 dwCreationDisposition = CREATE_NEW; | |
4737 }else if( isCreate ){ | |
4738 /* Open existing file, or create if it doesn't exist */ | |
4739 dwCreationDisposition = OPEN_ALWAYS; | |
4740 }else{ | |
4741 /* Opens a file, only if it exists. */ | |
4742 dwCreationDisposition = OPEN_EXISTING; | |
4743 } | |
4744 | |
4745 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; | |
4746 | |
4747 if( isDelete ){ | |
4748 #if SQLITE_OS_WINCE | |
4749 dwFlagsAndAttributes = FILE_ATTRIBUTE_HIDDEN; | |
4750 isTemp = 1; | |
4751 #else | |
4752 dwFlagsAndAttributes = FILE_ATTRIBUTE_TEMPORARY | |
4753 | FILE_ATTRIBUTE_HIDDEN | |
4754 | FILE_FLAG_DELETE_ON_CLOSE; | |
4755 #endif | |
4756 }else{ | |
4757 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; | |
4758 } | |
4759 /* Reports from the internet are that performance is always | |
4760 ** better if FILE_FLAG_RANDOM_ACCESS is used. Ticket #2699. */ | |
4761 #if SQLITE_OS_WINCE | |
4762 dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS; | |
4763 #endif | |
4764 | |
4765 if( osIsNT() ){ | |
4766 #if SQLITE_OS_WINRT | |
4767 CREATEFILE2_EXTENDED_PARAMETERS extendedParameters; | |
4768 extendedParameters.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS); | |
4769 extendedParameters.dwFileAttributes = | |
4770 dwFlagsAndAttributes & FILE_ATTRIBUTE_MASK; | |
4771 extendedParameters.dwFileFlags = dwFlagsAndAttributes & FILE_FLAG_MASK; | |
4772 extendedParameters.dwSecurityQosFlags = SECURITY_ANONYMOUS; | |
4773 extendedParameters.lpSecurityAttributes = NULL; | |
4774 extendedParameters.hTemplateFile = NULL; | |
4775 while( (h = osCreateFile2((LPCWSTR)zConverted, | |
4776 dwDesiredAccess, | |
4777 dwShareMode, | |
4778 dwCreationDisposition, | |
4779 &extendedParameters))==INVALID_HANDLE_VALUE && | |
4780 winRetryIoerr(&cnt, &lastErrno) ){ | |
4781 /* Noop */ | |
4782 } | |
4783 #else | |
4784 while( (h = osCreateFileW((LPCWSTR)zConverted, | |
4785 dwDesiredAccess, | |
4786 dwShareMode, NULL, | |
4787 dwCreationDisposition, | |
4788 dwFlagsAndAttributes, | |
4789 NULL))==INVALID_HANDLE_VALUE && | |
4790 winRetryIoerr(&cnt, &lastErrno) ){ | |
4791 /* Noop */ | |
4792 } | |
4793 #endif | |
4794 } | |
4795 #ifdef SQLITE_WIN32_HAS_ANSI | |
4796 else{ | |
4797 while( (h = osCreateFileA((LPCSTR)zConverted, | |
4798 dwDesiredAccess, | |
4799 dwShareMode, NULL, | |
4800 dwCreationDisposition, | |
4801 dwFlagsAndAttributes, | |
4802 NULL))==INVALID_HANDLE_VALUE && | |
4803 winRetryIoerr(&cnt, &lastErrno) ){ | |
4804 /* Noop */ | |
4805 } | |
4806 } | |
4807 #endif | |
4808 winLogIoerr(cnt, __LINE__); | |
4809 | |
4810 OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name, | |
4811 dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); | |
4812 | |
4813 if( h==INVALID_HANDLE_VALUE ){ | |
4814 pFile->lastErrno = lastErrno; | |
4815 winLogError(SQLITE_CANTOPEN, pFile->lastErrno, "winOpen", zUtf8Name); | |
4816 sqlite3_free(zConverted); | |
4817 sqlite3_free(zTmpname); | |
4818 if( isReadWrite && !isExclusive ){ | |
4819 return winOpen(pVfs, zName, id, | |
4820 ((flags|SQLITE_OPEN_READONLY) & | |
4821 ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), | |
4822 pOutFlags); | |
4823 }else{ | |
4824 return SQLITE_CANTOPEN_BKPT; | |
4825 } | |
4826 } | |
4827 | |
4828 if( pOutFlags ){ | |
4829 if( isReadWrite ){ | |
4830 *pOutFlags = SQLITE_OPEN_READWRITE; | |
4831 }else{ | |
4832 *pOutFlags = SQLITE_OPEN_READONLY; | |
4833 } | |
4834 } | |
4835 | |
4836 OSTRACE(("OPEN file=%p, name=%s, access=%lx, pOutFlags=%p, *pOutFlags=%d, " | |
4837 "rc=%s\n", h, zUtf8Name, dwDesiredAccess, pOutFlags, pOutFlags ? | |
4838 *pOutFlags : 0, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok")); | |
4839 | |
4840 #if SQLITE_OS_WINCE | |
4841 if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB | |
4842 && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK | |
4843 ){ | |
4844 osCloseHandle(h); | |
4845 sqlite3_free(zConverted); | |
4846 sqlite3_free(zTmpname); | |
4847 OSTRACE(("OPEN-CE-LOCK name=%s, rc=%s\n", zName, sqlite3ErrName(rc))); | |
4848 return rc; | |
4849 } | |
4850 if( isTemp ){ | |
4851 pFile->zDeleteOnClose = zConverted; | |
4852 }else | |
4853 #endif | |
4854 { | |
4855 sqlite3_free(zConverted); | |
4856 } | |
4857 | |
4858 sqlite3_free(zTmpname); | |
4859 pFile->pMethod = &winIoMethod; | |
4860 pFile->pVfs = pVfs; | |
4861 pFile->h = h; | |
4862 if( isReadonly ){ | |
4863 pFile->ctrlFlags |= WINFILE_RDONLY; | |
4864 } | |
4865 if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){ | |
4866 pFile->ctrlFlags |= WINFILE_PSOW; | |
4867 } | |
4868 pFile->lastErrno = NO_ERROR; | |
4869 pFile->zPath = zName; | |
4870 #if SQLITE_MAX_MMAP_SIZE>0 | |
4871 pFile->hMap = NULL; | |
4872 pFile->pMapRegion = 0; | |
4873 pFile->mmapSize = 0; | |
4874 pFile->mmapSizeActual = 0; | |
4875 pFile->mmapSizeMax = sqlite3GlobalConfig.szMmap; | |
4876 #endif | |
4877 | |
4878 OpenCounter(+1); | |
4879 return rc; | |
4880 } | |
4881 | |
4882 /* | |
4883 ** Delete the named file. | |
4884 ** | |
4885 ** Note that Windows does not allow a file to be deleted if some other | |
4886 ** process has it open. Sometimes a virus scanner or indexing program | |
4887 ** will open a journal file shortly after it is created in order to do | |
4888 ** whatever it does. While this other process is holding the | |
4889 ** file open, we will be unable to delete it. To work around this | |
4890 ** problem, we delay 100 milliseconds and try to delete again. Up | |
4891 ** to MX_DELETION_ATTEMPTs deletion attempts are run before giving | |
4892 ** up and returning an error. | |
4893 */ | |
4894 static int winDelete( | |
4895 sqlite3_vfs *pVfs, /* Not used on win32 */ | |
4896 const char *zFilename, /* Name of file to delete */ | |
4897 int syncDir /* Not used on win32 */ | |
4898 ){ | |
4899 int cnt = 0; | |
4900 int rc; | |
4901 DWORD attr; | |
4902 DWORD lastErrno = 0; | |
4903 void *zConverted; | |
4904 UNUSED_PARAMETER(pVfs); | |
4905 UNUSED_PARAMETER(syncDir); | |
4906 | |
4907 SimulateIOError(return SQLITE_IOERR_DELETE); | |
4908 OSTRACE(("DELETE name=%s, syncDir=%d\n", zFilename, syncDir)); | |
4909 | |
4910 zConverted = winConvertFromUtf8Filename(zFilename); | |
4911 if( zConverted==0 ){ | |
4912 OSTRACE(("DELETE name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); | |
4913 return SQLITE_IOERR_NOMEM; | |
4914 } | |
4915 if( osIsNT() ){ | |
4916 do { | |
4917 #if SQLITE_OS_WINRT | |
4918 WIN32_FILE_ATTRIBUTE_DATA sAttrData; | |
4919 memset(&sAttrData, 0, sizeof(sAttrData)); | |
4920 if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, | |
4921 &sAttrData) ){ | |
4922 attr = sAttrData.dwFileAttributes; | |
4923 }else{ | |
4924 lastErrno = osGetLastError(); | |
4925 if( lastErrno==ERROR_FILE_NOT_FOUND | |
4926 || lastErrno==ERROR_PATH_NOT_FOUND ){ | |
4927 rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ | |
4928 }else{ | |
4929 rc = SQLITE_ERROR; | |
4930 } | |
4931 break; | |
4932 } | |
4933 #else | |
4934 attr = osGetFileAttributesW(zConverted); | |
4935 #endif | |
4936 if ( attr==INVALID_FILE_ATTRIBUTES ){ | |
4937 lastErrno = osGetLastError(); | |
4938 if( lastErrno==ERROR_FILE_NOT_FOUND | |
4939 || lastErrno==ERROR_PATH_NOT_FOUND ){ | |
4940 rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ | |
4941 }else{ | |
4942 rc = SQLITE_ERROR; | |
4943 } | |
4944 break; | |
4945 } | |
4946 if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ | |
4947 rc = SQLITE_ERROR; /* Files only. */ | |
4948 break; | |
4949 } | |
4950 if ( osDeleteFileW(zConverted) ){ | |
4951 rc = SQLITE_OK; /* Deleted OK. */ | |
4952 break; | |
4953 } | |
4954 if ( !winRetryIoerr(&cnt, &lastErrno) ){ | |
4955 rc = SQLITE_ERROR; /* No more retries. */ | |
4956 break; | |
4957 } | |
4958 } while(1); | |
4959 } | |
4960 #ifdef SQLITE_WIN32_HAS_ANSI | |
4961 else{ | |
4962 do { | |
4963 attr = osGetFileAttributesA(zConverted); | |
4964 if ( attr==INVALID_FILE_ATTRIBUTES ){ | |
4965 lastErrno = osGetLastError(); | |
4966 if( lastErrno==ERROR_FILE_NOT_FOUND | |
4967 || lastErrno==ERROR_PATH_NOT_FOUND ){ | |
4968 rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ | |
4969 }else{ | |
4970 rc = SQLITE_ERROR; | |
4971 } | |
4972 break; | |
4973 } | |
4974 if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ | |
4975 rc = SQLITE_ERROR; /* Files only. */ | |
4976 break; | |
4977 } | |
4978 if ( osDeleteFileA(zConverted) ){ | |
4979 rc = SQLITE_OK; /* Deleted OK. */ | |
4980 break; | |
4981 } | |
4982 if ( !winRetryIoerr(&cnt, &lastErrno) ){ | |
4983 rc = SQLITE_ERROR; /* No more retries. */ | |
4984 break; | |
4985 } | |
4986 } while(1); | |
4987 } | |
4988 #endif | |
4989 if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ | |
4990 rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); | |
4991 }else{ | |
4992 winLogIoerr(cnt, __LINE__); | |
4993 } | |
4994 sqlite3_free(zConverted); | |
4995 OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc))); | |
4996 return rc; | |
4997 } | |
4998 | |
4999 /* | |
5000 ** Check the existence and status of a file. | |
5001 */ | |
5002 static int winAccess( | |
5003 sqlite3_vfs *pVfs, /* Not used on win32 */ | |
5004 const char *zFilename, /* Name of file to check */ | |
5005 int flags, /* Type of test to make on this file */ | |
5006 int *pResOut /* OUT: Result */ | |
5007 ){ | |
5008 DWORD attr; | |
5009 int rc = 0; | |
5010 DWORD lastErrno = 0; | |
5011 void *zConverted; | |
5012 UNUSED_PARAMETER(pVfs); | |
5013 | |
5014 SimulateIOError( return SQLITE_IOERR_ACCESS; ); | |
5015 OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", | |
5016 zFilename, flags, pResOut)); | |
5017 | |
5018 zConverted = winConvertFromUtf8Filename(zFilename); | |
5019 if( zConverted==0 ){ | |
5020 OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); | |
5021 return SQLITE_IOERR_NOMEM; | |
5022 } | |
5023 if( osIsNT() ){ | |
5024 int cnt = 0; | |
5025 WIN32_FILE_ATTRIBUTE_DATA sAttrData; | |
5026 memset(&sAttrData, 0, sizeof(sAttrData)); | |
5027 while( !(rc = osGetFileAttributesExW((LPCWSTR)zConverted, | |
5028 GetFileExInfoStandard, | |
5029 &sAttrData)) && winRetryIoerr(&cnt, &lastErrno) ){} | |
5030 if( rc ){ | |
5031 /* For an SQLITE_ACCESS_EXISTS query, treat a zero-length file | |
5032 ** as if it does not exist. | |
5033 */ | |
5034 if( flags==SQLITE_ACCESS_EXISTS | |
5035 && sAttrData.nFileSizeHigh==0 | |
5036 && sAttrData.nFileSizeLow==0 ){ | |
5037 attr = INVALID_FILE_ATTRIBUTES; | |
5038 }else{ | |
5039 attr = sAttrData.dwFileAttributes; | |
5040 } | |
5041 }else{ | |
5042 winLogIoerr(cnt, __LINE__); | |
5043 if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){ | |
5044 sqlite3_free(zConverted); | |
5045 return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess", | |
5046 zFilename); | |
5047 }else{ | |
5048 attr = INVALID_FILE_ATTRIBUTES; | |
5049 } | |
5050 } | |
5051 } | |
5052 #ifdef SQLITE_WIN32_HAS_ANSI | |
5053 else{ | |
5054 attr = osGetFileAttributesA((char*)zConverted); | |
5055 } | |
5056 #endif | |
5057 sqlite3_free(zConverted); | |
5058 switch( flags ){ | |
5059 case SQLITE_ACCESS_READ: | |
5060 case SQLITE_ACCESS_EXISTS: | |
5061 rc = attr!=INVALID_FILE_ATTRIBUTES; | |
5062 break; | |
5063 case SQLITE_ACCESS_READWRITE: | |
5064 rc = attr!=INVALID_FILE_ATTRIBUTES && | |
5065 (attr & FILE_ATTRIBUTE_READONLY)==0; | |
5066 break; | |
5067 default: | |
5068 assert(!"Invalid flags argument"); | |
5069 } | |
5070 *pResOut = rc; | |
5071 OSTRACE(("ACCESS name=%s, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n", | |
5072 zFilename, pResOut, *pResOut)); | |
5073 return SQLITE_OK; | |
5074 } | |
5075 | |
5076 /* | |
5077 ** Returns non-zero if the specified path name starts with a drive letter | |
5078 ** followed by a colon character. | |
5079 */ | |
5080 static BOOL winIsDriveLetterAndColon( | |
5081 const char *zPathname | |
5082 ){ | |
5083 return ( sqlite3Isalpha(zPathname[0]) && zPathname[1]==':' ); | |
5084 } | |
5085 | |
5086 /* | |
5087 ** Returns non-zero if the specified path name should be used verbatim. If | |
5088 ** non-zero is returned from this function, the calling function must simply | |
5089 ** use the provided path name verbatim -OR- resolve it into a full path name | |
5090 ** using the GetFullPathName Win32 API function (if available). | |
5091 */ | |
5092 static BOOL winIsVerbatimPathname( | |
5093 const char *zPathname | |
5094 ){ | |
5095 /* | |
5096 ** If the path name starts with a forward slash or a backslash, it is either | |
5097 ** a legal UNC name, a volume relative path, or an absolute path name in the | |
5098 ** "Unix" format on Windows. There is no easy way to differentiate between | |
5099 ** the final two cases; therefore, we return the safer return value of TRUE | |
5100 ** so that callers of this function will simply use it verbatim. | |
5101 */ | |
5102 if ( winIsDirSep(zPathname[0]) ){ | |
5103 return TRUE; | |
5104 } | |
5105 | |
5106 /* | |
5107 ** If the path name starts with a letter and a colon it is either a volume | |
5108 ** relative path or an absolute path. Callers of this function must not | |
5109 ** attempt to treat it as a relative path name (i.e. they should simply use | |
5110 ** it verbatim). | |
5111 */ | |
5112 if ( winIsDriveLetterAndColon(zPathname) ){ | |
5113 return TRUE; | |
5114 } | |
5115 | |
5116 /* | |
5117 ** If we get to this point, the path name should almost certainly be a purely | |
5118 ** relative one (i.e. not a UNC name, not absolute, and not volume relative). | |
5119 */ | |
5120 return FALSE; | |
5121 } | |
5122 | |
5123 /* | |
5124 ** Turn a relative pathname into a full pathname. Write the full | |
5125 ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname | |
5126 ** bytes in size. | |
5127 */ | |
5128 static int winFullPathname( | |
5129 sqlite3_vfs *pVfs, /* Pointer to vfs object */ | |
5130 const char *zRelative, /* Possibly relative input path */ | |
5131 int nFull, /* Size of output buffer in bytes */ | |
5132 char *zFull /* Output buffer */ | |
5133 ){ | |
5134 | |
5135 #if defined(__CYGWIN__) | |
5136 SimulateIOError( return SQLITE_ERROR ); | |
5137 UNUSED_PARAMETER(nFull); | |
5138 assert( nFull>=pVfs->mxPathname ); | |
5139 if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ | |
5140 /* | |
5141 ** NOTE: We are dealing with a relative path name and the data | |
5142 ** directory has been set. Therefore, use it as the basis | |
5143 ** for converting the relative path name to an absolute | |
5144 ** one by prepending the data directory and a slash. | |
5145 */ | |
5146 char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); | |
5147 if( !zOut ){ | |
5148 return SQLITE_IOERR_NOMEM; | |
5149 } | |
5150 if( cygwin_conv_path( | |
5151 (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A) | | |
5152 CCP_RELATIVE, zRelative, zOut, pVfs->mxPathname+1)<0 ){ | |
5153 sqlite3_free(zOut); | |
5154 return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, | |
5155 "winFullPathname1", zRelative); | |
5156 }else{ | |
5157 char *zUtf8 = winConvertToUtf8Filename(zOut); | |
5158 if( !zUtf8 ){ | |
5159 sqlite3_free(zOut); | |
5160 return SQLITE_IOERR_NOMEM; | |
5161 } | |
5162 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", | |
5163 sqlite3_data_directory, winGetDirSep(), zUtf8); | |
5164 sqlite3_free(zUtf8); | |
5165 sqlite3_free(zOut); | |
5166 } | |
5167 }else{ | |
5168 char *zOut = sqlite3MallocZero( pVfs->mxPathname+1 ); | |
5169 if( !zOut ){ | |
5170 return SQLITE_IOERR_NOMEM; | |
5171 } | |
5172 if( cygwin_conv_path( | |
5173 (osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A), | |
5174 zRelative, zOut, pVfs->mxPathname+1)<0 ){ | |
5175 sqlite3_free(zOut); | |
5176 return winLogError(SQLITE_CANTOPEN_CONVPATH, (DWORD)errno, | |
5177 "winFullPathname2", zRelative); | |
5178 }else{ | |
5179 char *zUtf8 = winConvertToUtf8Filename(zOut); | |
5180 if( !zUtf8 ){ | |
5181 sqlite3_free(zOut); | |
5182 return SQLITE_IOERR_NOMEM; | |
5183 } | |
5184 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zUtf8); | |
5185 sqlite3_free(zUtf8); | |
5186 sqlite3_free(zOut); | |
5187 } | |
5188 } | |
5189 return SQLITE_OK; | |
5190 #endif | |
5191 | |
5192 #if (SQLITE_OS_WINCE || SQLITE_OS_WINRT) && !defined(__CYGWIN__) | |
5193 SimulateIOError( return SQLITE_ERROR ); | |
5194 /* WinCE has no concept of a relative pathname, or so I am told. */ | |
5195 /* WinRT has no way to convert a relative path to an absolute one. */ | |
5196 if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ | |
5197 /* | |
5198 ** NOTE: We are dealing with a relative path name and the data | |
5199 ** directory has been set. Therefore, use it as the basis | |
5200 ** for converting the relative path name to an absolute | |
5201 ** one by prepending the data directory and a backslash. | |
5202 */ | |
5203 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", | |
5204 sqlite3_data_directory, winGetDirSep(), zRelative); | |
5205 }else{ | |
5206 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zRelative); | |
5207 } | |
5208 return SQLITE_OK; | |
5209 #endif | |
5210 | |
5211 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && !defined(__CYGWIN__) | |
5212 DWORD nByte; | |
5213 void *zConverted; | |
5214 char *zOut; | |
5215 | |
5216 /* If this path name begins with "/X:", where "X" is any alphabetic | |
5217 ** character, discard the initial "/" from the pathname. | |
5218 */ | |
5219 if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){ | |
5220 zRelative++; | |
5221 } | |
5222 | |
5223 /* It's odd to simulate an io-error here, but really this is just | |
5224 ** using the io-error infrastructure to test that SQLite handles this | |
5225 ** function failing. This function could fail if, for example, the | |
5226 ** current working directory has been unlinked. | |
5227 */ | |
5228 SimulateIOError( return SQLITE_ERROR ); | |
5229 if ( sqlite3_data_directory && !winIsVerbatimPathname(zRelative) ){ | |
5230 /* | |
5231 ** NOTE: We are dealing with a relative path name and the data | |
5232 ** directory has been set. Therefore, use it as the basis | |
5233 ** for converting the relative path name to an absolute | |
5234 ** one by prepending the data directory and a backslash. | |
5235 */ | |
5236 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s%c%s", | |
5237 sqlite3_data_directory, winGetDirSep(), zRelative); | |
5238 return SQLITE_OK; | |
5239 } | |
5240 zConverted = winConvertFromUtf8Filename(zRelative); | |
5241 if( zConverted==0 ){ | |
5242 return SQLITE_IOERR_NOMEM; | |
5243 } | |
5244 if( osIsNT() ){ | |
5245 LPWSTR zTemp; | |
5246 nByte = osGetFullPathNameW((LPCWSTR)zConverted, 0, 0, 0); | |
5247 if( nByte==0 ){ | |
5248 sqlite3_free(zConverted); | |
5249 return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), | |
5250 "winFullPathname1", zRelative); | |
5251 } | |
5252 nByte += 3; | |
5253 zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); | |
5254 if( zTemp==0 ){ | |
5255 sqlite3_free(zConverted); | |
5256 return SQLITE_IOERR_NOMEM; | |
5257 } | |
5258 nByte = osGetFullPathNameW((LPCWSTR)zConverted, nByte, zTemp, 0); | |
5259 if( nByte==0 ){ | |
5260 sqlite3_free(zConverted); | |
5261 sqlite3_free(zTemp); | |
5262 return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), | |
5263 "winFullPathname2", zRelative); | |
5264 } | |
5265 sqlite3_free(zConverted); | |
5266 zOut = winUnicodeToUtf8(zTemp); | |
5267 sqlite3_free(zTemp); | |
5268 } | |
5269 #ifdef SQLITE_WIN32_HAS_ANSI | |
5270 else{ | |
5271 char *zTemp; | |
5272 nByte = osGetFullPathNameA((char*)zConverted, 0, 0, 0); | |
5273 if( nByte==0 ){ | |
5274 sqlite3_free(zConverted); | |
5275 return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), | |
5276 "winFullPathname3", zRelative); | |
5277 } | |
5278 nByte += 3; | |
5279 zTemp = sqlite3MallocZero( nByte*sizeof(zTemp[0]) ); | |
5280 if( zTemp==0 ){ | |
5281 sqlite3_free(zConverted); | |
5282 return SQLITE_IOERR_NOMEM; | |
5283 } | |
5284 nByte = osGetFullPathNameA((char*)zConverted, nByte, zTemp, 0); | |
5285 if( nByte==0 ){ | |
5286 sqlite3_free(zConverted); | |
5287 sqlite3_free(zTemp); | |
5288 return winLogError(SQLITE_CANTOPEN_FULLPATH, osGetLastError(), | |
5289 "winFullPathname4", zRelative); | |
5290 } | |
5291 sqlite3_free(zConverted); | |
5292 zOut = sqlite3_win32_mbcs_to_utf8(zTemp); | |
5293 sqlite3_free(zTemp); | |
5294 } | |
5295 #endif | |
5296 if( zOut ){ | |
5297 sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s", zOut); | |
5298 sqlite3_free(zOut); | |
5299 return SQLITE_OK; | |
5300 }else{ | |
5301 return SQLITE_IOERR_NOMEM; | |
5302 } | |
5303 #endif | |
5304 } | |
5305 | |
5306 #ifndef SQLITE_OMIT_LOAD_EXTENSION | |
5307 /* | |
5308 ** Interfaces for opening a shared library, finding entry points | |
5309 ** within the shared library, and closing the shared library. | |
5310 */ | |
5311 static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ | |
5312 HANDLE h; | |
5313 #if defined(__CYGWIN__) | |
5314 int nFull = pVfs->mxPathname+1; | |
5315 char *zFull = sqlite3MallocZero( nFull ); | |
5316 void *zConverted = 0; | |
5317 if( zFull==0 ){ | |
5318 OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); | |
5319 return 0; | |
5320 } | |
5321 if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ | |
5322 sqlite3_free(zFull); | |
5323 OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); | |
5324 return 0; | |
5325 } | |
5326 zConverted = winConvertFromUtf8Filename(zFull); | |
5327 sqlite3_free(zFull); | |
5328 #else | |
5329 void *zConverted = winConvertFromUtf8Filename(zFilename); | |
5330 UNUSED_PARAMETER(pVfs); | |
5331 #endif | |
5332 if( zConverted==0 ){ | |
5333 OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); | |
5334 return 0; | |
5335 } | |
5336 if( osIsNT() ){ | |
5337 #if SQLITE_OS_WINRT | |
5338 h = osLoadPackagedLibrary((LPCWSTR)zConverted, 0); | |
5339 #else | |
5340 h = osLoadLibraryW((LPCWSTR)zConverted); | |
5341 #endif | |
5342 } | |
5343 #ifdef SQLITE_WIN32_HAS_ANSI | |
5344 else{ | |
5345 h = osLoadLibraryA((char*)zConverted); | |
5346 } | |
5347 #endif | |
5348 OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)h)); | |
5349 sqlite3_free(zConverted); | |
5350 return (void*)h; | |
5351 } | |
5352 static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){ | |
5353 UNUSED_PARAMETER(pVfs); | |
5354 winGetLastErrorMsg(osGetLastError(), nBuf, zBufOut); | |
5355 } | |
5356 static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){ | |
5357 FARPROC proc; | |
5358 UNUSED_PARAMETER(pVfs); | |
5359 proc = osGetProcAddressA((HANDLE)pH, zSym); | |
5360 OSTRACE(("DLSYM handle=%p, symbol=%s, address=%p\n", | |
5361 (void*)pH, zSym, (void*)proc)); | |
5362 return (void(*)(void))proc; | |
5363 } | |
5364 static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){ | |
5365 UNUSED_PARAMETER(pVfs); | |
5366 osFreeLibrary((HANDLE)pHandle); | |
5367 OSTRACE(("DLCLOSE handle=%p\n", (void*)pHandle)); | |
5368 } | |
5369 #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */ | |
5370 #define winDlOpen 0 | |
5371 #define winDlError 0 | |
5372 #define winDlSym 0 | |
5373 #define winDlClose 0 | |
5374 #endif | |
5375 | |
5376 | |
5377 /* | |
5378 ** Write up to nBuf bytes of randomness into zBuf. | |
5379 */ | |
5380 static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
5381 int n = 0; | |
5382 UNUSED_PARAMETER(pVfs); | |
5383 #if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS) | |
5384 n = nBuf; | |
5385 memset(zBuf, 0, nBuf); | |
5386 #else | |
5387 if( sizeof(SYSTEMTIME)<=nBuf-n ){ | |
5388 SYSTEMTIME x; | |
5389 osGetSystemTime(&x); | |
5390 memcpy(&zBuf[n], &x, sizeof(x)); | |
5391 n += sizeof(x); | |
5392 } | |
5393 if( sizeof(DWORD)<=nBuf-n ){ | |
5394 DWORD pid = osGetCurrentProcessId(); | |
5395 memcpy(&zBuf[n], &pid, sizeof(pid)); | |
5396 n += sizeof(pid); | |
5397 } | |
5398 #if SQLITE_OS_WINRT | |
5399 if( sizeof(ULONGLONG)<=nBuf-n ){ | |
5400 ULONGLONG cnt = osGetTickCount64(); | |
5401 memcpy(&zBuf[n], &cnt, sizeof(cnt)); | |
5402 n += sizeof(cnt); | |
5403 } | |
5404 #else | |
5405 if( sizeof(DWORD)<=nBuf-n ){ | |
5406 DWORD cnt = osGetTickCount(); | |
5407 memcpy(&zBuf[n], &cnt, sizeof(cnt)); | |
5408 n += sizeof(cnt); | |
5409 } | |
5410 #endif | |
5411 if( sizeof(LARGE_INTEGER)<=nBuf-n ){ | |
5412 LARGE_INTEGER i; | |
5413 osQueryPerformanceCounter(&i); | |
5414 memcpy(&zBuf[n], &i, sizeof(i)); | |
5415 n += sizeof(i); | |
5416 } | |
5417 #if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID | |
5418 if( sizeof(UUID)<=nBuf-n ){ | |
5419 UUID id; | |
5420 memset(&id, 0, sizeof(UUID)); | |
5421 osUuidCreate(&id); | |
5422 memcpy(&zBuf[n], &id, sizeof(UUID)); | |
5423 n += sizeof(UUID); | |
5424 } | |
5425 if( sizeof(UUID)<=nBuf-n ){ | |
5426 UUID id; | |
5427 memset(&id, 0, sizeof(UUID)); | |
5428 osUuidCreateSequential(&id); | |
5429 memcpy(&zBuf[n], &id, sizeof(UUID)); | |
5430 n += sizeof(UUID); | |
5431 } | |
5432 #endif | |
5433 #endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */ | |
5434 return n; | |
5435 } | |
5436 | |
5437 | |
5438 /* | |
5439 ** Sleep for a little while. Return the amount of time slept. | |
5440 */ | |
5441 static int winSleep(sqlite3_vfs *pVfs, int microsec){ | |
5442 sqlite3_win32_sleep((microsec+999)/1000); | |
5443 UNUSED_PARAMETER(pVfs); | |
5444 return ((microsec+999)/1000)*1000; | |
5445 } | |
5446 | |
5447 /* | |
5448 ** The following variable, if set to a non-zero value, is interpreted as | |
5449 ** the number of seconds since 1970 and is used to set the result of | |
5450 ** sqlite3OsCurrentTime() during testing. | |
5451 */ | |
5452 #ifdef SQLITE_TEST | |
5453 int sqlite3_current_time = 0; /* Fake system time in seconds since 1970. */ | |
5454 #endif | |
5455 | |
5456 /* | |
5457 ** Find the current time (in Universal Coordinated Time). Write into *piNow | |
5458 ** the current time and date as a Julian Day number times 86_400_000. In | |
5459 ** other words, write into *piNow the number of milliseconds since the Julian | |
5460 ** epoch of noon in Greenwich on November 24, 4714 B.C according to the | |
5461 ** proleptic Gregorian calendar. | |
5462 ** | |
5463 ** On success, return SQLITE_OK. Return SQLITE_ERROR if the time and date | |
5464 ** cannot be found. | |
5465 */ | |
5466 static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){ | |
5467 /* FILETIME structure is a 64-bit value representing the number of | |
5468 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5). | |
5469 */ | |
5470 FILETIME ft; | |
5471 static const sqlite3_int64 winFiletimeEpoch = 23058135*(sqlite3_int64)8640000; | |
5472 #ifdef SQLITE_TEST | |
5473 static const sqlite3_int64 unixEpoch = 24405875*(sqlite3_int64)8640000; | |
5474 #endif | |
5475 /* 2^32 - to avoid use of LL and warnings in gcc */ | |
5476 static const sqlite3_int64 max32BitValue = | |
5477 (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + | |
5478 (sqlite3_int64)294967296; | |
5479 | |
5480 #if SQLITE_OS_WINCE | |
5481 SYSTEMTIME time; | |
5482 osGetSystemTime(&time); | |
5483 /* if SystemTimeToFileTime() fails, it returns zero. */ | |
5484 if (!osSystemTimeToFileTime(&time,&ft)){ | |
5485 return SQLITE_ERROR; | |
5486 } | |
5487 #else | |
5488 osGetSystemTimeAsFileTime( &ft ); | |
5489 #endif | |
5490 | |
5491 *piNow = winFiletimeEpoch + | |
5492 ((((sqlite3_int64)ft.dwHighDateTime)*max32BitValue) + | |
5493 (sqlite3_int64)ft.dwLowDateTime)/(sqlite3_int64)10000; | |
5494 | |
5495 #ifdef SQLITE_TEST | |
5496 if( sqlite3_current_time ){ | |
5497 *piNow = 1000*(sqlite3_int64)sqlite3_current_time + unixEpoch; | |
5498 } | |
5499 #endif | |
5500 UNUSED_PARAMETER(pVfs); | |
5501 return SQLITE_OK; | |
5502 } | |
5503 | |
5504 /* | |
5505 ** Find the current time (in Universal Coordinated Time). Write the | |
5506 ** current time and date as a Julian Day number into *prNow and | |
5507 ** return 0. Return 1 if the time and date cannot be found. | |
5508 */ | |
5509 static int winCurrentTime(sqlite3_vfs *pVfs, double *prNow){ | |
5510 int rc; | |
5511 sqlite3_int64 i; | |
5512 rc = winCurrentTimeInt64(pVfs, &i); | |
5513 if( !rc ){ | |
5514 *prNow = i/86400000.0; | |
5515 } | |
5516 return rc; | |
5517 } | |
5518 | |
5519 /* | |
5520 ** The idea is that this function works like a combination of | |
5521 ** GetLastError() and FormatMessage() on Windows (or errno and | |
5522 ** strerror_r() on Unix). After an error is returned by an OS | |
5523 ** function, SQLite calls this function with zBuf pointing to | |
5524 ** a buffer of nBuf bytes. The OS layer should populate the | |
5525 ** buffer with a nul-terminated UTF-8 encoded error message | |
5526 ** describing the last IO error to have occurred within the calling | |
5527 ** thread. | |
5528 ** | |
5529 ** If the error message is too large for the supplied buffer, | |
5530 ** it should be truncated. The return value of xGetLastError | |
5531 ** is zero if the error message fits in the buffer, or non-zero | |
5532 ** otherwise (if the message was truncated). If non-zero is returned, | |
5533 ** then it is not necessary to include the nul-terminator character | |
5534 ** in the output buffer. | |
5535 ** | |
5536 ** Not supplying an error message will have no adverse effect | |
5537 ** on SQLite. It is fine to have an implementation that never | |
5538 ** returns an error message: | |
5539 ** | |
5540 ** int xGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
5541 ** assert(zBuf[0]=='\0'); | |
5542 ** return 0; | |
5543 ** } | |
5544 ** | |
5545 ** However if an error message is supplied, it will be incorporated | |
5546 ** by sqlite into the error message available to the user using | |
5547 ** sqlite3_errmsg(), possibly making IO errors easier to debug. | |
5548 */ | |
5549 static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){ | |
5550 UNUSED_PARAMETER(pVfs); | |
5551 return winGetLastErrorMsg(osGetLastError(), nBuf, zBuf); | |
5552 } | |
5553 | |
5554 /* | |
5555 ** Initialize and deinitialize the operating system interface. | |
5556 */ | |
5557 int sqlite3_os_init(void){ | |
5558 static sqlite3_vfs winVfs = { | |
5559 3, /* iVersion */ | |
5560 sizeof(winFile), /* szOsFile */ | |
5561 SQLITE_WIN32_MAX_PATH_BYTES, /* mxPathname */ | |
5562 0, /* pNext */ | |
5563 "win32", /* zName */ | |
5564 0, /* pAppData */ | |
5565 winOpen, /* xOpen */ | |
5566 winDelete, /* xDelete */ | |
5567 winAccess, /* xAccess */ | |
5568 winFullPathname, /* xFullPathname */ | |
5569 winDlOpen, /* xDlOpen */ | |
5570 winDlError, /* xDlError */ | |
5571 winDlSym, /* xDlSym */ | |
5572 winDlClose, /* xDlClose */ | |
5573 winRandomness, /* xRandomness */ | |
5574 winSleep, /* xSleep */ | |
5575 winCurrentTime, /* xCurrentTime */ | |
5576 winGetLastError, /* xGetLastError */ | |
5577 winCurrentTimeInt64, /* xCurrentTimeInt64 */ | |
5578 winSetSystemCall, /* xSetSystemCall */ | |
5579 winGetSystemCall, /* xGetSystemCall */ | |
5580 winNextSystemCall, /* xNextSystemCall */ | |
5581 }; | |
5582 #if defined(SQLITE_WIN32_HAS_WIDE) | |
5583 static sqlite3_vfs winLongPathVfs = { | |
5584 3, /* iVersion */ | |
5585 sizeof(winFile), /* szOsFile */ | |
5586 SQLITE_WINNT_MAX_PATH_BYTES, /* mxPathname */ | |
5587 0, /* pNext */ | |
5588 "win32-longpath", /* zName */ | |
5589 0, /* pAppData */ | |
5590 winOpen, /* xOpen */ | |
5591 winDelete, /* xDelete */ | |
5592 winAccess, /* xAccess */ | |
5593 winFullPathname, /* xFullPathname */ | |
5594 winDlOpen, /* xDlOpen */ | |
5595 winDlError, /* xDlError */ | |
5596 winDlSym, /* xDlSym */ | |
5597 winDlClose, /* xDlClose */ | |
5598 winRandomness, /* xRandomness */ | |
5599 winSleep, /* xSleep */ | |
5600 winCurrentTime, /* xCurrentTime */ | |
5601 winGetLastError, /* xGetLastError */ | |
5602 winCurrentTimeInt64, /* xCurrentTimeInt64 */ | |
5603 winSetSystemCall, /* xSetSystemCall */ | |
5604 winGetSystemCall, /* xGetSystemCall */ | |
5605 winNextSystemCall, /* xNextSystemCall */ | |
5606 }; | |
5607 #endif | |
5608 | |
5609 /* Double-check that the aSyscall[] array has been constructed | |
5610 ** correctly. See ticket [bb3a86e890c8e96ab] */ | |
5611 assert( ArraySize(aSyscall)==80 ); | |
5612 | |
5613 /* get memory map allocation granularity */ | |
5614 memset(&winSysInfo, 0, sizeof(SYSTEM_INFO)); | |
5615 #if SQLITE_OS_WINRT | |
5616 osGetNativeSystemInfo(&winSysInfo); | |
5617 #else | |
5618 osGetSystemInfo(&winSysInfo); | |
5619 #endif | |
5620 assert( winSysInfo.dwAllocationGranularity>0 ); | |
5621 assert( winSysInfo.dwPageSize>0 ); | |
5622 | |
5623 sqlite3_vfs_register(&winVfs, 1); | |
5624 | |
5625 #if defined(SQLITE_WIN32_HAS_WIDE) | |
5626 sqlite3_vfs_register(&winLongPathVfs, 0); | |
5627 #endif | |
5628 | |
5629 return SQLITE_OK; | |
5630 } | |
5631 | |
5632 int sqlite3_os_end(void){ | |
5633 #if SQLITE_OS_WINRT | |
5634 if( sleepObj!=NULL ){ | |
5635 osCloseHandle(sleepObj); | |
5636 sleepObj = NULL; | |
5637 } | |
5638 #endif | |
5639 return SQLITE_OK; | |
5640 } | |
5641 | |
5642 #endif /* SQLITE_OS_WIN */ | |
OLD | NEW |