Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: third_party/sqlite/src/os_win.c

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

Powered by Google App Engine
This is Rietveld 408576698