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