PageRenderTime 47ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 1ms

/Languages/IronPython/IronPython.SQLite/c#sqlite/os_win_c.cs

http://github.com/IronLanguages/main
C# | 3829 lines | 2285 code | 271 blank | 1273 comment | 456 complexity | a0f0d7b8e136ce4a90f18e2577dbfb2d MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. #define SQLITE_OS_WIN
  2. using System;
  3. using System.Diagnostics;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Threading;
  8. using DWORD = System.UInt64;
  9. using HANDLE = System.IntPtr;
  10. using i64 = System.Int64;
  11. using sqlite3_int64 = System.Int64;
  12. using u32 = System.UInt32;
  13. using u8 = System.Byte;
  14. #if SQLITE_WINRT
  15. using System.Threading.Tasks;
  16. using Windows.Storage;
  17. using Windows.Storage.Streams;
  18. using System.Runtime.InteropServices.WindowsRuntime;
  19. #elif WINDOWS_PHONE || SQLITE_SILVERLIGHT
  20. using System.IO.IsolatedStorage;
  21. #endif
  22. #if NETCOREAPP1_0
  23. using Environment = System.FakeEnvironment;
  24. #endif
  25. namespace Community.CsharpSqlite
  26. {
  27. public partial class Sqlite3
  28. {
  29. /*
  30. ** 2004 May 22
  31. **
  32. ** The author disclaims copyright to this source code. In place of
  33. ** a legal notice, here is a blessing:
  34. **
  35. ** May you do good and not evil.
  36. ** May you find forgiveness for yourself and forgive others.
  37. ** May you share freely, never taking more than you give.
  38. **
  39. ******************************************************************************
  40. **
  41. ** This file contains code that is specific to windows.
  42. *************************************************************************
  43. ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart
  44. ** C#-SQLite is an independent reimplementation of the SQLite software library
  45. **
  46. ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
  47. **
  48. *************************************************************************
  49. */
  50. //#include "sqliteInt.h"
  51. #if SQLITE_OS_WIN // * This file is used for windows only */
  52. /*
  53. ** A Note About Memory Allocation:
  54. **
  55. ** This driver uses malloc()/free() directly rather than going through
  56. ** the SQLite-wrappers sqlite3Malloc()/sqlite3DbFree(db,ref ). Those wrappers
  57. ** are designed for use on embedded systems where memory is scarce and
  58. ** malloc failures happen frequently. Win32 does not typically run on
  59. ** embedded systems, and when it does the developers normally have bigger
  60. ** problems to worry about than running out of memory. So there is not
  61. ** a compelling need to use the wrappers.
  62. **
  63. ** But there is a good reason to not use the wrappers. If we use the
  64. ** wrappers then we will get simulated malloc() failures within this
  65. ** driver. And that causes all kinds of problems for our tests. We
  66. ** could enhance SQLite to deal with simulated malloc failures within
  67. ** the OS driver, but the code to deal with those failure would not
  68. ** be exercised on Linux (which does not need to malloc() in the driver)
  69. ** and so we would have difficulty writing coverage tests for that
  70. ** code. Better to leave the code out, we think.
  71. **
  72. ** The point of this discussion is as follows: When creating a new
  73. ** OS layer for an embedded system, if you use this file as an example,
  74. ** avoid the use of malloc()/free(). Those routines work ok on windows
  75. ** desktops but not so well in embedded systems.
  76. */
  77. //#include <winbase.h>
  78. #if __CYGWIN__
  79. //# include <sys/cygwin.h>
  80. #endif
  81. /*
  82. ** Macros used to determine whether or not to use threads.
  83. */
  84. #if THREADSAFE
  85. //# define SQLITE_W32_THREADS 1
  86. #endif
  87. /*
  88. ** Include code that is common to all os_*.c files
  89. */
  90. //#include "os_common.h"
  91. /*
  92. ** Some microsoft compilers lack this definition.
  93. */
  94. #if !INVALID_FILE_ATTRIBUTES
  95. //# define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
  96. const int INVALID_FILE_ATTRIBUTES = -1;
  97. #endif
  98. /*
  99. ** Determine if we are dealing with WindowsCE - which has a much
  100. ** reduced API.
  101. */
  102. #if SQLITE_OS_WINCE
  103. //# define AreFileApisANSI() 1
  104. //# define GetDiskFreeSpaceW() 0
  105. #endif
  106. /* Forward references */
  107. //typedef struct winShm winShm; /* A connection to shared-memory */
  108. //typedef struct winShmNode winShmNode; /* A region of shared-memory */
  109. /*
  110. ** WinCE lacks native support for file locking so we have to fake it
  111. ** with some code of our own.
  112. */
  113. #if SQLITE_OS_WINCE
  114. typedef struct winceLock {
  115. int nReaders; /* Number of reader locks obtained */
  116. BOOL bPending; /* Indicates a pending lock has been obtained */
  117. BOOL bReserved; /* Indicates a reserved lock has been obtained */
  118. BOOL bExclusive; /* Indicates an exclusive lock has been obtained */
  119. } winceLock;
  120. #endif
  121. private static LockingStrategy lockingStrategy = HelperMethods.IsRunningMediumTrust() ? new MediumTrustLockingStrategy() : new LockingStrategy();
  122. /*
  123. ** The winFile structure is a subclass of sqlite3_file* specific to the win32
  124. ** portability layer.
  125. */
  126. //typedef struct sqlite3_file sqlite3_file;
  127. public partial class sqlite3_file
  128. {
  129. public sqlite3_vfs pVfs; /* The VFS used to open this file */
  130. #if SQLITE_WINRT
  131. public IRandomAccessStream fs;
  132. #else
  133. public FileStream fs; /* Filestream access to this file*/
  134. #endif
  135. // public HANDLE h; /* Handle for accessing the file */
  136. public int locktype; /* Type of lock currently held on this file */
  137. public int sharedLockByte; /* Randomly chosen byte used as a shared lock */
  138. public DWORD lastErrno; /* The Windows errno from the last I/O error */
  139. public DWORD sectorSize; /* Sector size of the device file is on */
  140. #if !SQLITE_OMIT_WAL
  141. public winShm pShm; /* Instance of shared memory on this file */
  142. #else
  143. public object pShm; /* DUMMY Instance of shared memory on this file */
  144. #endif
  145. public string zPath; /* Full pathname of this file */
  146. public int szChunk; /* Chunk size configured by FCNTL_CHUNK_SIZE */
  147. #if SQLITE_OS_WINCE
  148. Wstring zDeleteOnClose; /* Name of file to delete when closing */
  149. HANDLE hMutex; /* Mutex used to control access to shared lock */
  150. HANDLE hShared; /* Shared memory segment used for locking */
  151. winceLock local; /* Locks obtained by this instance of sqlite3_file */
  152. winceLock *shared; /* Global shared lock memory for the file */
  153. #endif
  154. public void Clear()
  155. {
  156. pMethods = null;
  157. fs = null;
  158. locktype = 0;
  159. sharedLockByte = 0;
  160. lastErrno = 0;
  161. sectorSize = 0;
  162. }
  163. };
  164. /*
  165. ** Forward prototypes.
  166. */
  167. //static int getSectorSize(
  168. // sqlite3_vfs *pVfs,
  169. // string zRelative /* UTF-8 file name */
  170. //);
  171. /*
  172. ** The following variable is (normally) set once and never changes
  173. ** thereafter. It records whether the operating system is Win95
  174. ** or WinNT.
  175. **
  176. ** 0: Operating system unknown.
  177. ** 1: Operating system is Win95.
  178. ** 2: Operating system is WinNT.
  179. **
  180. ** In order to facilitate testing on a WinNT system, the test fixture
  181. ** can manually set this value to 1 to emulate Win98 behavior.
  182. */
  183. #if SQLITE_TEST
  184. int sqlite3_os_type = 0;
  185. #else
  186. static int sqlite3_os_type = 0;
  187. #endif
  188. /*
  189. ** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
  190. ** or WinCE. Return false (zero) for Win95, Win98, or WinME.
  191. **
  192. ** Here is an interesting observation: Win95, Win98, and WinME lack
  193. ** the LockFileEx() API. But we can still statically link against that
  194. ** API as long as we don't call it when running Win95/98/ME. A call to
  195. ** this routine is used to determine if the host is Win95/98/ME or
  196. ** WinNT/2K/XP so that we will know whether or not we can safely call
  197. ** the LockFileEx() API.
  198. */
  199. #if SQLITE_OS_WINCE
  200. //# define isNT() (1)
  201. #elif SQLITE_WINRT
  202. static bool isNT() { return true; }
  203. #else
  204. static bool isNT()
  205. {
  206. //if (sqlite3_os_type == 0)
  207. //{
  208. // OSVERSIONINFO sInfo;
  209. // sInfo.dwOSVersionInfoSize = sInfo.Length;
  210. // GetVersionEx(&sInfo);
  211. // sqlite3_os_type = sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT ? 2 : 1;
  212. //}
  213. //return sqlite3_os_type == 2;
  214. return Environment.OSVersion.Platform >= PlatformID.Win32NT;
  215. }
  216. #endif // * SQLITE_OS_WINCE */
  217. /*
  218. ** Convert a UTF-8 string to microsoft unicode (UTF-16?).
  219. **
  220. ** Space to hold the returned string is obtained from malloc.
  221. */
  222. //static WCHAR *utf8ToUnicode(string zFilename){
  223. // int nChar;
  224. // Wstring zWideFilename;
  225. // nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, NULL, 0);
  226. // zWideFilename = malloc( nChar*sizeof(zWideFilename[0]) );
  227. // if( zWideFilename==0 ){
  228. // return 0;
  229. // }
  230. // nChar = MultiByteToWideChar(CP_UTF8, 0, zFilename, -1, zWideFilename, nChar);
  231. // if( nChar==0 ){
  232. // free(zWideFilename);
  233. // zWideFileName = "";
  234. // }
  235. // return zWideFilename;
  236. //}
  237. /*
  238. ** Convert microsoft unicode to UTF-8. Space to hold the returned string is
  239. ** obtained from malloc().
  240. */
  241. //static char *unicodeToUtf8(const Wstring zWideFilename){
  242. // int nByte;
  243. // string zFilename;
  244. // nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, 0, 0, 0, 0);
  245. // zFilename = malloc( nByte );
  246. // if( zFilename==0 ){
  247. // return 0;
  248. // }
  249. // nByte = WideCharToMultiByte(CP_UTF8, 0, zWideFilename, -1, zFilename, nByte,
  250. // 0, 0);
  251. // if( nByte == 0 ){
  252. // free(zFilename);
  253. // zFileName = "";
  254. // }
  255. // return zFilename;
  256. //}
  257. /*
  258. ** Convert an ansi string to microsoft unicode, based on the
  259. ** current codepage settings for file apis.
  260. **
  261. ** Space to hold the returned string is obtained
  262. ** from malloc.
  263. */
  264. //static WCHAR *mbcsToUnicode(string zFilename){
  265. // int nByte;
  266. // Wstring zMbcsFilename;
  267. // int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  268. // nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, NULL,0)*WCHAR.Length;
  269. // zMbcsFilename = malloc( nByte*sizeof(zMbcsFilename[0]) );
  270. // if( zMbcsFilename==0 ){
  271. // return 0;
  272. // }
  273. // nByte = MultiByteToWideChar(codepage, 0, zFilename, -1, zMbcsFilename, nByte);
  274. // if( nByte==0 ){
  275. // free(zMbcsFilename);
  276. // zMbcsFileName = "";
  277. // }
  278. // return zMbcsFilename;
  279. //}
  280. /*
  281. ** Convert microsoft unicode to multibyte character string, based on the
  282. ** user's Ansi codepage.
  283. **
  284. ** Space to hold the returned string is obtained from
  285. ** malloc().
  286. */
  287. //static char *unicodeToMbcs(const Wstring zWideFilename){
  288. // int nByte;
  289. // string zFilename;
  290. // int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  291. // nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, 0, 0, 0, 0);
  292. // zFilename = malloc( nByte );
  293. // if( zFilename==0 ){
  294. // return 0;
  295. // }
  296. // nByte = WideCharToMultiByte(codepage, 0, zWideFilename, -1, zFilename, nByte,
  297. // 0, 0);
  298. // if( nByte == 0 ){
  299. // free(zFilename);
  300. // zFileName = "";
  301. // }
  302. // return zFilename;
  303. //}
  304. /*
  305. ** Convert multibyte character string to UTF-8. Space to hold the
  306. ** returned string is obtained from malloc().
  307. */
  308. //static char *sqlite3_win32_mbcs_to_utf8(string zFilename){
  309. // string zFilenameUtf8;
  310. // Wstring zTmpWide;
  311. // zTmpWide = mbcsToUnicode(zFilename);
  312. // if( zTmpWide==0 ){
  313. // return 0;
  314. // }
  315. // zFilenameUtf8 = unicodeToUtf8(zTmpWide);
  316. // free(zTmpWide);
  317. // return zFilenameUtf8;
  318. //}
  319. /*
  320. ** Convert UTF-8 to multibyte character string. Space to hold the
  321. ** returned string is obtained from malloc().
  322. */
  323. //char *sqlite3_win32_utf8_to_mbcs(string zFilename){
  324. // string zFilenameMbcs;
  325. // Wstring zTmpWide;
  326. // zTmpWide = utf8ToUnicode(zFilename);
  327. // if( zTmpWide==0 ){
  328. // return 0;
  329. // }
  330. // zFilenameMbcs = unicodeToMbcs(zTmpWide);
  331. // free(zTmpWide);
  332. // return zFilenameMbcs;
  333. //}
  334. /*
  335. ** The return value of getLastErrorMsg
  336. ** is zero if the error message fits in the buffer, or non-zero
  337. ** otherwise (if the message was truncated).
  338. */
  339. static int getLastErrorMsg(int nBuf, ref string zBuf){
  340. /* FormatMessage returns 0 on failure. Otherwise it
  341. ** returns the number of TCHARs written to the output
  342. ** buffer, excluding the terminating null char.
  343. */
  344. //DWORD error = GetLastError();
  345. //DWORD dwLen = 0;
  346. //string zOut = "";
  347. //if( isNT() ){
  348. //Wstring zTempWide = NULL;
  349. //dwLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  350. // NULL,
  351. // error,
  352. // 0,
  353. // (LPWSTR) &zTempWide,
  354. // 0,
  355. // 0);
  356. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  357. zBuf = "Unknown error";
  358. #else
  359. zBuf = Marshal.GetLastWin32Error().ToString();//new Win32Exception( Marshal.GetLastWin32Error() ).Message;
  360. #endif
  361. //if( dwLen > 0 ){
  362. // /* allocate a buffer and convert to UTF8 */
  363. // zOut = unicodeToUtf8(zTempWide);
  364. // /* free the system buffer allocated by FormatMessage */
  365. // LocalFree(zTempWide);
  366. //}
  367. /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
  368. ** Since the ASCII version of these Windows API do not exist for WINCE,
  369. ** it's important to not reference them for WINCE builds.
  370. */
  371. //#if !SQLITE_OS_WINCE //==0
  372. // }else{
  373. // string zTemp = null;
  374. // dwLen = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  375. // null,
  376. // error,
  377. // 0,
  378. // ref zTemp,
  379. // 0,
  380. // 0);
  381. // if( dwLen > 0 ){
  382. // /* allocate a buffer and convert to UTF8 */
  383. // zOut = sqlite3_win32_mbcs_to_utf8(zTemp);
  384. // /* free the system buffer allocated by FormatMessage */
  385. // LocalFree(zTemp);
  386. // }
  387. //#endif
  388. // }
  389. //if( 0 == dwLen ){
  390. // sqlite3_snprintf(nBuf, zBuf, "OsError 0x%x (%u)", error, error);
  391. //}else{
  392. // /* copy a maximum of nBuf chars to output buffer */
  393. // sqlite3_snprintf(nBuf, zBuf, "%s", zOut);
  394. // /* free the UTF8 buffer */
  395. // free(zOut);
  396. //}
  397. return 0;
  398. }
  399. /*
  400. **
  401. ** This function - winLogErrorAtLine() - is only ever called via the macro
  402. ** winLogError().
  403. **
  404. ** This routine is invoked after an error occurs in an OS function.
  405. ** It logs a message using sqlite3_log() containing the current value of
  406. ** error code and, if possible, the human-readable equivalent from
  407. ** FormatMessage.
  408. **
  409. ** The first argument passed to the macro should be the error code that
  410. ** will be returned to SQLite (e.g. SQLITE_IOERR_DELETE, SQLITE_CANTOPEN).
  411. ** The two subsequent arguments should be the name of the OS function that
  412. ** failed and the the associated file-system path, if any.
  413. */
  414. //#define winLogError(a,b,c) winLogErrorAtLine(a,b,c,__LINE__)
  415. static int winLogError( int a, string b, string c )
  416. {
  417. #if !SQLITE_WINRT && !SILVERLIGHT && !NETSTANDARD
  418. StackTrace st = new StackTrace( new StackFrame( true ) );
  419. StackFrame sf = st.GetFrame( 0 );
  420. return winLogErrorAtLine( a, b, c, sf.GetFileLineNumber() );
  421. #else
  422. return winLogErrorAtLine( a, b, c, 0 );
  423. #endif
  424. }
  425. static int winLogErrorAtLine(
  426. int errcode, /* SQLite error code */
  427. string zFunc, /* Name of OS function that failed */
  428. string zPath, /* File path associated with error */
  429. int iLine /* Source line number where error occurred */
  430. ){
  431. string zMsg = null; /* Human readable error text */
  432. int i; /* Loop counter */
  433. DWORD iErrno;// = GetLastError(); /* Error code */
  434. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  435. iErrno = (int)ERROR_NOT_SUPPORTED;
  436. #else
  437. iErrno = (u32)Marshal.GetLastWin32Error();
  438. #endif
  439. //zMsg[0] = 0;
  440. getLastErrorMsg( 500, ref zMsg );
  441. Debug.Assert( errcode != SQLITE_OK );
  442. if ( zPath == null )
  443. zPath = "";
  444. for ( i = 0; i < zMsg.Length && zMsg[i] != '\r' && zMsg[i] != '\n'; i++ )
  445. {
  446. }
  447. zMsg = zMsg.Substring( 0, i );
  448. sqlite3_log(errcode,
  449. "os_win.c:%d: (%d) %s(%s) - %s",
  450. iLine, iErrno, zFunc, zPath, zMsg
  451. );
  452. return errcode;
  453. }
  454. #if SQLITE_OS_WINCE
  455. /*************************************************************************
  456. ** This section contains code for WinCE only.
  457. */
  458. /*
  459. ** WindowsCE does not have a localtime() function. So create a
  460. ** substitute.
  461. */
  462. //#include <time.h>
  463. struct tm *__cdecl localtime(const time_t *t)
  464. {
  465. static struct tm y;
  466. FILETIME uTm, lTm;
  467. SYSTEMTIME pTm;
  468. sqlite3_int64 t64;
  469. t64 = *t;
  470. t64 = (t64 + 11644473600)*10000000;
  471. uTm.dwLowDateTime = (DWORD)(t64 & 0xFFFFFFFF);
  472. uTm.dwHighDateTime= (DWORD)(t64 >> 32);
  473. FileTimeToLocalFileTime(&uTm,&lTm);
  474. FileTimeToSystemTime(&lTm,&pTm);
  475. y.tm_year = pTm.wYear - 1900;
  476. y.tm_mon = pTm.wMonth - 1;
  477. y.tm_wday = pTm.wDayOfWeek;
  478. y.tm_mday = pTm.wDay;
  479. y.tm_hour = pTm.wHour;
  480. y.tm_min = pTm.wMinute;
  481. y.tm_sec = pTm.wSecond;
  482. return &y;
  483. }
  484. /* This will never be called, but defined to make the code compile */
  485. //#define GetTempPathA(a,b)
  486. //#define LockFile(a,b,c,d,e) winceLockFile(&a, b, c, d, e)
  487. //#define UnlockFile(a,b,c,d,e) winceUnlockFile(&a, b, c, d, e)
  488. //#define LockFileEx(a,b,c,d,e,f) winceLockFileEx(&a, b, c, d, e, f)
  489. //#define HANDLE_TO_WINFILE(a) (winFile)&((char)a)[-(int)offsetof(winFile,h)]
  490. /*
  491. ** Acquire a lock on the handle h
  492. */
  493. static void winceMutexAcquire(HANDLE h){
  494. DWORD dwErr;
  495. do {
  496. dwErr = WaitForSingleObject(h, INFINITE);
  497. } while (dwErr != WAIT_OBJECT_0 && dwErr != WAIT_ABANDONED);
  498. }
  499. /*
  500. ** Release a lock acquired by winceMutexAcquire()
  501. */
  502. //#define winceMutexRelease(h) ReleaseMutex(h)
  503. /*
  504. ** Create the mutex and shared memory used for locking in the file
  505. ** descriptor pFile
  506. */
  507. static BOOL winceCreateLock(string zFilename, sqlite3_file pFile){
  508. Wstring zTok;
  509. Wstring zName = utf8ToUnicode(zFilename);
  510. BOOL bInit = TRUE;
  511. /* Initialize the local lockdata */
  512. ZeroMemory(pFile.local, pFile.local).Length;
  513. /* Replace the backslashes from the filename and lowercase it
  514. ** to derive a mutex name. */
  515. zTok = CharLowerW(zName);
  516. for (;*zTok;zTok++){
  517. if (*zTok == '\\') *zTok = '_';
  518. }
  519. /* Create/open the named mutex */
  520. pFile.hMutex = CreateMutexW(NULL, FALSE, zName);
  521. if (!pFile.hMutex){
  522. pFile.lastErrno = (u32)GetLastError();
  523. winLogError(SQLITE_ERROR, "winceCreateLock1", zFilename);
  524. free(zName);
  525. return FALSE;
  526. }
  527. /* Acquire the mutex before continuing */
  528. winceMutexAcquire(pFile.hMutex);
  529. /* Since the names of named mutexes, semaphores, file mappings etc are
  530. ** case-sensitive, take advantage of that by uppercasing the mutex name
  531. ** and using that as the shared filemapping name.
  532. */
  533. CharUpperW(zName);
  534. pFile.hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
  535. PAGE_READWRITE, 0, winceLock.Length,
  536. zName);
  537. /* Set a flag that indicates we're the first to create the memory so it
  538. ** must be zero-initialized */
  539. if (GetLastError() == ERROR_ALREADY_EXISTS){
  540. bInit = FALSE;
  541. }
  542. free(zName);
  543. /* If we succeeded in making the shared memory handle, map it. */
  544. if (pFile.hShared){
  545. pFile.shared = (winceLock)MapViewOfFile(pFile.hShared,
  546. FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, winceLock).Length;
  547. /* If mapping failed, close the shared memory handle and erase it */
  548. if (!pFile.shared){
  549. pFile.lastErrno = (u32)GetLastError();
  550. winLogError(SQLITE_ERROR, "winceCreateLock2", zFilename);
  551. CloseHandle(pFile.hShared);
  552. pFile.hShared = NULL;
  553. }
  554. }
  555. /* If shared memory could not be created, then close the mutex and fail */
  556. if (pFile.hShared == NULL){
  557. winceMutexRelease(pFile.hMutex);
  558. CloseHandle(pFile.hMutex);
  559. pFile.hMutex = NULL;
  560. return FALSE;
  561. }
  562. /* Initialize the shared memory if we're supposed to */
  563. if (bInit) {
  564. ZeroMemory(pFile.shared, winceLock).Length;
  565. }
  566. winceMutexRelease(pFile.hMutex);
  567. return TRUE;
  568. }
  569. /*
  570. ** Destroy the part of sqlite3_file that deals with wince locks
  571. */
  572. static void winceDestroyLock(sqlite3_file pFile){
  573. if (pFile.hMutex){
  574. /* Acquire the mutex */
  575. winceMutexAcquire(pFile.hMutex);
  576. /* The following blocks should probably Debug.Assert in debug mode, but they
  577. are to cleanup in case any locks remained open */
  578. if (pFile.local.nReaders){
  579. pFile.shared.nReaders --;
  580. }
  581. if (pFile.local.bReserved){
  582. pFile.shared.bReserved = FALSE;
  583. }
  584. if (pFile.local.bPending){
  585. pFile.shared.bPending = FALSE;
  586. }
  587. if (pFile.local.bExclusive){
  588. pFile.shared.bExclusive = FALSE;
  589. }
  590. /* De-reference and close our copy of the shared memory handle */
  591. UnmapViewOfFile(pFile.shared);
  592. CloseHandle(pFile.hShared);
  593. /* Done with the mutex */
  594. winceMutexRelease(pFile.hMutex);
  595. CloseHandle(pFile.hMutex);
  596. pFile.hMutex = NULL;
  597. }
  598. }
  599. /*
  600. ** An implementation of the LockFile() API of windows for wince
  601. */
  602. static BOOL winceLockFile(
  603. HANDLE *phFile,
  604. DWORD dwFileOffsetLow,
  605. DWORD dwFileOffsetHigh,
  606. DWORD nNumberOfBytesToLockLow,
  607. DWORD nNumberOfBytesToLockHigh
  608. ){
  609. winFile *pFile = HANDLE_TO_WINFILE(phFile);
  610. BOOL bReturn = FALSE;
  611. UNUSED_PARAMETER(dwFileOffsetHigh);
  612. UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
  613. if (!pFile.hMutex) return TRUE;
  614. winceMutexAcquire(pFile.hMutex);
  615. /* Wanting an exclusive lock? */
  616. if (dwFileOffsetLow == (DWORD)SHARED_FIRST
  617. && nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
  618. if (pFile.shared.nReaders == 0 && pFile.shared.bExclusive == 0){
  619. pFile.shared.bExclusive = TRUE;
  620. pFile.local.bExclusive = TRUE;
  621. bReturn = TRUE;
  622. }
  623. }
  624. /* Want a read-only lock? */
  625. else if (dwFileOffsetLow == (DWORD)SHARED_FIRST &&
  626. nNumberOfBytesToLockLow == 1){
  627. if (pFile.shared.bExclusive == 0){
  628. pFile.local.nReaders ++;
  629. if (pFile.local.nReaders == 1){
  630. pFile.shared.nReaders ++;
  631. }
  632. bReturn = TRUE;
  633. }
  634. }
  635. /* Want a pending lock? */
  636. else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
  637. /* If no pending lock has been acquired, then acquire it */
  638. if (pFile.shared.bPending == 0) {
  639. pFile.shared.bPending = TRUE;
  640. pFile.local.bPending = TRUE;
  641. bReturn = TRUE;
  642. }
  643. }
  644. /* Want a reserved lock? */
  645. else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
  646. if (pFile.shared.bReserved == 0) {
  647. pFile.shared.bReserved = TRUE;
  648. pFile.local.bReserved = TRUE;
  649. bReturn = TRUE;
  650. }
  651. }
  652. winceMutexRelease(pFile.hMutex);
  653. return bReturn;
  654. }
  655. /*
  656. ** An implementation of the UnlockFile API of windows for wince
  657. */
  658. static BOOL winceUnlockFile(
  659. HANDLE *phFile,
  660. DWORD dwFileOffsetLow,
  661. DWORD dwFileOffsetHigh,
  662. DWORD nNumberOfBytesToUnlockLow,
  663. DWORD nNumberOfBytesToUnlockHigh
  664. ){
  665. winFile *pFile = HANDLE_TO_WINFILE(phFile);
  666. BOOL bReturn = FALSE;
  667. UNUSED_PARAMETER(dwFileOffsetHigh);
  668. UNUSED_PARAMETER(nNumberOfBytesToUnlockHigh);
  669. if (!pFile.hMutex) return TRUE;
  670. winceMutexAcquire(pFile.hMutex);
  671. /* Releasing a reader lock or an exclusive lock */
  672. if (dwFileOffsetLow == (DWORD)SHARED_FIRST){
  673. /* Did we have an exclusive lock? */
  674. if (pFile.local.bExclusive){
  675. Debug.Assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE);
  676. pFile.local.bExclusive = FALSE;
  677. pFile.shared.bExclusive = FALSE;
  678. bReturn = TRUE;
  679. }
  680. /* Did we just have a reader lock? */
  681. else if (pFile.local.nReaders){
  682. Debug.Assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
  683. pFile.local.nReaders --;
  684. if (pFile.local.nReaders == 0)
  685. {
  686. pFile.shared.nReaders --;
  687. }
  688. bReturn = TRUE;
  689. }
  690. }
  691. /* Releasing a pending lock */
  692. else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
  693. if (pFile.local.bPending){
  694. pFile.local.bPending = FALSE;
  695. pFile.shared.bPending = FALSE;
  696. bReturn = TRUE;
  697. }
  698. }
  699. /* Releasing a reserved lock */
  700. else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
  701. if (pFile.local.bReserved) {
  702. pFile.local.bReserved = FALSE;
  703. pFile.shared.bReserved = FALSE;
  704. bReturn = TRUE;
  705. }
  706. }
  707. winceMutexRelease(pFile.hMutex);
  708. return bReturn;
  709. }
  710. /*
  711. ** An implementation of the LockFileEx() API of windows for wince
  712. */
  713. static BOOL winceLockFileEx(
  714. HANDLE *phFile,
  715. DWORD dwFlags,
  716. DWORD dwReserved,
  717. DWORD nNumberOfBytesToLockLow,
  718. DWORD nNumberOfBytesToLockHigh,
  719. LPOVERLAPPED lpOverlapped
  720. ){
  721. UNUSED_PARAMETER(dwReserved);
  722. UNUSED_PARAMETER(nNumberOfBytesToLockHigh);
  723. /* If the caller wants a shared read lock, forward this call
  724. ** to winceLockFile */
  725. if (lpOverlapped.Offset == (DWORD)SHARED_FIRST &&
  726. dwFlags == 1 &&
  727. nNumberOfBytesToLockLow == (DWORD)SHARED_SIZE){
  728. return winceLockFile(phFile, SHARED_FIRST, 0, 1, 0);
  729. }
  730. return FALSE;
  731. }
  732. /*
  733. ** End of the special code for wince
  734. *****************************************************************************/
  735. #endif // * SQLITE_OS_WINCE */
  736. /*****************************************************************************
  737. ** The next group of routines implement the I/O methods specified
  738. ** by the sqlite3_io_methods object.
  739. ******************************************************************************/
  740. /*
  741. ** Some microsoft compilers lack this definition.
  742. */
  743. #if !INVALID_SET_FILE_POINTER
  744. //# define INVALID_SET_FILE_POINTER ((DWORD)-1)
  745. const int INVALID_SET_FILE_POINTER = -1;
  746. #endif
  747. /*
  748. ** Move the current position of the file handle passed as the first
  749. ** argument to offset iOffset within the file. If successful, return 0.
  750. ** Otherwise, set pFile->lastErrno and return non-zero.
  751. */
  752. static int seekWinFile( sqlite3_file id, sqlite3_int64 iOffset )
  753. {
  754. //LONG upperBits; /* Most sig. 32 bits of new offset */
  755. //LONG lowerBits; /* Least sig. 32 bits of new offset */
  756. DWORD dwRet; /* Value returned by SetFilePointer() */
  757. sqlite3_file pFile = id;
  758. //upperBits = (LONG)((iOffset>>32) & 0x7fffffff);
  759. //lowerBits = (LONG)(iOffset & 0xffffffff);
  760. /* API oddity: If successful, SetFilePointer() returns a dword
  761. ** containing the lower 32-bits of the new file-offset. Or, if it fails,
  762. ** it returns INVALID_SET_FILE_POINTER. However according to MSDN,
  763. ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine
  764. ** whether an error has actually occured, it is also necessary to call
  765. ** GetLastError().
  766. */
  767. //dwRet = SetFilePointer(id, lowerBits, &upperBits, FILE_BEGIN);
  768. //if( (dwRet==INVALID_SET_FILE_POINTER && GetLastError()!=NO_ERROR) ){
  769. // pFile->lastErrno = GetLastError();
  770. // winLogError(SQLITE_IOERR_SEEK, "seekWinFile", pFile->zPath);
  771. try
  772. {
  773. #if SQLITE_WINRT
  774. id.fs.Seek( (ulong)iOffset ); // SetFilePointer(pFile.fs.Name, lowerBits, upperBits, FILE_BEGIN);
  775. #else
  776. id.fs.Seek( iOffset, SeekOrigin.Begin ); // SetFilePointer(pFile.fs.Name, lowerBits, upperBits, FILE_BEGIN);
  777. #endif
  778. }
  779. catch ( Exception e )
  780. {
  781. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  782. pFile.lastErrno = 1;
  783. #else
  784. pFile.lastErrno = (u32)Marshal.GetLastWin32Error();
  785. #endif
  786. winLogError(SQLITE_IOERR_SEEK, "seekWinFile", pFile.zPath);
  787. return 1;
  788. }
  789. return 0;
  790. }
  791. /*
  792. ** Close a file.
  793. **
  794. ** It is reported that an attempt to close a handle might sometimes
  795. ** fail. This is a very unreasonable result, but windows is notorious
  796. ** for being unreasonable so I do not doubt that it might happen. If
  797. ** the close fails, we pause for 100 milliseconds and try again. As
  798. ** many as MX_CLOSE_ATTEMPT attempts to close the handle are made before
  799. ** giving up and returning an error.
  800. */
  801. public static int MX_CLOSE_ATTEMPT = 3;
  802. static int winClose( sqlite3_file id )
  803. {
  804. bool rc;
  805. int cnt = 0;
  806. sqlite3_file pFile = (sqlite3_file)id;
  807. Debug.Assert( id != null );
  808. Debug.Assert( pFile.pShm == null );
  809. #if SQLITE_DEBUG
  810. #if WINDOWS_PHONE || SQLITE_SILVERLIGHT
  811. OSTRACE( "CLOSE %d\n", pFile.fs.GetHashCode());
  812. #else
  813. OSTRACE( "CLOSE %d (%s)\n", pFile.fs.GetHashCode(), pFile.fs.Name );
  814. #endif
  815. #endif
  816. do
  817. {
  818. #if SQLITE_WINRT || NETSTANDARD
  819. pFile.fs.Dispose();
  820. #else
  821. pFile.fs.Close();
  822. #endif
  823. rc = true;
  824. // rc = CloseHandle(pFile.h);
  825. /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
  826. // if (!rc && ++cnt < MX_CLOSE_ATTEMPT) Thread.Sleep(100); //, 1) );
  827. } while ( !rc && ++cnt < MX_CLOSE_ATTEMPT ); //, 1) );
  828. #if SQLITE_OS_WINCE
  829. //#define WINCE_DELETION_ATTEMPTS 3
  830. winceDestroyLock(pFile);
  831. if( pFile.zDeleteOnClose ){
  832. int cnt = 0;
  833. while(
  834. DeleteFileW(pFile.zDeleteOnClose)==0
  835. && GetFileAttributesW(pFile.zDeleteOnClose)!=0xffffffff
  836. && cnt++ < WINCE_DELETION_ATTEMPTS
  837. ){
  838. Sleep(100); /* Wait a little before trying again */
  839. }
  840. free(pFile.zDeleteOnClose);
  841. }
  842. #endif
  843. #if SQLITE_TEST
  844. OSTRACE( "CLOSE %d %s\n", pFile.fs.GetHashCode(), rc ? "ok" : "failed" );
  845. OpenCounter( -1 );
  846. #endif
  847. return rc ? SQLITE_OK : winLogError(SQLITE_IOERR_CLOSE, "winClose", pFile.zPath);
  848. }
  849. /*
  850. ** Read data from a file into a buffer. Return SQLITE_OK if all
  851. ** bytes were read successfully and SQLITE_IOERR if anything goes
  852. ** wrong.
  853. */
  854. static int winRead(
  855. sqlite3_file id, /* File to read from */
  856. byte[] pBuf, /* Write content into this buffer */
  857. int amt, /* Number of bytes to read */
  858. sqlite3_int64 offset /* Begin reading at this offset */
  859. )
  860. {
  861. long rc;
  862. sqlite3_file pFile = id;
  863. int nRead; /* Number of bytes actually read from file */
  864. Debug.Assert( id != null );
  865. #if SQLITE_TEST
  866. if ( SimulateIOError() )
  867. return SQLITE_IOERR_READ;
  868. #endif
  869. #if SQLITE_DEBUG
  870. OSTRACE( "READ %d lock=%d\n", pFile.fs.GetHashCode(), pFile.locktype );
  871. #endif
  872. if ( !id.fs.CanRead )
  873. return SQLITE_IOERR_READ;
  874. if ( seekWinFile( pFile, offset ) != 0 )
  875. {
  876. return SQLITE_FULL;
  877. }
  878. try
  879. {
  880. #if SQLITE_WINRT
  881. using (IInputStream inputStream = id.fs.GetInputStreamAt((ulong)offset))
  882. {
  883. IBuffer buffer = pBuf.AsBuffer(0,0,pBuf.Length);
  884. inputStream.ReadAsync(buffer, (uint)amt, InputStreamOptions.None).AsTask().Wait();
  885. nRead = (int)buffer.Length;
  886. }
  887. #else
  888. nRead = id.fs.Read( pBuf, 0, amt ); // i if( null==ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
  889. #endif
  890. }
  891. catch ( Exception e )
  892. {
  893. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  894. pFile.lastErrno = 1;
  895. #else
  896. pFile.lastErrno = (u32)Marshal.GetLastWin32Error();
  897. #endif
  898. return winLogError(SQLITE_IOERR_READ, "winRead", pFile.zPath);
  899. }
  900. if ( nRead < amt )
  901. {
  902. /* Unread parts of the buffer must be zero-filled */
  903. Array.Clear( pBuf, (int)nRead, (int)( amt - nRead ) ); // memset(&((char)pBuf)[nRead], 0, amt-nRead);
  904. return SQLITE_IOERR_SHORT_READ;
  905. }
  906. return SQLITE_OK;
  907. }
  908. /*
  909. ** Write data from a buffer into a file. Return SQLITE_OK on success
  910. ** or some other error code on failure.
  911. */
  912. static int winWrite(
  913. sqlite3_file id, /* File to write into */
  914. byte[] pBuf, /* The bytes to be written */
  915. int amt, /* Number of bytes to write */
  916. sqlite3_int64 offset /* Offset into the file to begin writing at */
  917. )
  918. {
  919. int rc; /* True if error has occured, else false */
  920. sqlite3_file pFile = id; /* File handle */
  921. Debug.Assert( amt > 0 );
  922. Debug.Assert( pFile != null );
  923. #if SQLITE_TEST
  924. if ( SimulateIOError() )
  925. return SQLITE_IOERR_WRITE;
  926. if ( SimulateDiskfullError() )
  927. return SQLITE_FULL;
  928. #endif
  929. #if SQLITE_DEBUG
  930. OSTRACE( "WRITE %d lock=%d\n", id.fs.GetHashCode(), id.locktype );
  931. #endif
  932. rc = seekWinFile( pFile, offset );
  933. //if( rc==0 ){
  934. // u8 *aRem = (u8 )pBuf; /* Data yet to be written */
  935. // int nRem = amt; /* Number of bytes yet to be written */
  936. // DWORD nWrite; /* Bytes written by each WriteFile() call */
  937. // while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
  938. // aRem += nWrite;
  939. // nRem -= nWrite;
  940. // }
  941. #if SQLITE_WINRT
  942. ulong wrote = id.fs.Position;
  943. #else
  944. long wrote = id.fs.Position;
  945. #endif
  946. try
  947. {
  948. Debug.Assert( pBuf.Length >= amt );
  949. #if SQLITE_WINRT
  950. using (IOutputStream outStream = id.fs.GetOutputStreamAt((ulong)offset))
  951. {
  952. outStream.WriteAsync(pBuf.AsBuffer(0, amt)).AsTask().Wait();
  953. outStream.FlushAsync().AsTask().Wait();
  954. wrote = (ulong)amt;
  955. }
  956. #else
  957. id.fs.Write( pBuf, 0, amt );
  958. wrote = id.fs.Position - wrote;
  959. #endif
  960. rc = 1;// Success
  961. }
  962. catch ( IOException e )
  963. {
  964. return SQLITE_READONLY;
  965. }
  966. if ( rc == 0 || amt > (int)wrote )
  967. {
  968. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  969. id.lastErrno = 1;
  970. #else
  971. id.lastErrno = (u32)Marshal.GetLastWin32Error();
  972. #endif
  973. if (( id.lastErrno == ERROR_HANDLE_DISK_FULL )
  974. || ( id.lastErrno == ERROR_DISK_FULL ))
  975. {
  976. return SQLITE_FULL;
  977. }
  978. else
  979. {
  980. return winLogError(SQLITE_IOERR_WRITE, "winWrite", pFile.zPath);
  981. }
  982. }
  983. return SQLITE_OK;
  984. }
  985. /*
  986. ** Truncate an open file to a specified size
  987. */
  988. static int winTruncate( sqlite3_file id, sqlite3_int64 nByte )
  989. {
  990. sqlite3_file pFile = id; /* File handle object */
  991. int rc = SQLITE_OK; /* Return code for this function */
  992. Debug.Assert( pFile != null );
  993. #if SQLITE_DEBUG
  994. #if WINDOWS_PHONE || SQLITE_SILVERLIGHT
  995. OSTRACE( "TRUNCATE %d %lld\n", id.fs.GetHashCode(), nByte );
  996. #else
  997. OSTRACE( "TRUNCATE %s %lld\n", id.fs.Name, nByte );
  998. #endif
  999. #endif
  1000. #if SQLITE_TEST
  1001. if ( SimulateIOError() )
  1002. return SQLITE_IOERR_TRUNCATE;
  1003. if ( SimulateIOError() )
  1004. return SQLITE_IOERR_TRUNCATE;
  1005. #endif
  1006. /* If the user has configured a chunk-size for this file, truncate the
  1007. ** file so that it consists of an integer number of chunks (i.e. the
  1008. ** actual file size after the operation may be larger than the requested
  1009. ** size).
  1010. */
  1011. if ( pFile.szChunk != 0 )
  1012. {
  1013. nByte = ( ( nByte + pFile.szChunk - 1 ) / pFile.szChunk ) * pFile.szChunk;
  1014. }
  1015. /* SetEndOfFile() returns non-zero when successful, or zero when it fails. */
  1016. //if ( seekWinFile( pFile, nByte ) )
  1017. //{
  1018. // rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate1", pFile->zPath);
  1019. //}
  1020. //else if( 0==SetEndOfFile(pFile->h) ){
  1021. // pFile->lastErrno = GetLastError();
  1022. // rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate2", pFile->zPath);
  1023. //}
  1024. try
  1025. {
  1026. #if SQLITE_WINRT
  1027. id.fs.Size = (ulong)nByte;
  1028. #else
  1029. id.fs.SetLength( nByte );
  1030. #endif
  1031. rc = SQLITE_OK;
  1032. }
  1033. catch ( IOException e )
  1034. {
  1035. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1036. id.lastErrno = 1;
  1037. #else
  1038. id.lastErrno = (u32)Marshal.GetLastWin32Error();
  1039. #endif
  1040. rc = winLogError(SQLITE_IOERR_TRUNCATE, "winTruncate2", pFile.zPath);
  1041. }
  1042. OSTRACE( "TRUNCATE %d %lld %s\n", id.fs.GetHashCode(), nByte, rc == SQLITE_OK ? "ok" : "failed" );
  1043. return rc;
  1044. }
  1045. #if SQLITE_TEST
  1046. /*
  1047. ** Count the number of fullsyncs and normal syncs. This is used to test
  1048. ** that syncs and fullsyncs are occuring at the right times.
  1049. */
  1050. #if !TCLSH
  1051. static int sqlite3_sync_count = 0;
  1052. static int sqlite3_fullsync_count = 0;
  1053. #else
  1054. static tcl.lang.Var.SQLITE3_GETSET sqlite3_sync_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite3_sync_count" );
  1055. static tcl.lang.Var.SQLITE3_GETSET sqlite3_fullsync_count = new tcl.lang.Var.SQLITE3_GETSET( "sqlite_fullsync_count" );
  1056. #endif
  1057. #endif
  1058. /*
  1059. ** Make sure all writes to a particular file are committed to disk.
  1060. */
  1061. static int winSync( sqlite3_file id, int flags )
  1062. {
  1063. #if !(NDEBUG) || !(SQLITE_NO_SYNC) || (SQLITE_DEBUG)
  1064. sqlite3_file pFile = (sqlite3_file)id;
  1065. bool rc;
  1066. #else
  1067. UNUSED_PARAMETER(id);
  1068. #endif
  1069. Debug.Assert( pFile != null );
  1070. /* Check that one of SQLITE_SYNC_NORMAL or FULL was passed */
  1071. Debug.Assert( ( flags & 0x0F ) == SQLITE_SYNC_NORMAL
  1072. || ( flags & 0x0F ) == SQLITE_SYNC_FULL
  1073. );
  1074. OSTRACE( "SYNC %d lock=%d\n", pFile.fs.GetHashCode(), pFile.locktype );
  1075. /* Unix cannot, but some systems may return SQLITE_FULL from here. This
  1076. ** line is to test that doing so does not cause any problems.
  1077. */
  1078. #if SQLITE_TEST
  1079. if ( SimulateDiskfullError() )
  1080. return SQLITE_FULL;
  1081. #endif
  1082. #if !SQLITE_TEST
  1083. UNUSED_PARAMETER(flags);
  1084. #else
  1085. if ( (flags&0x0F)==SQLITE_SYNC_FULL )
  1086. {
  1087. #if !TCLSH
  1088. sqlite3_fullsync_count++;
  1089. }
  1090. sqlite3_sync_count++;
  1091. #else
  1092. sqlite3_fullsync_count.iValue++;
  1093. }
  1094. sqlite3_sync_count.iValue++;
  1095. #endif
  1096. #endif
  1097. /* If we compiled with the SQLITE_NO_SYNC flag, then syncing is a
  1098. ** no-op
  1099. */
  1100. #if SQLITE_NO_SYNC
  1101. return SQLITE_OK;
  1102. #else
  1103. #if SQLITE_WINRT
  1104. Stream stream = pFile.fs.AsStreamForWrite();
  1105. stream.Flush();
  1106. #else
  1107. pFile.fs.Flush();
  1108. #endif
  1109. return SQLITE_OK;
  1110. //rc = FlushFileBuffers(pFile->h);
  1111. //SimulateIOError( rc=FALSE );
  1112. //if( rc ){
  1113. // return SQLITE_OK;
  1114. //}else{
  1115. // pFile->lastErrno = GetLastError();
  1116. // return winLogError(SQLITE_IOERR_FSYNC, "winSync", pFile->zPath);
  1117. //}
  1118. #endif
  1119. }
  1120. /*
  1121. ** Determine the current size of a file in bytes
  1122. */
  1123. static int winFileSize( sqlite3_file id, ref long pSize )
  1124. {
  1125. //DWORD upperBits;
  1126. //DWORD lowerBits;
  1127. // sqlite3_file pFile = (sqlite3_file)id;
  1128. // DWORD error;
  1129. Debug.Assert( id != null );
  1130. #if SQLITE_TEST
  1131. if ( SimulateIOError() )
  1132. return SQLITE_IOERR_FSTAT;
  1133. #endif
  1134. //lowerBits = GetFileSize(pFile.fs.Name, upperBits);
  1135. //if ( ( lowerBits == INVALID_FILE_SIZE )
  1136. // && ( ( error = GetLastError() ) != NO_ERROR ) )
  1137. //{
  1138. // pFile.lastErrno = error;
  1139. // return winLogError(SQLITE_IOERR_FSTAT, "winFileSize", pFile->zPath);
  1140. //}
  1141. //pSize = (((sqlite3_int64)upperBits)<<32) + lowerBits;
  1142. #if SQLITE_WINRT
  1143. pSize = id.fs.CanRead ? (long)id.fs.Size : 0;
  1144. #else
  1145. pSize = id.fs.CanRead ? id.fs.Length : 0;
  1146. #endif
  1147. return SQLITE_OK;
  1148. }
  1149. /*
  1150. ** Acquire a reader lock.
  1151. ** Different API routines are called depending on whether or not this
  1152. ** is Win95 or WinNT.
  1153. */
  1154. static int getReadLock( sqlite3_file pFile )
  1155. {
  1156. int res = 0;
  1157. if ( isNT() )
  1158. {
  1159. res = lockingStrategy.SharedLockFile( pFile, SHARED_FIRST, SHARED_SIZE );
  1160. }
  1161. /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
  1162. */
  1163. #if !SQLITE_OS_WINCE
  1164. //else
  1165. //{
  1166. // int lk;
  1167. // sqlite3_randomness(lk.Length, lk);
  1168. // pFile.sharedLockByte = (u16)((lk & 0x7fffffff)%(SHARED_SIZE - 1));
  1169. // res = pFile.fs.Lock( SHARED_FIRST + pFile.sharedLockByte, 0, 1, 0);
  1170. #endif
  1171. //}
  1172. if ( res == 0 )
  1173. {
  1174. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1175. pFile.lastErrno = 1;
  1176. #else
  1177. pFile.lastErrno = (u32)Marshal.GetLastWin32Error();
  1178. #endif
  1179. }
  1180. /* No need to log a failure to lock */
  1181. return res;
  1182. }
  1183. /*
  1184. ** Undo a readlock
  1185. */
  1186. static int unlockReadLock( sqlite3_file pFile )
  1187. {
  1188. int res = 1;
  1189. if ( isNT() )
  1190. {
  1191. try
  1192. {
  1193. lockingStrategy.UnlockFile( pFile, SHARED_FIRST, SHARED_SIZE ); // res = UnlockFile(pFile.h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  1194. }
  1195. catch ( Exception e )
  1196. {
  1197. res = 0;
  1198. }
  1199. }
  1200. /* isNT() is 1 if SQLITE_OS_WINCE==1, so this else is never executed.
  1201. */
  1202. #if !SQLITE_OS_WINCE
  1203. else
  1204. {
  1205. Debugger.Break(); // res = UnlockFile(pFile.h, SHARED_FIRST + pFilE.sharedLockByte, 0, 1, 0);
  1206. }
  1207. #endif
  1208. if ( res == 0 )
  1209. {
  1210. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1211. pFile.lastErrno = 1;
  1212. #else
  1213. pFile.lastErrno = (u32)Marshal.GetLastWin32Error();
  1214. #endif
  1215. winLogError(SQLITE_IOERR_UNLOCK, "unlockReadLock", pFile.zPath);
  1216. }
  1217. return res;
  1218. }
  1219. /*
  1220. ** Lock the file with the lock specified by parameter locktype - one
  1221. ** of the following:
  1222. **
  1223. ** (1) SHARED_LOCK
  1224. ** (2) RESERVED_LOCK
  1225. ** (3) PENDING_LOCK
  1226. ** (4) EXCLUSIVE_LOCK
  1227. **
  1228. ** Sometimes when requesting one lock state, additional lock states
  1229. ** are inserted in between. The locking might fail on one of the later
  1230. ** transitions leaving the lock state different from what it started but
  1231. ** still short of its goal. The following chart shows the allowed
  1232. ** transitions and the inserted intermediate states:
  1233. **
  1234. ** UNLOCKED . SHARED
  1235. ** SHARED . RESERVED
  1236. ** SHARED . (PENDING) . EXCLUSIVE
  1237. ** RESERVED . (PENDING) . EXCLUSIVE
  1238. ** PENDING . EXCLUSIVE
  1239. **
  1240. ** This routine will only increase a lock. The winUnlock() routine
  1241. ** erases all locks at once and returns us immediately to locking level 0.
  1242. ** It is not possible to lower the locking level one step at a time. You
  1243. ** must go straight to locking level 0.
  1244. */
  1245. static int winLock( sqlite3_file id, int locktype )
  1246. {
  1247. int rc = SQLITE_OK; /* Return code from subroutines */
  1248. int res = 1; /* Result of a windows lock call */
  1249. int newLocktype; /* Set pFile.locktype to this value before exiting */
  1250. bool gotPendingLock = false;/* True if we acquired a PENDING lock this time */
  1251. sqlite3_file pFile = (sqlite3_file)id;
  1252. DWORD error = NO_ERROR;
  1253. Debug.Assert( id != null );
  1254. #if SQLITE_DEBUG
  1255. OSTRACE( "LOCK %d %d was %d(%d)\n",
  1256. pFile.fs.GetHashCode(), locktype, pFile.locktype, pFile.sharedLockByte );
  1257. #endif
  1258. /* If there is already a lock of this type or more restrictive on the
  1259. ** OsFile, do nothing. Don't use the end_lock: exit path, as
  1260. ** sqlite3OsEnterMutex() hasn't been called yet.
  1261. */
  1262. if ( pFile.locktype >= locktype )
  1263. {
  1264. return SQLITE_OK;
  1265. }
  1266. /* Make sure the locking sequence is correct
  1267. */
  1268. Debug.Assert( pFile.locktype != NO_LOCK || locktype == SHARED_LOCK );
  1269. Debug.Assert( locktype != PENDING_LOCK );
  1270. Debug.Assert( locktype != RESERVED_LOCK || pFile.locktype == SHARED_LOCK );
  1271. /* Lock the PENDING_LOCK byte if we need to acquire a PENDING lock or
  1272. ** a SHARED lock. If we are acquiring a SHARED lock, the acquisition of
  1273. ** the PENDING_LOCK byte is temporary.
  1274. */
  1275. newLocktype = pFile.locktype;
  1276. if ( pFile.locktype == NO_LOCK
  1277. || ( ( locktype == EXCLUSIVE_LOCK )
  1278. && ( pFile.locktype == RESERVED_LOCK ) )
  1279. )
  1280. {
  1281. int cnt = 3;
  1282. res = 0;
  1283. while ( cnt-- > 0 && res == 0 )//(res = LockFile(pFile.fs.SafeFileHandle.DangerousGetHandle().ToInt32(), PENDING_BYTE, 0, 1, 0)) == 0)
  1284. {
  1285. try
  1286. {
  1287. lockingStrategy.LockFile( pFile, PENDING_BYTE, 1 );
  1288. res = 1;
  1289. }
  1290. catch ( Exception e )
  1291. {
  1292. /* Try 3 times to get the pending lock. The pending lock might be
  1293. ** held by another reader process who will release it momentarily.
  1294. */
  1295. #if SQLITE_DEBUG
  1296. OSTRACE( "could not get a PENDING lock. cnt=%d\n", cnt );
  1297. #endif
  1298. #if SQLITE_WINRT
  1299. System.Threading.Tasks.Task.Delay(1).Wait();
  1300. #else
  1301. Thread.Sleep( 1 );
  1302. #endif
  1303. }
  1304. }
  1305. gotPendingLock = ( res != 0 );
  1306. if ( 0 == res )
  1307. {
  1308. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1309. error = 1;
  1310. #else
  1311. error = (u32)Marshal.GetLastWin32Error();
  1312. #endif
  1313. }
  1314. }
  1315. /* Acquire a shared lock
  1316. */
  1317. if ( locktype == SHARED_LOCK && res != 0 )
  1318. {
  1319. Debug.Assert( pFile.locktype == NO_LOCK );
  1320. res = getReadLock( pFile );
  1321. if ( res != 0 )
  1322. {
  1323. newLocktype = SHARED_LOCK;
  1324. }
  1325. else
  1326. {
  1327. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1328. error = 1;
  1329. #else
  1330. error = (u32)Marshal.GetLastWin32Error();
  1331. #endif
  1332. }
  1333. }
  1334. /* Acquire a RESERVED lock
  1335. */
  1336. if ( ( locktype == RESERVED_LOCK ) && res != 0 )
  1337. {
  1338. Debug.Assert( pFile.locktype == SHARED_LOCK );
  1339. try
  1340. {
  1341. lockingStrategy.LockFile( pFile, RESERVED_BYTE, 1 );//res = LockFile(pFile.fs.SafeFileHandle.DangerousGetHandle().ToInt32(), RESERVED_BYTE, 0, 1, 0);
  1342. newLocktype = RESERVED_LOCK;
  1343. res = 1;
  1344. }
  1345. catch ( Exception e )
  1346. {
  1347. res = 0;
  1348. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1349. error = 1;
  1350. #else
  1351. error = (u32)Marshal.GetLastWin32Error();
  1352. #endif
  1353. }
  1354. if ( res != 0 )
  1355. {
  1356. newLocktype = RESERVED_LOCK;
  1357. }
  1358. else
  1359. {
  1360. #if SQLITE_SILVERLIGHT
  1361. error = 1;
  1362. #else
  1363. error = (u32)Marshal.GetLastWin32Error();
  1364. #endif
  1365. }
  1366. }
  1367. /* Acquire a PENDING lock
  1368. */
  1369. if ( locktype == EXCLUSIVE_LOCK && res != 0 )
  1370. {
  1371. newLocktype = PENDING_LOCK;
  1372. gotPendingLock = false;
  1373. }
  1374. /* Acquire an EXCLUSIVE lock
  1375. */
  1376. if ( locktype == EXCLUSIVE_LOCK && res != 0 )
  1377. {
  1378. Debug.Assert( pFile.locktype >= SHARED_LOCK );
  1379. res = unlockReadLock( pFile );
  1380. #if SQLITE_DEBUG
  1381. OSTRACE( "unreadlock = %d\n", res );
  1382. #endif
  1383. //res = LockFile(pFile.fs.SafeFileHandle.DangerousGetHandle().ToInt32(), SHARED_FIRST, 0, SHARED_SIZE, 0);
  1384. try
  1385. {
  1386. lockingStrategy.LockFile( pFile, SHARED_FIRST, SHARED_SIZE );
  1387. newLocktype = EXCLUSIVE_LOCK;
  1388. res = 1;
  1389. }
  1390. catch ( Exception e )
  1391. {
  1392. res = 0;
  1393. }
  1394. if ( res != 0 )
  1395. {
  1396. newLocktype = EXCLUSIVE_LOCK;
  1397. }
  1398. else
  1399. {
  1400. #if SQLITE_SILVERLIGHT || SQLITE_WINRT
  1401. error = 1;
  1402. #else
  1403. error = (u32)Marshal.GetLastWin32Error();
  1404. #endif
  1405. #if SQLITE_DEBUG
  1406. OSTRACE( "error-code = %d\n", error );
  1407. #endif
  1408. getReadLock( pFile );
  1409. }
  1410. }
  1411. /* If we are holding a PENDING lock that ought to be released, then
  1412. ** release it now.
  1413. */
  1414. if ( gotPendingLock && locktype == SHARED_LOCK )
  1415. {
  1416. lockingStrategy.UnlockFile( pFile, PENDING_BYTE, 1 );
  1417. }
  1418. /* Update the state of the lock has held in the file descriptor then
  1419. ** return the appropriate result code.
  1420. */
  1421. if ( res != 0 )
  1422. {
  1423. rc = SQLITE_OK;
  1424. }
  1425. else
  1426. {
  1427. #if SQLITE_DEBUG
  1428. OSTRACE( "LOCK FAILED %d trying for %d but got %d\n", pFile.fs.GetHashCode(),
  1429. locktype, newLocktype );
  1430. #endif
  1431. pFile.lastErrno = error;
  1432. rc = SQLITE_BUSY;
  1433. }
  1434. pFile.locktype = (u8)newLocktype;
  1435. return rc;
  1436. }
  1437. /*
  1438. ** This routine checks if there is a RESERVED lock held on the specified
  1439. ** file by this or any other process. If such a lock is held, return
  1440. ** non-zero, otherwise zero.
  1441. */
  1442. static int winCheckReservedLock( sqlite3_file id, ref int pResOut )
  1443. {
  1444. int rc;
  1445. sqlite3_file pFile = (sqlite3_file)id;
  1446. if ( SimulateIOError() )
  1447. return SQLITE_IOERR_CHECKRESERVEDLOCK;
  1448. Debug.Assert( id != null );
  1449. if ( pFile.locktype >= RESERVED_LOCK )
  1450. {
  1451. rc = 1;
  1452. #if SQLITE_DEBUG
  1453. #if WINDOWS_PHONE || SQLITE_SILVERLIGHT
  1454. OSTRACE( "TEST WR-LOCK %d %d (local)\n", pFile.fs.GetHashCode(), rc );
  1455. #else
  1456. OSTRACE( "TEST WR-LOCK %s %d (local)\n", pFile.fs.Name, rc );
  1457. #endif
  1458. #endif
  1459. }
  1460. else
  1461. {
  1462. try
  1463. {
  1464. lockingStrategy.LockFile( pFile, RESERVED_BYTE, 1 );
  1465. lockingStrategy.UnlockFile( pFile, RESERVED_BYTE, 1 );
  1466. rc = 1;
  1467. }
  1468. catch ( IOException e )
  1469. {
  1470. rc = 0;
  1471. }
  1472. rc = 1 - rc; // !rc
  1473. #if SQLITE_DEBUG
  1474. OSTRACE( "TEST WR-LOCK %d %d (remote)\n", pFile.fs.GetHashCode(), rc );
  1475. #endif
  1476. }
  1477. pResOut = rc;
  1478. return SQLITE_OK;
  1479. }
  1480. /*
  1481. ** Lower the locking level on file descriptor id to locktype. locktype
  1482. ** must be either NO_LOCK or SHARED_LOCK.
  1483. **
  1484. ** If the locking level of the file descriptor is already at or below
  1485. ** the requested locking level, this routine is a no-op.
  1486. **
  1487. ** It is not possible for this routine to fail if the second argument
  1488. ** is NO_LOCK. If the second argument is SHARED_LOCK then this routine
  1489. ** might return SQLITE_IOERR;
  1490. */
  1491. static int winUnlock( sqlite3_file id, int locktype )
  1492. {
  1493. int type;
  1494. sqlite3_file pFile = (sqlite3_file)id;
  1495. int rc = SQLITE_OK;
  1496. Debug.Assert( pFile != null );
  1497. Debug.Assert( locktype <= SHARED_LOCK );
  1498. #if SQLITE_DEBUG
  1499. OSTRACE( "UNLOCK %d to %d was %d(%d)\n", pFile.fs.GetHashCode(), locktype,
  1500. pFile.locktype, pFile.sharedLockByte );
  1501. #endif
  1502. type = pFile.locktype;
  1503. if ( type >= EXCLUSIVE_LOCK )
  1504. {
  1505. lockingStrategy.UnlockFile( pFile, SHARED_FIRST, SHARED_SIZE ); // UnlockFile(pFile.h, SHARED_FIRST, 0, SHARED_SIZE, 0);
  1506. if ( locktype == SHARED_LOCK && getReadLock( pFile ) == 0 )
  1507. {
  1508. /* This should never happen. We should always be able to
  1509. ** reacquire the read lock */
  1510. rc = winLogError(SQLITE_IOERR_UNLOCK, "winUnlock", pFile.zPath);
  1511. }
  1512. }
  1513. if ( type >= RESERVED_LOCK )
  1514. {
  1515. try
  1516. {
  1517. lockingStrategy.UnlockFile( pFile, RESERVED_BYTE, 1 );// UnlockFile(pFile.h, RESERVED_BYTE, 0, 1, 0);
  1518. }
  1519. catch ( Exception e )
  1520. {
  1521. }
  1522. }
  1523. if ( locktype == NO_LOCK && type >= SHARED_LOCK )
  1524. {
  1525. unlockReadLock( pFile );
  1526. }
  1527. if ( type >= PENDING_LOCK )
  1528. {
  1529. try
  1530. {
  1531. lockingStrategy.UnlockFile( pFile, PENDING_BYTE, 1 );// UnlockFile(pFile.h, PENDING_BYTE, 0, 1, 0);
  1532. }
  1533. catch ( Exception e )
  1534. {
  1535. }
  1536. }
  1537. pFile.locktype = (u8)locktype;
  1538. return rc;
  1539. }
  1540. /*
  1541. ** Control a…

Large files files are truncated, but you can click here to view the full file