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