blob: 044618624e527f49dc7a3abe90ae0e6c7f295f77 [file] [log] [blame]
drhbbd42a62004-05-22 17:41:58 +00001/*
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*/
drhbbd42a62004-05-22 17:41:58 +000015#include "sqliteInt.h"
drheb206252004-10-01 02:00:31 +000016#include "os.h"
17#if OS_WIN /* This file is used for windows only */
drhbbd42a62004-05-22 17:41:58 +000018
19#include <winbase.h>
20
drh09bf0e82005-03-21 00:36:08 +000021#ifdef __CYGWIN__
22# include <sys/cygwin.h>
23#endif
24
drhbbd42a62004-05-22 17:41:58 +000025/*
26** Macros used to determine whether or not to use threads.
27*/
28#if defined(THREADSAFE) && THREADSAFE
29# define SQLITE_W32_THREADS 1
30#endif
31
32/*
33** Include code that is common to all os_*.c files
34*/
35#include "os_common.h"
36
37/*
drhcc78fea2006-01-06 16:17:05 +000038** Determine if we are dealing with WindowsCE - which has a much
39** reduced API.
40*/
41#if defined(_WIN32_WCE)
42# define OS_WINCE 1
43#else
44# define OS_WINCE 0
45#endif
46
47/*
drh72aead82006-01-23 15:54:25 +000048** WinCE lacks native support for file locking so we have to fake it
49** with some code of our own.
50*/
51#if OS_WINCE
52typedef struct winceLock {
53 int nReaders; /* Number of reader locks obtained */
54 BOOL bPending; /* Indicates a pending lock has been obtained */
55 BOOL bReserved; /* Indicates a reserved lock has been obtained */
56 BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
57} winceLock;
58#endif
59
60/*
drh054889e2005-11-30 03:20:31 +000061** The winFile structure is a subclass of OsFile specific to the win32
62** portability layer.
drh9cbe6352005-11-29 03:13:21 +000063*/
drh054889e2005-11-30 03:20:31 +000064typedef struct winFile winFile;
65struct winFile {
66 IoMethod const *pMethod;/* Must be first */
drh9cbe6352005-11-29 03:13:21 +000067 HANDLE h; /* Handle for accessing the file */
68 unsigned char locktype; /* Type of lock currently held on this file */
69 short sharedLockByte; /* Randomly chosen byte used as a shared lock */
drhcc78fea2006-01-06 16:17:05 +000070#if OS_WINCE
drh72aead82006-01-23 15:54:25 +000071 WCHAR *zDeleteOnClose; /* Name of file to delete when closing */
72 HANDLE hMutex; /* Mutex used to control access to shared lock */
73 HANDLE hShared; /* Shared memory segment used for locking */
74 winceLock local; /* Locks obtained by this instance of winFile */
75 winceLock *shared; /* Global shared lock memory for the file */
drhcc78fea2006-01-06 16:17:05 +000076#endif
drh9cbe6352005-11-29 03:13:21 +000077};
78
79
drh9cbe6352005-11-29 03:13:21 +000080/*
drh0ccebe72005-06-07 22:22:50 +000081** Do not include any of the File I/O interface procedures if the
82** SQLITE_OMIT_DISKIO macro is defined (indicating that there database
83** will be in-memory only)
84*/
85#ifndef SQLITE_OMIT_DISKIO
86
87/*
drhc0929982005-09-05 19:08:29 +000088** The following variable is (normally) set once and never changes
89** thereafter. It records whether the operating system is Win95
90** or WinNT.
91**
92** 0: Operating system unknown.
93** 1: Operating system is Win95.
94** 2: Operating system is WinNT.
95**
96** In order to facilitate testing on a WinNT system, the test fixture
97** can manually set this value to 1 to emulate Win98 behavior.
98*/
99int sqlite3_os_type = 0;
100
101/*
drhcc78fea2006-01-06 16:17:05 +0000102** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
103** or WinCE. Return false (zero) for Win95, Win98, or WinME.
drhc0929982005-09-05 19:08:29 +0000104**
105** Here is an interesting observation: Win95, Win98, and WinME lack
106** the LockFileEx() API. But we can still statically link against that
107** API as long as we don't call it win running Win95/98/ME. A call to
108** this routine is used to determine if the host is Win95/98/ME or
109** WinNT/2K/XP so that we will know whether or not we can safely call
110** the LockFileEx() API.
111*/
drhcc78fea2006-01-06 16:17:05 +0000112#if OS_WINCE
113# define isNT() (1)
114#else
115 static int isNT(void){
116 if( sqlite3_os_type==0 ){
117 OSVERSIONINFO sInfo;
118 sInfo.dwOSVersionInfoSize = sizeof(sInfo);
119 GetVersionEx(&sInfo);
120 sqlite3_os_type = sInfo.dwPlatformId==VER_PLATFORM_WIN32_NT ? 2 : 1;
121 }
122 return sqlite3_os_type==2;
drhc0929982005-09-05 19:08:29 +0000123 }
drhcc78fea2006-01-06 16:17:05 +0000124#endif /* OS_WINCE */
125
drhc0929982005-09-05 19:08:29 +0000126/*
127** Convert a UTF-8 string to UTF-32. Space to hold the returned string
128** is obtained from sqliteMalloc.
129*/
130static WCHAR *utf8ToUnicode(const char *zFilename){
131 int nByte;
132 WCHAR *zWideFilename;
133
134 if( !isNT() ){
135 return 0;
136 }
137 nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0)*sizeof(WCHAR);
drhd81bd4e2005-09-05 20:06:49 +0000138 zWideFilename = sqliteMalloc( nByte*sizeof(zWideFilename[0]) );
drhc0929982005-09-05 19:08:29 +0000139 if( zWideFilename==0 ){
140 return 0;
141 }
142 nByte = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nByte);
143 if( nByte==0 ){
144 sqliteFree(zWideFilename);
145 zWideFilename = 0;
146 }
147 return zWideFilename;
148}
149
150/*
151** Convert UTF-32 to UTF-8. Space to hold the returned string is
152** obtained from sqliteMalloc().
153*/
154static char *unicodeToUtf8(const WCHAR *zWideFilename){
155 int nByte;
156 char *zFilename;
157
158 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
159 zFilename = sqliteMalloc( nByte );
160 if( zFilename==0 ){
161 return 0;
162 }
163 nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
164 0, 0);
165 if( nByte == 0 ){
166 sqliteFree(zFilename);
167 zFilename = 0;
168 }
169 return zFilename;
170}
171
drh72aead82006-01-23 15:54:25 +0000172#if OS_WINCE
173/*************************************************************************
174** This section contains code for WinCE only.
175*/
176/*
177** WindowsCE does not have a localtime() function. So create a
178** substitute.
179*/
180#include <time.h>
181struct tm *__cdecl localtime(const time_t *t)
182{
183 static struct tm y;
184 FILETIME uTm, lTm;
185 SYSTEMTIME pTm;
186 i64 t64;
187 t64 = *t;
188 t64 = (t64 + 11644473600)*10000000;
189 uTm.dwLowDateTime = t64 & 0xFFFFFFFF;
190 uTm.dwHighDateTime= t64 >> 32;
191 FileTimeToLocalFileTime(&uTm,&lTm);
192 FileTimeToSystemTime(&lTm,&pTm);
193 y.tm_year = pTm.wYear - 1900;
194 y.tm_mon = pTm.wMonth - 1;
195 y.tm_wday = pTm.wDayOfWeek;
196 y.tm_mday = pTm.wDay;
197 y.tm_hour = pTm.wHour;
198 y.tm_min = pTm.wMinute;
199 y.tm_sec = pTm.wSecond;
200 return &y;
201}
202
203/* This will never be called, but defined to make the code compile */
204#define GetTempPathA(a,b)
205
206#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
207#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
208#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
209
210#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-offsetof(winFile,h)]
211
212/*
213** Acquire a lock on the handle h
214*/
215static void winceMutexAcquire(HANDLE h){
216 DWORD dwErr;
217 do {
218 dwErr = WaitForSingleObject(h, INFINITE);
219 } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
220}
221/*
222** Release a lock acquired by winceMutexAcquire()
223*/
224#define winceMutexRelease(h) ReleaseMutex(h)
225
226/*
227** Create the mutex and shared memory used for locking in the file
228** descriptor pFile
229*/
230static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
231 WCHAR *zTok;
232 WCHAR *zName = utf8ToUnicode(zFilename);
233 BOOL bInit = TRUE;
234
235 /* Initialize the local lockdata */
236 ZeroMemory(&pFile->local, sizeof(pFile->local));
237
238 /* Replace the backslashes from the filename and lowercase it
239 ** to derive a mutex name. */
240 zTok = CharLowerW(zName);
241 for (;*zTok;zTok++){
242 if (*zTok == '\\') *zTok = '_';
243 }
244
245 /* Create/open the named mutex */
246 pFile->hMutex = CreateMutexW(NULL, FALSE, zName);
247 if (!pFile->hMutex){
248 sqliteFree(zName);
249 return FALSE;
250 }
251
252 /* Acquire the mutex before continuing */
253 winceMutexAcquire(pFile->hMutex);
254
255 /* Since the names of named mutexes, semaphores, file mappings etc are
256 ** case-sensitive, take advantage of that by uppercasing the mutex name
257 ** and using that as the shared filemapping name.
258 */
259 CharUpperW(zName);
260 pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
261 PAGE_READWRITE, 0, sizeof(winceLock),
262 zName);
263
264 /* Set a flag that indicates we're the first to create the memory so it
265 ** must be zero-initialized */
266 if (GetLastError() == ERROR_ALREADY_EXISTS){
267 bInit = FALSE;
268 }
269
270 sqliteFree(zName);
271
272 /* If we succeeded in making the shared memory handle, map it. */
273 if (pFile->hShared){
274 pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared,
275 FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
276 /* If mapping failed, close the shared memory handle and erase it */
277 if (!pFile->shared){
278 CloseHandle(pFile->hShared);
279 pFile->hShared = NULL;
280 }
281 }
282
283 /* If shared memory could not be created, then close the mutex and fail */
284 if (pFile->hShared == NULL){
285 winceMutexRelease(pFile->hMutex);
286 CloseHandle(pFile->hMutex);
287 pFile->hMutex = NULL;
288 return FALSE;
289 }
290
291 /* Initialize the shared memory if we're supposed to */
292 if (bInit) {
293 ZeroMemory(pFile->shared, sizeof(winceLock));
294 }
295
296 winceMutexRelease(pFile->hMutex);
297 return TRUE;
298}
299
300/*
301** Destroy the part of winFile that deals with wince locks
302*/
303static void winceDestroyLock(winFile *pFile){
304 if (pFile->hMutex){
305 /* Acquire the mutex */
306 winceMutexAcquire(pFile->hMutex);
307
308 /* The following blocks should probably assert in debug mode, but they
309 are to cleanup in case any locks remained open */
310 if (pFile->local.nReaders){
311 pFile->shared->nReaders --;
312 }
313 if (pFile->local.bReserved){
314 pFile->shared->bReserved = FALSE;
315 }
316 if (pFile->local.bPending){
317 pFile->shared->bPending = FALSE;
318 }
319 if (pFile->local.bExclusive){
320 pFile->shared->bExclusive = FALSE;
321 }
322
323 /* De-reference and close our copy of the shared memory handle */
324 UnmapViewOfFile(pFile->shared);
325 CloseHandle(pFile->hShared);
326
327 /* Done with the mutex */
328 winceMutexRelease(pFile->hMutex);
329 CloseHandle(pFile->hMutex);
330 pFile->hMutex = NULL;
331 }
332}
333
334/*
335** An implementation of the LockFile() API of windows for wince
336*/
337static BOOL winceLockFile(
338 HANDLE *phFile,
339 DWORD dwFileOffsetLow,
340 DWORD dwFileOffsetHigh,
341 DWORD nNumberOfBytesToLockLow,
342 DWORD nNumberOfBytesToLockHigh
343){
344 winFile *pFile = HANDLE_TO_WINFILE(phFile);
345 BOOL bReturn = FALSE;
346
347 if (!pFile->hMutex) return TRUE;
348 winceMutexAcquire(pFile->hMutex);
349
350 /* Wanting an exclusive lock? */
351 if (dwFileOffsetLow == SHARED_FIRST
352 && nNumberOfBytesToLockLow == SHARED_SIZE){
353 if (pFile->shared->nReaders == 0 && pFile->shared->bExclusive == 0){
354 pFile->shared->bExclusive = TRUE;
355 pFile->local.bExclusive = TRUE;
356 bReturn = TRUE;
357 }
358 }
359
360 /* Want a read-only lock? */
361 else if ((dwFileOffsetLow >= SHARED_FIRST &&
362 dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE) &&
363 nNumberOfBytesToLockLow == 1){
364 if (pFile->shared->bExclusive == 0){
365 pFile->local.nReaders ++;
366 if (pFile->local.nReaders == 1){
367 pFile->shared->nReaders ++;
368 }
369 bReturn = TRUE;
370 }
371 }
372
373 /* Want a pending lock? */
374 else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToLockLow == 1){
375 /* If no pending lock has been acquired, then acquire it */
376 if (pFile->shared->bPending == 0) {
377 pFile->shared->bPending = TRUE;
378 pFile->local.bPending = TRUE;
379 bReturn = TRUE;
380 }
381 }
382 /* Want a reserved lock? */
383 else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
384 if (pFile->shared->bReserved == 0) {
385 pFile->shared->bReserved = TRUE;
386 pFile->local.bReserved = TRUE;
387 bReturn = TRUE;
388 }
389 }
390
391 winceMutexRelease(pFile->hMutex);
392 return bReturn;
393}
394
395/*
396** An implementation of the UnlockFile API of windows for wince
397*/
398static BOOL winceUnlockFile(
399 HANDLE *phFile,
400 DWORD dwFileOffsetLow,
401 DWORD dwFileOffsetHigh,
402 DWORD nNumberOfBytesToUnlockLow,
403 DWORD nNumberOfBytesToUnlockHigh
404){
405 winFile *pFile = HANDLE_TO_WINFILE(phFile);
406 BOOL bReturn = FALSE;
407
408 if (!pFile->hMutex) return TRUE;
409 winceMutexAcquire(pFile->hMutex);
410
411 /* Releasing a reader lock or an exclusive lock */
412 if (dwFileOffsetLow >= SHARED_FIRST &&
413 dwFileOffsetLow < SHARED_FIRST + SHARED_SIZE){
414 /* Did we have an exclusive lock? */
415 if (pFile->local.bExclusive){
416 pFile->local.bExclusive = FALSE;
417 pFile->shared->bExclusive = FALSE;
418 bReturn = TRUE;
419 }
420
421 /* Did we just have a reader lock? */
422 else if (pFile->local.nReaders){
423 pFile->local.nReaders --;
424 if (pFile->local.nReaders == 0)
425 {
426 pFile->shared->nReaders --;
427 }
428 bReturn = TRUE;
429 }
430 }
431
432 /* Releasing a pending lock */
433 else if (dwFileOffsetLow == PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
434 if (pFile->local.bPending){
435 pFile->local.bPending = FALSE;
436 pFile->shared->bPending = FALSE;
437 bReturn = TRUE;
438 }
439 }
440 /* Releasing a reserved lock */
441 else if (dwFileOffsetLow == RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
442 if (pFile->local.bReserved) {
443 pFile->local.bReserved = FALSE;
444 pFile->shared->bReserved = FALSE;
445 bReturn = TRUE;
446 }
447 }
448
449 winceMutexRelease(pFile->hMutex);
450 return bReturn;
451}
452
453/*
454** An implementation of the LockFileEx() API of windows for wince
455*/
456static BOOL winceLockFileEx(
457 HANDLE *phFile,
458 DWORD dwFlags,
459 DWORD dwReserved,
460 DWORD nNumberOfBytesToLockLow,
461 DWORD nNumberOfBytesToLockHigh,
462 LPOVERLAPPED lpOverlapped
463){
464 /* If the caller wants a shared read lock, forward this call
465 ** to winceLockFile */
466 if (lpOverlapped->Offset == SHARED_FIRST &&
467 dwFlags == 1 &&
468 nNumberOfBytesToLockLow == SHARED_SIZE){
469 return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
470 }
471 return FALSE;
472}
473/*
474** End of the special code for wince
475*****************************************************************************/
476#endif /* OS_WINCE */
drhc0929982005-09-05 19:08:29 +0000477
478/*
drhbbd42a62004-05-22 17:41:58 +0000479** Delete the named file
480*/
drh66560ad2006-01-06 14:32:19 +0000481int sqlite3WinDelete(const char *zFilename){
drhc0929982005-09-05 19:08:29 +0000482 WCHAR *zWide = utf8ToUnicode(zFilename);
483 if( zWide ){
484 DeleteFileW(zWide);
485 sqliteFree(zWide);
486 }else{
drhcc78fea2006-01-06 16:17:05 +0000487#if OS_WINCE
488 return SQLITE_NOMEM;
489#else
drhc0929982005-09-05 19:08:29 +0000490 DeleteFileA(zFilename);
drhcc78fea2006-01-06 16:17:05 +0000491#endif
drhc0929982005-09-05 19:08:29 +0000492 }
drh51c6d962004-06-06 00:42:25 +0000493 TRACE2("DELETE \"%s\"\n", zFilename);
drhbbd42a62004-05-22 17:41:58 +0000494 return SQLITE_OK;
495}
496
497/*
498** Return TRUE if the named file exists.
499*/
drh66560ad2006-01-06 14:32:19 +0000500int sqlite3WinFileExists(const char *zFilename){
drhc0929982005-09-05 19:08:29 +0000501 int exists = 0;
502 WCHAR *zWide = utf8ToUnicode(zFilename);
503 if( zWide ){
504 exists = GetFileAttributesW(zWide) != 0xffffffff;
505 sqliteFree(zWide);
506 }else{
drhcc78fea2006-01-06 16:17:05 +0000507#if OS_WINCE
508 return SQLITE_NOMEM;
509#else
drhc0929982005-09-05 19:08:29 +0000510 exists = GetFileAttributesA(zFilename) != 0xffffffff;
drhcc78fea2006-01-06 16:17:05 +0000511#endif
drhc0929982005-09-05 19:08:29 +0000512 }
513 return exists;
drhbbd42a62004-05-22 17:41:58 +0000514}
515
drh054889e2005-11-30 03:20:31 +0000516/* Forward declaration */
517int allocateWinFile(winFile *pInit, OsFile **pId);
drh9cbe6352005-11-29 03:13:21 +0000518
drhbbd42a62004-05-22 17:41:58 +0000519/*
520** Attempt to open a file for both reading and writing. If that
521** fails, try opening it read-only. If the file does not exist,
522** try to create it.
523**
524** On success, a handle for the open file is written to *id
525** and *pReadonly is set to 0 if the file was opened for reading and
526** writing or 1 if the file was opened read-only. The function returns
527** SQLITE_OK.
528**
529** On failure, the function returns SQLITE_CANTOPEN and leaves
530** *id and *pReadonly unchanged.
531*/
drh66560ad2006-01-06 14:32:19 +0000532int sqlite3WinOpenReadWrite(
drhbbd42a62004-05-22 17:41:58 +0000533 const char *zFilename,
drh9cbe6352005-11-29 03:13:21 +0000534 OsFile **pId,
drhbbd42a62004-05-22 17:41:58 +0000535 int *pReadonly
536){
drh054889e2005-11-30 03:20:31 +0000537 winFile f;
drhda71ce12004-06-21 18:14:45 +0000538 HANDLE h;
drhc0929982005-09-05 19:08:29 +0000539 WCHAR *zWide = utf8ToUnicode(zFilename);
drh9cbe6352005-11-29 03:13:21 +0000540 assert( *pId==0 );
drhc0929982005-09-05 19:08:29 +0000541 if( zWide ){
542 h = CreateFileW(zWide,
543 GENERIC_READ | GENERIC_WRITE,
544 FILE_SHARE_READ | FILE_SHARE_WRITE,
drhbbd42a62004-05-22 17:41:58 +0000545 NULL,
546 OPEN_ALWAYS,
547 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
548 NULL
549 );
550 if( h==INVALID_HANDLE_VALUE ){
drhc0929982005-09-05 19:08:29 +0000551 h = CreateFileW(zWide,
552 GENERIC_READ,
553 FILE_SHARE_READ,
554 NULL,
555 OPEN_ALWAYS,
556 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
557 NULL
558 );
559 if( h==INVALID_HANDLE_VALUE ){
560 sqliteFree(zWide);
561 return SQLITE_CANTOPEN;
562 }
563 *pReadonly = 1;
564 }else{
565 *pReadonly = 0;
drhbbd42a62004-05-22 17:41:58 +0000566 }
drh72aead82006-01-23 15:54:25 +0000567#if OS_WINCE
568 if (!winceCreateLock(zFilename, &f)){
569 CloseHandle(h);
570 sqliteFree(zWide);
571 return SQLITE_CANTOPEN;
572 }
573#endif
drhc0929982005-09-05 19:08:29 +0000574 sqliteFree(zWide);
drhbbd42a62004-05-22 17:41:58 +0000575 }else{
drhcc78fea2006-01-06 16:17:05 +0000576#if OS_WINCE
577 return SQLITE_NOMEM;
578#else
drhc0929982005-09-05 19:08:29 +0000579 h = CreateFileA(zFilename,
580 GENERIC_READ | GENERIC_WRITE,
581 FILE_SHARE_READ | FILE_SHARE_WRITE,
582 NULL,
583 OPEN_ALWAYS,
584 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
585 NULL
586 );
587 if( h==INVALID_HANDLE_VALUE ){
588 h = CreateFileA(zFilename,
589 GENERIC_READ,
590 FILE_SHARE_READ,
591 NULL,
592 OPEN_ALWAYS,
593 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
594 NULL
595 );
596 if( h==INVALID_HANDLE_VALUE ){
597 return SQLITE_CANTOPEN;
598 }
599 *pReadonly = 1;
600 }else{
601 *pReadonly = 0;
602 }
drhcc78fea2006-01-06 16:17:05 +0000603#endif /* OS_WINCE */
drhbbd42a62004-05-22 17:41:58 +0000604 }
drh9cbe6352005-11-29 03:13:21 +0000605 f.h = h;
drh4bddfd22006-01-07 18:14:48 +0000606#if OS_WINCE
607 f.zDeleteOnClose = 0;
608#endif
drh51c6d962004-06-06 00:42:25 +0000609 TRACE3("OPEN R/W %d \"%s\"\n", h, zFilename);
drh054889e2005-11-30 03:20:31 +0000610 return allocateWinFile(&f, pId);
drhbbd42a62004-05-22 17:41:58 +0000611}
612
613
614/*
615** Attempt to open a new file for exclusive access by this process.
616** The file will be opened for both reading and writing. To avoid
617** a potential security problem, we do not allow the file to have
618** previously existed. Nor do we allow the file to be a symbolic
619** link.
620**
621** If delFlag is true, then make arrangements to automatically delete
622** the file when it is closed.
623**
624** On success, write the file handle into *id and return SQLITE_OK.
625**
626** On failure, return SQLITE_CANTOPEN.
627*/
drh66560ad2006-01-06 14:32:19 +0000628int sqlite3WinOpenExclusive(const char *zFilename, OsFile **pId, int delFlag){
drh054889e2005-11-30 03:20:31 +0000629 winFile f;
drhbbd42a62004-05-22 17:41:58 +0000630 HANDLE h;
631 int fileflags;
drhc0929982005-09-05 19:08:29 +0000632 WCHAR *zWide = utf8ToUnicode(zFilename);
drh9cbe6352005-11-29 03:13:21 +0000633 assert( *pId == 0 );
drhcc78fea2006-01-06 16:17:05 +0000634 fileflags = FILE_FLAG_RANDOM_ACCESS;
635#if !OS_WINCE
drhbbd42a62004-05-22 17:41:58 +0000636 if( delFlag ){
drhcc78fea2006-01-06 16:17:05 +0000637 fileflags |= FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE;
drhbbd42a62004-05-22 17:41:58 +0000638 }
drhcc78fea2006-01-06 16:17:05 +0000639#endif
drhc0929982005-09-05 19:08:29 +0000640 if( zWide ){
641 h = CreateFileW(zWide,
642 GENERIC_READ | GENERIC_WRITE,
643 0,
644 NULL,
645 CREATE_ALWAYS,
646 fileflags,
647 NULL
648 );
649 sqliteFree(zWide);
650 }else{
drhcc78fea2006-01-06 16:17:05 +0000651#if OS_WINCE
652 return SQLITE_NOMEM;
653#else
drhc0929982005-09-05 19:08:29 +0000654 h = CreateFileA(zFilename,
655 GENERIC_READ | GENERIC_WRITE,
656 0,
657 NULL,
658 CREATE_ALWAYS,
659 fileflags,
660 NULL
661 );
drhcc78fea2006-01-06 16:17:05 +0000662#endif /* OS_WINCE */
drhc0929982005-09-05 19:08:29 +0000663 }
drhbbd42a62004-05-22 17:41:58 +0000664 if( h==INVALID_HANDLE_VALUE ){
665 return SQLITE_CANTOPEN;
666 }
drh9cbe6352005-11-29 03:13:21 +0000667 f.h = h;
drhcc78fea2006-01-06 16:17:05 +0000668#if OS_WINCE
drh9e9fe6f2006-01-06 21:09:01 +0000669 f.zDeleteOnClose = delFlag ? utf8ToUnicode(zFilename) : 0;
drh36a50052006-01-23 22:15:07 +0000670 f.hMutex = NULL;
drhcc78fea2006-01-06 16:17:05 +0000671#endif
drh51c6d962004-06-06 00:42:25 +0000672 TRACE3("OPEN EX %d \"%s\"\n", h, zFilename);
drh054889e2005-11-30 03:20:31 +0000673 return allocateWinFile(&f, pId);
drhbbd42a62004-05-22 17:41:58 +0000674}
675
676/*
677** Attempt to open a new file for read-only access.
678**
679** On success, write the file handle into *id and return SQLITE_OK.
680**
681** On failure, return SQLITE_CANTOPEN.
682*/
drh66560ad2006-01-06 14:32:19 +0000683int sqlite3WinOpenReadOnly(const char *zFilename, OsFile **pId){
drh054889e2005-11-30 03:20:31 +0000684 winFile f;
drhda71ce12004-06-21 18:14:45 +0000685 HANDLE h;
drhc0929982005-09-05 19:08:29 +0000686 WCHAR *zWide = utf8ToUnicode(zFilename);
drh9cbe6352005-11-29 03:13:21 +0000687 assert( *pId==0 );
drhc0929982005-09-05 19:08:29 +0000688 if( zWide ){
689 h = CreateFileW(zWide,
690 GENERIC_READ,
691 0,
692 NULL,
693 OPEN_EXISTING,
694 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
695 NULL
696 );
697 sqliteFree(zWide);
698 }else{
drhcc78fea2006-01-06 16:17:05 +0000699#if OS_WINCE
700 return SQLITE_NOMEM;
701#else
drhc0929982005-09-05 19:08:29 +0000702 h = CreateFileA(zFilename,
703 GENERIC_READ,
704 0,
705 NULL,
706 OPEN_EXISTING,
707 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
708 NULL
709 );
drhcc78fea2006-01-06 16:17:05 +0000710#endif
drhc0929982005-09-05 19:08:29 +0000711 }
drhbbd42a62004-05-22 17:41:58 +0000712 if( h==INVALID_HANDLE_VALUE ){
713 return SQLITE_CANTOPEN;
714 }
drh9cbe6352005-11-29 03:13:21 +0000715 f.h = h;
drh4bddfd22006-01-07 18:14:48 +0000716#if OS_WINCE
717 f.zDeleteOnClose = 0;
drh36a50052006-01-23 22:15:07 +0000718 f.hMutex = NULL;
drh4bddfd22006-01-07 18:14:48 +0000719#endif
drh51c6d962004-06-06 00:42:25 +0000720 TRACE3("OPEN RO %d \"%s\"\n", h, zFilename);
drh054889e2005-11-30 03:20:31 +0000721 return allocateWinFile(&f, pId);
drhbbd42a62004-05-22 17:41:58 +0000722}
723
724/*
725** Attempt to open a file descriptor for the directory that contains a
726** file. This file descriptor can be used to fsync() the directory
727** in order to make sure the creation of a new file is actually written
728** to disk.
729**
730** This routine is only meaningful for Unix. It is a no-op under
731** windows since windows does not support hard links.
732**
733** On success, a handle for a previously open file is at *id is
734** updated with the new directory file descriptor and SQLITE_OK is
735** returned.
736**
737** On failure, the function returns SQLITE_CANTOPEN and leaves
738** *id unchanged.
739*/
drh9c06c952005-11-26 00:25:00 +0000740static int winOpenDirectory(
drh054889e2005-11-30 03:20:31 +0000741 OsFile *id,
742 const char *zDirname
drhbbd42a62004-05-22 17:41:58 +0000743){
744 return SQLITE_OK;
745}
746
747/*
drh3d2efea2004-08-28 01:12:56 +0000748** If the following global variable points to a string which is the
749** name of a directory, then that directory will be used to store
750** temporary files.
751*/
tpoindex9a09a3c2004-12-20 19:01:32 +0000752char *sqlite3_temp_directory = 0;
drh3d2efea2004-08-28 01:12:56 +0000753
754/*
drhbbd42a62004-05-22 17:41:58 +0000755** Create a temporary file name in zBuf. zBuf must be big enough to
756** hold at least SQLITE_TEMPNAME_SIZE characters.
757*/
drh66560ad2006-01-06 14:32:19 +0000758int sqlite3WinTempFileName(char *zBuf){
drhbbd42a62004-05-22 17:41:58 +0000759 static char zChars[] =
760 "abcdefghijklmnopqrstuvwxyz"
761 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
762 "0123456789";
763 int i, j;
764 char zTempPath[SQLITE_TEMPNAME_SIZE];
drheffd02b2004-08-29 23:42:13 +0000765 if( sqlite3_temp_directory ){
766 strncpy(zTempPath, sqlite3_temp_directory, SQLITE_TEMPNAME_SIZE-30);
drh3d2efea2004-08-28 01:12:56 +0000767 zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
drhc0929982005-09-05 19:08:29 +0000768 }else if( isNT() ){
769 char *zMulti;
770 WCHAR zWidePath[SQLITE_TEMPNAME_SIZE];
771 GetTempPathW(SQLITE_TEMPNAME_SIZE-30, zWidePath);
772 zMulti = unicodeToUtf8(zWidePath);
773 if( zMulti ){
drhd81bd4e2005-09-05 20:06:49 +0000774 strncpy(zTempPath, zMulti, SQLITE_TEMPNAME_SIZE-30);
drhc0929982005-09-05 19:08:29 +0000775 zTempPath[SQLITE_TEMPNAME_SIZE-30] = 0;
776 sqliteFree(zMulti);
777 }
drh3d2efea2004-08-28 01:12:56 +0000778 }else{
779 GetTempPathA(SQLITE_TEMPNAME_SIZE-30, zTempPath);
780 }
drhbbd42a62004-05-22 17:41:58 +0000781 for(i=strlen(zTempPath); i>0 && zTempPath[i-1]=='\\'; i--){}
782 zTempPath[i] = 0;
783 for(;;){
784 sprintf(zBuf, "%s\\"TEMP_FILE_PREFIX, zTempPath);
785 j = strlen(zBuf);
786 sqlite3Randomness(15, &zBuf[j]);
787 for(i=0; i<15; i++, j++){
788 zBuf[j] = (char)zChars[ ((unsigned char)zBuf[j])%(sizeof(zChars)-1) ];
789 }
790 zBuf[j] = 0;
drh66560ad2006-01-06 14:32:19 +0000791 if( !sqlite3OsFileExists(zBuf) ) break;
drhbbd42a62004-05-22 17:41:58 +0000792 }
drh51c6d962004-06-06 00:42:25 +0000793 TRACE2("TEMP FILENAME: %s\n", zBuf);
drhbbd42a62004-05-22 17:41:58 +0000794 return SQLITE_OK;
795}
796
797/*
798** Close a file.
799*/
drh9cbe6352005-11-29 03:13:21 +0000800static int winClose(OsFile **pId){
drh054889e2005-11-30 03:20:31 +0000801 winFile *pFile;
802 if( pId && (pFile = (winFile*)*pId)!=0 ){
803 TRACE2("CLOSE %d\n", pFile->h);
804 CloseHandle(pFile->h);
drhcc78fea2006-01-06 16:17:05 +0000805#if OS_WINCE
drh72aead82006-01-23 15:54:25 +0000806 winceDestroyLock(pFile);
drhcc78fea2006-01-06 16:17:05 +0000807 if( pFile->zDeleteOnClose ){
drh9e9fe6f2006-01-06 21:09:01 +0000808 DeleteFileW(pFile->zDeleteOnClose);
drhcc78fea2006-01-06 16:17:05 +0000809 sqliteFree(pFile->zDeleteOnClose);
810 }
811#endif
drhda71ce12004-06-21 18:14:45 +0000812 OpenCounter(-1);
drh054889e2005-11-30 03:20:31 +0000813 sqliteFree(pFile);
drh9cbe6352005-11-29 03:13:21 +0000814 *pId = 0;
drhda71ce12004-06-21 18:14:45 +0000815 }
drhbbd42a62004-05-22 17:41:58 +0000816 return SQLITE_OK;
817}
818
819/*
820** Read data from a file into a buffer. Return SQLITE_OK if all
821** bytes were read successfully and SQLITE_IOERR if anything goes
822** wrong.
823*/
drh9c06c952005-11-26 00:25:00 +0000824static int winRead(OsFile *id, void *pBuf, int amt){
drhbbd42a62004-05-22 17:41:58 +0000825 DWORD got;
drh9cbe6352005-11-29 03:13:21 +0000826 assert( id!=0 );
drhbbd42a62004-05-22 17:41:58 +0000827 SimulateIOError(SQLITE_IOERR);
drh054889e2005-11-30 03:20:31 +0000828 TRACE3("READ %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
829 if( !ReadFile(((winFile*)id)->h, pBuf, amt, &got, 0) ){
drhbbd42a62004-05-22 17:41:58 +0000830 got = 0;
831 }
832 if( got==(DWORD)amt ){
833 return SQLITE_OK;
834 }else{
835 return SQLITE_IOERR;
836 }
837}
838
839/*
840** Write data from a buffer into a file. Return SQLITE_OK on success
841** or some other error code on failure.
842*/
drh9c06c952005-11-26 00:25:00 +0000843static int winWrite(OsFile *id, const void *pBuf, int amt){
drh4c7f9412005-02-03 00:29:47 +0000844 int rc = 0;
drhbbd42a62004-05-22 17:41:58 +0000845 DWORD wrote;
drh9cbe6352005-11-29 03:13:21 +0000846 assert( id!=0 );
drhbbd42a62004-05-22 17:41:58 +0000847 SimulateIOError(SQLITE_IOERR);
dougcurrie0924bba2004-10-01 18:21:43 +0000848 SimulateDiskfullError;
drh054889e2005-11-30 03:20:31 +0000849 TRACE3("WRITE %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
drh4c7f9412005-02-03 00:29:47 +0000850 assert( amt>0 );
drh054889e2005-11-30 03:20:31 +0000851 while( amt>0 && (rc = WriteFile(((winFile*)id)->h, pBuf, amt, &wrote, 0))!=0
852 && wrote>0 ){
drhbbd42a62004-05-22 17:41:58 +0000853 amt -= wrote;
854 pBuf = &((char*)pBuf)[wrote];
855 }
856 if( !rc || amt>(int)wrote ){
857 return SQLITE_FULL;
858 }
859 return SQLITE_OK;
860}
861
862/*
drhbbdc2b92005-09-19 12:53:18 +0000863** Some microsoft compilers lack this definition.
864*/
865#ifndef INVALID_SET_FILE_POINTER
866# define INVALID_SET_FILE_POINTER ((DWORD)-1)
867#endif
868
869/*
drhbbd42a62004-05-22 17:41:58 +0000870** Move the read/write pointer in a file.
871*/
drh9c06c952005-11-26 00:25:00 +0000872static int winSeek(OsFile *id, i64 offset){
drhbbd42a62004-05-22 17:41:58 +0000873 LONG upperBits = offset>>32;
874 LONG lowerBits = offset & 0xffffffff;
875 DWORD rc;
drh9cbe6352005-11-29 03:13:21 +0000876 assert( id!=0 );
drhb4746b92005-09-09 01:32:06 +0000877#ifdef SQLITE_TEST
878 if( offset ) SimulateDiskfullError
879#endif
drhbbd42a62004-05-22 17:41:58 +0000880 SEEK(offset/1024 + 1);
drh054889e2005-11-30 03:20:31 +0000881 rc = SetFilePointer(((winFile*)id)->h, lowerBits, &upperBits, FILE_BEGIN);
882 TRACE3("SEEK %d %lld\n", ((winFile*)id)->h, offset);
drhe08b8142005-09-09 10:17:33 +0000883 if( rc==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR ){
884 return SQLITE_FULL;
885 }
drhbbd42a62004-05-22 17:41:58 +0000886 return SQLITE_OK;
887}
888
889/*
890** Make sure all writes to a particular file are committed to disk.
891*/
drh9c06c952005-11-26 00:25:00 +0000892static int winSync(OsFile *id, int dataOnly){
drh9cbe6352005-11-29 03:13:21 +0000893 assert( id!=0 );
drh054889e2005-11-30 03:20:31 +0000894 TRACE3("SYNC %d lock=%d\n", ((winFile*)id)->h, ((winFile*)id)->locktype);
895 if( FlushFileBuffers(((winFile*)id)->h) ){
drhbbd42a62004-05-22 17:41:58 +0000896 return SQLITE_OK;
897 }else{
898 return SQLITE_IOERR;
899 }
900}
901
902/*
danielk1977962398d2004-06-14 09:35:16 +0000903** Sync the directory zDirname. This is a no-op on operating systems other
904** than UNIX.
905*/
drh66560ad2006-01-06 14:32:19 +0000906int sqlite3WinSyncDirectory(const char *zDirname){
danielk1977369f27e2004-06-15 11:40:04 +0000907 SimulateIOError(SQLITE_IOERR);
danielk1977962398d2004-06-14 09:35:16 +0000908 return SQLITE_OK;
909}
910
911/*
drhbbd42a62004-05-22 17:41:58 +0000912** Truncate an open file to a specified size
913*/
drh9c06c952005-11-26 00:25:00 +0000914static int winTruncate(OsFile *id, i64 nByte){
drhbbd42a62004-05-22 17:41:58 +0000915 LONG upperBits = nByte>>32;
drh9cbe6352005-11-29 03:13:21 +0000916 assert( id!=0 );
drh054889e2005-11-30 03:20:31 +0000917 TRACE3("TRUNCATE %d %lld\n", ((winFile*)id)->h, nByte);
drhbbd42a62004-05-22 17:41:58 +0000918 SimulateIOError(SQLITE_IOERR);
drh054889e2005-11-30 03:20:31 +0000919 SetFilePointer(((winFile*)id)->h, nByte, &upperBits, FILE_BEGIN);
920 SetEndOfFile(((winFile*)id)->h);
drhbbd42a62004-05-22 17:41:58 +0000921 return SQLITE_OK;
922}
923
924/*
925** Determine the current size of a file in bytes
926*/
drh9c06c952005-11-26 00:25:00 +0000927static int winFileSize(OsFile *id, i64 *pSize){
drhbbd42a62004-05-22 17:41:58 +0000928 DWORD upperBits, lowerBits;
drh9cbe6352005-11-29 03:13:21 +0000929 assert( id!=0 );
drhbbd42a62004-05-22 17:41:58 +0000930 SimulateIOError(SQLITE_IOERR);
drh054889e2005-11-30 03:20:31 +0000931 lowerBits = GetFileSize(((winFile*)id)->h, &upperBits);
drheb206252004-10-01 02:00:31 +0000932 *pSize = (((i64)upperBits)<<32) + lowerBits;
drhbbd42a62004-05-22 17:41:58 +0000933 return SQLITE_OK;
934}
935
936/*
drh602bbd32006-01-06 20:22:29 +0000937** LOCKFILE_FAIL_IMMEDIATELY is undefined on some Windows systems.
938*/
939#ifndef LOCKFILE_FAIL_IMMEDIATELY
940# define LOCKFILE_FAIL_IMMEDIATELY 1
941#endif
942
943/*
drh9c105bb2004-10-02 20:38:28 +0000944** Acquire a reader lock.
drh51c6d962004-06-06 00:42:25 +0000945** Different API routines are called depending on whether or not this
946** is Win95 or WinNT.
947*/
drh054889e2005-11-30 03:20:31 +0000948static int getReadLock(winFile *id){
drh51c6d962004-06-06 00:42:25 +0000949 int res;
950 if( isNT() ){
951 OVERLAPPED ovlp;
drh9c105bb2004-10-02 20:38:28 +0000952 ovlp.Offset = SHARED_FIRST;
drh51c6d962004-06-06 00:42:25 +0000953 ovlp.OffsetHigh = 0;
954 ovlp.hEvent = 0;
drh9c105bb2004-10-02 20:38:28 +0000955 res = LockFileEx(id->h, LOCKFILE_FAIL_IMMEDIATELY, 0, SHARED_SIZE,0,&ovlp);
drhbbd42a62004-05-22 17:41:58 +0000956 }else{
drh9c105bb2004-10-02 20:38:28 +0000957 int lk;
958 sqlite3Randomness(sizeof(lk), &lk);
959 id->sharedLockByte = (lk & 0x7fffffff)%(SHARED_SIZE - 1);
960 res = LockFile(id->h, SHARED_FIRST+id->sharedLockByte, 0, 1, 0);
drh51c6d962004-06-06 00:42:25 +0000961 }
962 return res;
963}
964
965/*
966** Undo a readlock
967*/
drh054889e2005-11-30 03:20:31 +0000968static int unlockReadLock(winFile *pFile){
drh51c6d962004-06-06 00:42:25 +0000969 int res;
970 if( isNT() ){
drh054889e2005-11-30 03:20:31 +0000971 res = UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
drh51c6d962004-06-06 00:42:25 +0000972 }else{
drh054889e2005-11-30 03:20:31 +0000973 res = UnlockFile(pFile->h, SHARED_FIRST + pFile->sharedLockByte, 0, 1, 0);
drh51c6d962004-06-06 00:42:25 +0000974 }
975 return res;
976}
977
drh268283b2005-01-08 15:44:25 +0000978#ifndef SQLITE_OMIT_PAGER_PRAGMAS
drh51c6d962004-06-06 00:42:25 +0000979/*
tpoindex9a09a3c2004-12-20 19:01:32 +0000980** Check that a given pathname is a directory and is writable
981**
982*/
drh66560ad2006-01-06 14:32:19 +0000983int sqlite3WinIsDirWritable(char *zDirname){
tpoindex9a09a3c2004-12-20 19:01:32 +0000984 int fileAttr;
drhc0929982005-09-05 19:08:29 +0000985 WCHAR *zWide;
986 if( zDirname==0 ) return 0;
987 if( !isNT() && strlen(zDirname)>MAX_PATH ) return 0;
988 zWide = utf8ToUnicode(zDirname);
989 if( zWide ){
990 fileAttr = GetFileAttributesW(zWide);
991 sqliteFree(zWide);
992 }else{
drhcc78fea2006-01-06 16:17:05 +0000993#if OS_WINCE
994 return 0;
995#else
drhc0929982005-09-05 19:08:29 +0000996 fileAttr = GetFileAttributesA(zDirname);
drhcc78fea2006-01-06 16:17:05 +0000997#endif
drhc0929982005-09-05 19:08:29 +0000998 }
tpoindex9a09a3c2004-12-20 19:01:32 +0000999 if( fileAttr == 0xffffffff ) return 0;
drh268283b2005-01-08 15:44:25 +00001000 if( (fileAttr & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY ){
1001 return 0;
1002 }
tpoindex9a09a3c2004-12-20 19:01:32 +00001003 return 1;
1004}
drh268283b2005-01-08 15:44:25 +00001005#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
tpoindex9a09a3c2004-12-20 19:01:32 +00001006
1007/*
drhb3e04342004-06-08 00:47:47 +00001008** Lock the file with the lock specified by parameter locktype - one
1009** of the following:
1010**
1011** (1) SHARED_LOCK
1012** (2) RESERVED_LOCK
1013** (3) PENDING_LOCK
1014** (4) EXCLUSIVE_LOCK
1015**
1016** Sometimes when requesting one lock state, additional lock states
1017** are inserted in between. The locking might fail on one of the later
1018** transitions leaving the lock state different from what it started but
1019** still short of its goal. The following chart shows the allowed
1020** transitions and the inserted intermediate states:
1021**
1022** UNLOCKED -> SHARED
1023** SHARED -> RESERVED
1024** SHARED -> (PENDING) -> EXCLUSIVE
1025** RESERVED -> (PENDING) -> EXCLUSIVE
1026** PENDING -> EXCLUSIVE
1027**
drh9c06c952005-11-26 00:25:00 +00001028** This routine will only increase a lock. The winUnlock() routine
drhb3e04342004-06-08 00:47:47 +00001029** erases all locks at once and returns us immediately to locking level 0.
1030** It is not possible to lower the locking level one step at a time. You
1031** must go straight to locking level 0.
drh51c6d962004-06-06 00:42:25 +00001032*/
drh9c06c952005-11-26 00:25:00 +00001033static int winLock(OsFile *id, int locktype){
drh51c6d962004-06-06 00:42:25 +00001034 int rc = SQLITE_OK; /* Return code from subroutines */
1035 int res = 1; /* Result of a windows lock call */
drhe54ca3f2004-06-07 01:52:14 +00001036 int newLocktype; /* Set id->locktype to this value before exiting */
1037 int gotPendingLock = 0;/* True if we acquired a PENDING lock this time */
drh054889e2005-11-30 03:20:31 +00001038 winFile *pFile = (winFile*)id;
drh51c6d962004-06-06 00:42:25 +00001039
drh054889e2005-11-30 03:20:31 +00001040 assert( pFile!=0 );
drhe54ca3f2004-06-07 01:52:14 +00001041 TRACE5("LOCK %d %d was %d(%d)\n",
drh054889e2005-11-30 03:20:31 +00001042 pFile->h, locktype, pFile->locktype, pFile->sharedLockByte);
drh51c6d962004-06-06 00:42:25 +00001043
1044 /* If there is already a lock of this type or more restrictive on the
1045 ** OsFile, do nothing. Don't use the end_lock: exit path, as
1046 ** sqlite3OsEnterMutex() hasn't been called yet.
1047 */
drh054889e2005-11-30 03:20:31 +00001048 if( pFile->locktype>=locktype ){
drh51c6d962004-06-06 00:42:25 +00001049 return SQLITE_OK;
1050 }
1051
drhb3e04342004-06-08 00:47:47 +00001052 /* Make sure the locking sequence is correct
1053 */
drh054889e2005-11-30 03:20:31 +00001054 assert( pFile->locktype!=NO_LOCK || locktype==SHARED_LOCK );
drhb3e04342004-06-08 00:47:47 +00001055 assert( locktype!=PENDING_LOCK );
drh054889e2005-11-30 03:20:31 +00001056 assert( locktype!=RESERVED_LOCK || pFile->locktype==SHARED_LOCK );
drhb3e04342004-06-08 00:47:47 +00001057
drh51c6d962004-06-06 00:42:25 +00001058 /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
1059 ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
1060 ** the PENDING_LOCK byte is temporary.
1061 */
drh054889e2005-11-30 03:20:31 +00001062 newLocktype = pFile->locktype;
1063 if( pFile->locktype==NO_LOCK
1064 || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK)
drhe54ca3f2004-06-07 01:52:14 +00001065 ){
drhb3e04342004-06-08 00:47:47 +00001066 int cnt = 3;
drh054889e2005-11-30 03:20:31 +00001067 while( cnt-->0 && (res = LockFile(pFile->h, PENDING_BYTE, 0, 1, 0))==0 ){
drhb3e04342004-06-08 00:47:47 +00001068 /* Try 3 times to get the pending lock. The pending lock might be
drh51c6d962004-06-06 00:42:25 +00001069 ** held by another reader process who will release it momentarily.
1070 */
drhe54ca3f2004-06-07 01:52:14 +00001071 TRACE2("could not get a PENDING lock. cnt=%d\n", cnt);
drhbbd42a62004-05-22 17:41:58 +00001072 Sleep(1);
1073 }
drhe54ca3f2004-06-07 01:52:14 +00001074 gotPendingLock = res;
drh51c6d962004-06-06 00:42:25 +00001075 }
1076
1077 /* Acquire a shared lock
1078 */
drhb3e04342004-06-08 00:47:47 +00001079 if( locktype==SHARED_LOCK && res ){
drh054889e2005-11-30 03:20:31 +00001080 assert( pFile->locktype==NO_LOCK );
1081 res = getReadLock(pFile);
drhe54ca3f2004-06-07 01:52:14 +00001082 if( res ){
1083 newLocktype = SHARED_LOCK;
drh51c6d962004-06-06 00:42:25 +00001084 }
1085 }
1086
1087 /* Acquire a RESERVED lock
1088 */
drhb3e04342004-06-08 00:47:47 +00001089 if( locktype==RESERVED_LOCK && res ){
drh054889e2005-11-30 03:20:31 +00001090 assert( pFile->locktype==SHARED_LOCK );
1091 res = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
drhe54ca3f2004-06-07 01:52:14 +00001092 if( res ){
1093 newLocktype = RESERVED_LOCK;
1094 }
1095 }
1096
1097 /* Acquire a PENDING lock
1098 */
drhb3e04342004-06-08 00:47:47 +00001099 if( locktype==EXCLUSIVE_LOCK && res ){
drhe54ca3f2004-06-07 01:52:14 +00001100 newLocktype = PENDING_LOCK;
1101 gotPendingLock = 0;
drh51c6d962004-06-06 00:42:25 +00001102 }
1103
1104 /* Acquire an EXCLUSIVE lock
1105 */
drhe54ca3f2004-06-07 01:52:14 +00001106 if( locktype==EXCLUSIVE_LOCK && res ){
drh054889e2005-11-30 03:20:31 +00001107 assert( pFile->locktype>=SHARED_LOCK );
1108 res = unlockReadLock(pFile);
drhb3e04342004-06-08 00:47:47 +00001109 TRACE2("unreadlock = %d\n", res);
drh054889e2005-11-30 03:20:31 +00001110 res = LockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
drhe54ca3f2004-06-07 01:52:14 +00001111 if( res ){
1112 newLocktype = EXCLUSIVE_LOCK;
1113 }else{
1114 TRACE2("error-code = %d\n", GetLastError());
1115 }
1116 }
1117
1118 /* If we are holding a PENDING lock that ought to be released, then
1119 ** release it now.
1120 */
drhb3e04342004-06-08 00:47:47 +00001121 if( gotPendingLock && locktype==SHARED_LOCK ){
drh054889e2005-11-30 03:20:31 +00001122 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
drh51c6d962004-06-06 00:42:25 +00001123 }
1124
1125 /* Update the state of the lock has held in the file descriptor then
1126 ** return the appropriate result code.
1127 */
1128 if( res ){
drh51c6d962004-06-06 00:42:25 +00001129 rc = SQLITE_OK;
1130 }else{
drh054889e2005-11-30 03:20:31 +00001131 TRACE4("LOCK FAILED %d trying for %d but got %d\n", pFile->h,
drhe54ca3f2004-06-07 01:52:14 +00001132 locktype, newLocktype);
drh51c6d962004-06-06 00:42:25 +00001133 rc = SQLITE_BUSY;
drhbbd42a62004-05-22 17:41:58 +00001134 }
drh054889e2005-11-30 03:20:31 +00001135 pFile->locktype = newLocktype;
drhbbd42a62004-05-22 17:41:58 +00001136 return rc;
1137}
1138
1139/*
drh51c6d962004-06-06 00:42:25 +00001140** This routine checks if there is a RESERVED lock held on the specified
1141** file by this or any other process. If such a lock is held, return
1142** non-zero, otherwise zero.
drhbbd42a62004-05-22 17:41:58 +00001143*/
drh9c06c952005-11-26 00:25:00 +00001144static int winCheckReservedLock(OsFile *id){
drhbbd42a62004-05-22 17:41:58 +00001145 int rc;
drh054889e2005-11-30 03:20:31 +00001146 winFile *pFile = (winFile*)id;
1147 assert( pFile!=0 );
1148 if( pFile->locktype>=RESERVED_LOCK ){
drh51c6d962004-06-06 00:42:25 +00001149 rc = 1;
drh054889e2005-11-30 03:20:31 +00001150 TRACE3("TEST WR-LOCK %d %d (local)\n", pFile->h, rc);
drhbbd42a62004-05-22 17:41:58 +00001151 }else{
drh054889e2005-11-30 03:20:31 +00001152 rc = LockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
drh51c6d962004-06-06 00:42:25 +00001153 if( rc ){
drh054889e2005-11-30 03:20:31 +00001154 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
drhbbd42a62004-05-22 17:41:58 +00001155 }
drh2ac3ee92004-06-07 16:27:46 +00001156 rc = !rc;
drh054889e2005-11-30 03:20:31 +00001157 TRACE3("TEST WR-LOCK %d %d (remote)\n", pFile->h, rc);
drhbbd42a62004-05-22 17:41:58 +00001158 }
drh2ac3ee92004-06-07 16:27:46 +00001159 return rc;
drhbbd42a62004-05-22 17:41:58 +00001160}
1161
1162/*
drha6abd042004-06-09 17:37:22 +00001163** Lower the locking level on file descriptor id to locktype. locktype
1164** must be either NO_LOCK or SHARED_LOCK.
1165**
1166** If the locking level of the file descriptor is already at or below
1167** the requested locking level, this routine is a no-op.
1168**
drh9c105bb2004-10-02 20:38:28 +00001169** It is not possible for this routine to fail if the second argument
1170** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
1171** might return SQLITE_IOERR;
drhbbd42a62004-05-22 17:41:58 +00001172*/
drh9c06c952005-11-26 00:25:00 +00001173static int winUnlock(OsFile *id, int locktype){
drh9c105bb2004-10-02 20:38:28 +00001174 int type;
1175 int rc = SQLITE_OK;
drh054889e2005-11-30 03:20:31 +00001176 winFile *pFile = (winFile*)id;
1177 assert( pFile!=0 );
drha6abd042004-06-09 17:37:22 +00001178 assert( locktype<=SHARED_LOCK );
drh054889e2005-11-30 03:20:31 +00001179 TRACE5("UNLOCK %d to %d was %d(%d)\n", pFile->h, locktype,
1180 pFile->locktype, pFile->sharedLockByte);
1181 type = pFile->locktype;
drhe54ca3f2004-06-07 01:52:14 +00001182 if( type>=EXCLUSIVE_LOCK ){
drh054889e2005-11-30 03:20:31 +00001183 UnlockFile(pFile->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
1184 if( locktype==SHARED_LOCK && !getReadLock(pFile) ){
drh9c105bb2004-10-02 20:38:28 +00001185 /* This should never happen. We should always be able to
1186 ** reacquire the read lock */
1187 rc = SQLITE_IOERR;
1188 }
drhbbd42a62004-05-22 17:41:58 +00001189 }
drhe54ca3f2004-06-07 01:52:14 +00001190 if( type>=RESERVED_LOCK ){
drh054889e2005-11-30 03:20:31 +00001191 UnlockFile(pFile->h, RESERVED_BYTE, 0, 1, 0);
drh51c6d962004-06-06 00:42:25 +00001192 }
drh9c105bb2004-10-02 20:38:28 +00001193 if( locktype==NO_LOCK && type>=SHARED_LOCK ){
drh054889e2005-11-30 03:20:31 +00001194 unlockReadLock(pFile);
drh51c6d962004-06-06 00:42:25 +00001195 }
drhb3e04342004-06-08 00:47:47 +00001196 if( type>=PENDING_LOCK ){
drh054889e2005-11-30 03:20:31 +00001197 UnlockFile(pFile->h, PENDING_BYTE, 0, 1, 0);
drhb3e04342004-06-08 00:47:47 +00001198 }
drh054889e2005-11-30 03:20:31 +00001199 pFile->locktype = locktype;
drh9c105bb2004-10-02 20:38:28 +00001200 return rc;
drhbbd42a62004-05-22 17:41:58 +00001201}
1202
1203/*
drh0ccebe72005-06-07 22:22:50 +00001204** Turn a relative pathname into a full pathname. Return a pointer
1205** to the full pathname stored in space obtained from sqliteMalloc().
1206** The calling function is responsible for freeing this space once it
1207** is no longer needed.
1208*/
drh66560ad2006-01-06 14:32:19 +00001209char *sqlite3WinFullPathname(const char *zRelative){
drh0ccebe72005-06-07 22:22:50 +00001210 char *zFull;
drhcc78fea2006-01-06 16:17:05 +00001211#if defined(__CYGWIN__)
drh0ccebe72005-06-07 22:22:50 +00001212 int nByte;
drh0ccebe72005-06-07 22:22:50 +00001213 nByte = strlen(zRelative) + MAX_PATH + 1001;
1214 zFull = sqliteMalloc( nByte );
1215 if( zFull==0 ) return 0;
1216 if( cygwin_conv_to_full_win32_path(zRelative, zFull) ) return 0;
drhcc78fea2006-01-06 16:17:05 +00001217#elif OS_WINCE
1218 /* WinCE has no concept of a relative pathname, or so I am told. */
danielk1977e7259292006-01-13 06:33:23 +00001219 zFull = sqliteStrDup(zRelative);
drh0ccebe72005-06-07 22:22:50 +00001220#else
drhcc78fea2006-01-06 16:17:05 +00001221 char *zNotUsed;
1222 WCHAR *zWide;
1223 int nByte;
drhc0929982005-09-05 19:08:29 +00001224 zWide = utf8ToUnicode(zRelative);
1225 if( zWide ){
1226 WCHAR *zTemp, *zNotUsedW;
1227 nByte = GetFullPathNameW(zWide, 0, 0, &zNotUsedW) + 1;
1228 zTemp = sqliteMalloc( nByte*sizeof(zTemp[0]) );
1229 if( zTemp==0 ) return 0;
1230 GetFullPathNameW(zWide, nByte, zTemp, &zNotUsedW);
1231 sqliteFree(zWide);
1232 zFull = unicodeToUtf8(zTemp);
1233 sqliteFree(zTemp);
1234 }else{
1235 nByte = GetFullPathNameA(zRelative, 0, 0, &zNotUsed) + 1;
1236 zFull = sqliteMalloc( nByte*sizeof(zFull[0]) );
1237 if( zFull==0 ) return 0;
1238 GetFullPathNameA(zRelative, nByte, zFull, &zNotUsed);
1239 }
drh0ccebe72005-06-07 22:22:50 +00001240#endif
1241 return zFull;
1242}
1243
drh9c06c952005-11-26 00:25:00 +00001244/*
drh9cbe6352005-11-29 03:13:21 +00001245** The fullSync option is meaningless on windows. This is a no-op.
drh18839212005-11-26 03:43:23 +00001246*/
drh9cbe6352005-11-29 03:13:21 +00001247static void winSetFullSync(OsFile *id, int v){
1248 return;
1249}
1250
1251/*
1252** Return the underlying file handle for an OsFile
1253*/
1254static int winFileHandle(OsFile *id){
drh054889e2005-11-30 03:20:31 +00001255 return (int)((winFile*)id)->h;
drh9cbe6352005-11-29 03:13:21 +00001256}
1257
1258/*
1259** Return an integer that indices the type of lock currently held
1260** by this handle. (Used for testing and analysis only.)
1261*/
1262static int winLockState(OsFile *id){
drh054889e2005-11-30 03:20:31 +00001263 return ((winFile*)id)->locktype;
drh18839212005-11-26 03:43:23 +00001264}
1265
drh18839212005-11-26 03:43:23 +00001266/*
drh054889e2005-11-30 03:20:31 +00001267** This vector defines all the methods that can operate on an OsFile
1268** for win32.
drh9c06c952005-11-26 00:25:00 +00001269*/
drh054889e2005-11-30 03:20:31 +00001270static const IoMethod sqlite3WinIoMethod = {
drh9c06c952005-11-26 00:25:00 +00001271 winClose,
drh054889e2005-11-30 03:20:31 +00001272 winOpenDirectory,
drh9c06c952005-11-26 00:25:00 +00001273 winRead,
1274 winWrite,
1275 winSeek,
drh9c06c952005-11-26 00:25:00 +00001276 winTruncate,
drh054889e2005-11-30 03:20:31 +00001277 winSync,
drh9cbe6352005-11-29 03:13:21 +00001278 winSetFullSync,
1279 winFileHandle,
drh054889e2005-11-30 03:20:31 +00001280 winFileSize,
1281 winLock,
1282 winUnlock,
drh9cbe6352005-11-29 03:13:21 +00001283 winLockState,
drh054889e2005-11-30 03:20:31 +00001284 winCheckReservedLock,
drh9c06c952005-11-26 00:25:00 +00001285};
1286
drh054889e2005-11-30 03:20:31 +00001287/*
1288** Allocate memory for an OsFile. Initialize the new OsFile
1289** to the value given in pInit and return a pointer to the new
1290** OsFile. If we run out of memory, close the file and return NULL.
1291*/
1292int allocateWinFile(winFile *pInit, OsFile **pId){
1293 winFile *pNew;
1294 pNew = sqliteMalloc( sizeof(*pNew) );
1295 if( pNew==0 ){
1296 CloseHandle(pInit->h);
drhcc78fea2006-01-06 16:17:05 +00001297#if OS_WINCE
1298 sqliteFree(pInit->zDeleteOnClose);
1299#endif
drh054889e2005-11-30 03:20:31 +00001300 *pId = 0;
1301 return SQLITE_NOMEM;
1302 }else{
1303 *pNew = *pInit;
1304 pNew->pMethod = &sqlite3WinIoMethod;
drhbe1f84c2006-01-23 16:25:22 +00001305 pNew->locktype = NO_LOCK;
1306 pNew->sharedLockByte = 0;
drh66560ad2006-01-06 14:32:19 +00001307 *pId = (OsFile*)pNew;
drhbe1f84c2006-01-23 16:25:22 +00001308 OpenCounter(+1);
drh054889e2005-11-30 03:20:31 +00001309 return SQLITE_OK;
1310 }
1311}
1312
1313
drh0ccebe72005-06-07 22:22:50 +00001314#endif /* SQLITE_OMIT_DISKIO */
1315/***************************************************************************
1316** Everything above deals with file I/O. Everything that follows deals
1317** with other miscellanous aspects of the operating system interface
1318****************************************************************************/
1319
1320/*
drhbbd42a62004-05-22 17:41:58 +00001321** Get information to seed the random number generator. The seed
1322** is written into the buffer zBuf[256]. The calling function must
1323** supply a sufficiently large buffer.
1324*/
drh66560ad2006-01-06 14:32:19 +00001325int sqlite3WinRandomSeed(char *zBuf){
drhbbd42a62004-05-22 17:41:58 +00001326 /* We have to initialize zBuf to prevent valgrind from reporting
1327 ** errors. The reports issued by valgrind are incorrect - we would
1328 ** prefer that the randomness be increased by making use of the
1329 ** uninitialized space in zBuf - but valgrind errors tend to worry
1330 ** some users. Rather than argue, it seems easier just to initialize
1331 ** the whole array and silence valgrind, even if that means less randomness
1332 ** in the random seed.
1333 **
1334 ** When testing, initializing zBuf[] to zero is all we do. That means
1335 ** that we always use the same random number sequence.* This makes the
1336 ** tests repeatable.
1337 */
1338 memset(zBuf, 0, 256);
1339 GetSystemTime((LPSYSTEMTIME)zBuf);
1340 return SQLITE_OK;
1341}
1342
1343/*
1344** Sleep for a little while. Return the amount of time slept.
1345*/
drh66560ad2006-01-06 14:32:19 +00001346int sqlite3WinSleep(int ms){
drhbbd42a62004-05-22 17:41:58 +00001347 Sleep(ms);
1348 return ms;
1349}
1350
1351/*
1352** Static variables used for thread synchronization
1353*/
1354static int inMutex = 0;
1355#ifdef SQLITE_W32_THREADS
drh757b04e2006-01-18 17:25:45 +00001356 static DWORD mutexOwner;
drhbbd42a62004-05-22 17:41:58 +00001357 static CRITICAL_SECTION cs;
1358#endif
1359
1360/*
drh757b04e2006-01-18 17:25:45 +00001361** The following pair of routines implement mutual exclusion for
drhbbd42a62004-05-22 17:41:58 +00001362** multi-threaded processes. Only a single thread is allowed to
1363** executed code that is surrounded by EnterMutex() and LeaveMutex().
1364**
1365** SQLite uses only a single Mutex. There is not much critical
1366** code and what little there is executes quickly and without blocking.
drh757b04e2006-01-18 17:25:45 +00001367**
1368** Version 3.3.1 and earlier used a simple mutex. Beginning with
1369** version 3.3.2, a recursive mutex is required.
drhbbd42a62004-05-22 17:41:58 +00001370*/
drh66560ad2006-01-06 14:32:19 +00001371void sqlite3WinEnterMutex(){
drhbbd42a62004-05-22 17:41:58 +00001372#ifdef SQLITE_W32_THREADS
1373 static int isInit = 0;
1374 while( !isInit ){
1375 static long lock = 0;
1376 if( InterlockedIncrement(&lock)==1 ){
1377 InitializeCriticalSection(&cs);
1378 isInit = 1;
1379 }else{
1380 Sleep(1);
1381 }
1382 }
1383 EnterCriticalSection(&cs);
drh757b04e2006-01-18 17:25:45 +00001384 mutexOwner = GetCurrentThreadId();
drhbbd42a62004-05-22 17:41:58 +00001385#endif
drh332b1fe2006-01-18 14:20:17 +00001386 inMutex++;
drhbbd42a62004-05-22 17:41:58 +00001387}
drh66560ad2006-01-06 14:32:19 +00001388void sqlite3WinLeaveMutex(){
drhbbd42a62004-05-22 17:41:58 +00001389 assert( inMutex );
drh332b1fe2006-01-18 14:20:17 +00001390 inMutex--;
drhbbd42a62004-05-22 17:41:58 +00001391#ifdef SQLITE_W32_THREADS
drh757b04e2006-01-18 17:25:45 +00001392 assert( mutexOwner==GetCurrentThreadId() );
drhbbd42a62004-05-22 17:41:58 +00001393 LeaveCriticalSection(&cs);
1394#endif
1395}
1396
1397/*
drh757b04e2006-01-18 17:25:45 +00001398** Return TRUE if the mutex is currently held.
1399**
1400** If the thisThreadOnly parameter is true, return true if and only if the
1401** calling thread holds the mutex. If the parameter is false, return
1402** true if any thread holds the mutex.
drh88f474a2006-01-02 20:00:12 +00001403*/
drh757b04e2006-01-18 17:25:45 +00001404int sqlite3WinInMutex(int thisThreadOnly){
drh332b1fe2006-01-18 14:20:17 +00001405#ifdef SQLITE_W32_THREADS
drh757b04e2006-01-18 17:25:45 +00001406 return inMutex>0 && (thisThreadOnly==0 || mutexOwner==GetCurrentThreadId());
drh332b1fe2006-01-18 14:20:17 +00001407#else
drh757b04e2006-01-18 17:25:45 +00001408 return inMutex>0;
drh332b1fe2006-01-18 14:20:17 +00001409#endif
drh88f474a2006-01-02 20:00:12 +00001410}
1411
1412
1413/*
drhbbd42a62004-05-22 17:41:58 +00001414** The following variable, if set to a non-zero value, becomes the result
1415** returned from sqlite3OsCurrentTime(). This is used for testing.
1416*/
1417#ifdef SQLITE_TEST
1418int sqlite3_current_time = 0;
1419#endif
1420
1421/*
1422** Find the current time (in Universal Coordinated Time). Write the
1423** current time and date as a Julian Day number into *prNow and
1424** return 0. Return 1 if the time and date cannot be found.
1425*/
drh66560ad2006-01-06 14:32:19 +00001426int sqlite3WinCurrentTime(double *prNow){
drhbbd42a62004-05-22 17:41:58 +00001427 FILETIME ft;
1428 /* FILETIME structure is a 64-bit value representing the number of
1429 100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).
1430 */
1431 double now;
drhcc78fea2006-01-06 16:17:05 +00001432#if OS_WINCE
1433 SYSTEMTIME time;
1434 GetSystemTime(&time);
1435 SystemTimeToFileTime(&time,&ft);
1436#else
drhbbd42a62004-05-22 17:41:58 +00001437 GetSystemTimeAsFileTime( &ft );
drhcc78fea2006-01-06 16:17:05 +00001438#endif
drhbbd42a62004-05-22 17:41:58 +00001439 now = ((double)ft.dwHighDateTime) * 4294967296.0;
1440 *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;
1441#ifdef SQLITE_TEST
1442 if( sqlite3_current_time ){
1443 *prNow = sqlite3_current_time/86400.0 + 2440587.5;
1444 }
1445#endif
1446 return 0;
1447}
1448
drh6f7adc82006-01-11 21:41:20 +00001449/*
drhb4bc7052006-01-11 23:40:33 +00001450** Remember the number of thread-specific-data blocks allocated.
1451** Use this to verify that we are not leaking thread-specific-data.
1452** Ticket #1601
1453*/
1454#ifdef SQLITE_TEST
1455int sqlite3_tsd_count = 0;
1456# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
1457# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
1458#else
1459# define TSD_COUNTER_INCR /* no-op */
1460# define TSD_COUNTER_DECR /* no-op */
1461#endif
1462
1463
1464
1465/*
drh70ff98a2006-01-12 01:25:18 +00001466** If called with allocateFlag>1, then return a pointer to thread
drh6f7adc82006-01-11 21:41:20 +00001467** specific data for the current thread. Allocate and zero the
1468** thread-specific data if it does not already exist necessary.
drh3fbb0b12006-01-06 00:36:00 +00001469**
drh6f7adc82006-01-11 21:41:20 +00001470** If called with allocateFlag==0, then check the current thread
drh70ff98a2006-01-12 01:25:18 +00001471** specific data. Return it if it exists. If it does not exist,
1472** then return NULL.
1473**
1474** If called with allocateFlag<0, check to see if the thread specific
1475** data is allocated and is all zero. If it is then deallocate it.
drh6f7adc82006-01-11 21:41:20 +00001476** Return a pointer to the thread specific data or NULL if it is
drh70ff98a2006-01-12 01:25:18 +00001477** unallocated or gets deallocated.
danielk197713a68c32005-12-15 10:11:30 +00001478*/
drhb4bc7052006-01-11 23:40:33 +00001479ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){
drh3fbb0b12006-01-06 00:36:00 +00001480 static int key;
1481 static int keyInit = 0;
drh6f7adc82006-01-11 21:41:20 +00001482 static const ThreadData zeroData;
drhb4bc7052006-01-11 23:40:33 +00001483 ThreadData *pTsd;
drh3fbb0b12006-01-06 00:36:00 +00001484
1485 if( !keyInit ){
drh66560ad2006-01-06 14:32:19 +00001486 sqlite3OsEnterMutex();
drh3fbb0b12006-01-06 00:36:00 +00001487 if( !keyInit ){
1488 key = TlsAlloc();
1489 if( key==0xffffffff ){
drh66560ad2006-01-06 14:32:19 +00001490 sqlite3OsLeaveMutex();
drh3fbb0b12006-01-06 00:36:00 +00001491 return 0;
1492 }
1493 keyInit = 1;
1494 }
drh66560ad2006-01-06 14:32:19 +00001495 sqlite3OsLeaveMutex();
danielk197713a68c32005-12-15 10:11:30 +00001496 }
drh3fbb0b12006-01-06 00:36:00 +00001497 pTsd = TlsGetValue(key);
drh70ff98a2006-01-12 01:25:18 +00001498 if( allocateFlag>0 ){
drh6f7adc82006-01-11 21:41:20 +00001499 if( !pTsd ){
drhb4bc7052006-01-11 23:40:33 +00001500 pTsd = sqlite3OsMalloc( sizeof(zeroData) );
drh6f7adc82006-01-11 21:41:20 +00001501 if( pTsd ){
1502 *pTsd = zeroData;
1503 TlsSetValue(key, pTsd);
drhb4bc7052006-01-11 23:40:33 +00001504 TSD_COUNTER_INCR;
drh6f7adc82006-01-11 21:41:20 +00001505 }
drh3fbb0b12006-01-06 00:36:00 +00001506 }
drh70ff98a2006-01-12 01:25:18 +00001507 }else if( pTsd!=0 && allocateFlag<0
danielk19779e128002006-01-18 16:51:35 +00001508 && memcmp(pTsd, &zeroData, sizeof(ThreadData))==0 ){
drh6f7adc82006-01-11 21:41:20 +00001509 sqlite3OsFree(pTsd);
1510 TlsSetValue(key, 0);
drhb4bc7052006-01-11 23:40:33 +00001511 TSD_COUNTER_DECR;
drh6f7adc82006-01-11 21:41:20 +00001512 pTsd = 0;
drh3fbb0b12006-01-06 00:36:00 +00001513 }
1514 return pTsd;
danielk197713a68c32005-12-15 10:11:30 +00001515}
drhbbd42a62004-05-22 17:41:58 +00001516#endif /* OS_WIN */