/ Changes On Branch winSectorSize
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch winSectorSize Excluding Merge-Ins

This is equivalent to a diff from 97914266cb to 47beb55c5b

2017-01-18
23:12
For Windows 8.x and higher, require the SQLITE_WIN32_WIN8_SECTOR_SIZE compile-time option in order to enable sector size determination. (Leaf check-in: 47beb55c5b user: mistachkin tags: winSectorSize)
19:36
Improve and update comments. (check-in: 2dc16d345b user: mistachkin tags: winSectorSize)
2017-01-16
18:10
Back out check-in [0b3174e0b1364c] and replace it with a better fix for \ticket [91e2e8ba6ff2e2] - a fix that does not cause the problem identified by ticket [7ffd1ca1d2ad4ec]. Add new test cases for both tickets. (check-in: 9b64af7b52 user: drh tags: trunk)
16:01
Add test cases for tickets [91e2e8ba6ff2e2] and [7ffd1ca1d2ad4ec]. (check-in: 9d0dfe0b08 user: drh tags: automatic-index-affinity)
11:54
An example showing how to improve performance of sqlite3VdbeSerialPut() using the GCC intrinsic function __builtin_bswap64(). (Leaf check-in: e42ed9b4ad user: drh tags: builtin-bswap64)
2017-01-13
22:21
Merge updates from trunk. (check-in: 8b42b8e31a user: mistachkin tags: winSectorSize)
18:24
Fix a problem preventing resumption of RBU operations after recovering from a process or system failure that occurs during the incremental-checkpoint phase. (check-in: 97914266cb user: dan tags: trunk)
12:53
Fix the build for SQLITE_ENABLE_MEMORY_MANAGEMENT. (check-in: 8c85b8fdd7 user: drh tags: trunk)

Changes to src/os_win.c.

64
65
66
67
68
69
70








71
72
73
74
75
76
77
 must be defined."
#endif

/*
** Define the required Windows SDK version constants if they are not
** already available.
*/








#ifndef NTDDI_WIN8
#  define NTDDI_WIN8                        0x06020000
#endif

#ifndef NTDDI_WINBLUE
#  define NTDDI_WINBLUE                     0x06030000
#endif







>
>
>
>
>
>
>
>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
 must be defined."
#endif

/*
** Define the required Windows SDK version constants if they are not
** already available.
*/
#ifndef _WIN32_WINNT_VISTA
#  define _WIN32_WINNT_VISTA                0x0600
#endif

#ifndef _WIN32_WINNT_WIN8
#  define _WIN32_WINNT_WIN8                 0x0602
#endif

#ifndef NTDDI_WIN8
#  define NTDDI_WIN8                        0x06020000
#endif

#ifndef NTDDI_WINBLUE
#  define NTDDI_WINBLUE                     0x06030000
#endif
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456






457
458
459
460
461


462
463


464
465
466
467
468
469
470
static int winMemInit(void *pAppData);
static void winMemShutdown(void *pAppData);

const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */

/*
** The following variable is (normally) set once and never changes
** thereafter.  It records whether the operating system is Win9x
** or WinNT.
**
** 0:   Operating system unknown.
** 1:   Operating system is Win9x.
** 2:   Operating system is WinNT.
**






** In order to facilitate testing on a WinNT system, the test fixture
** can manually set this value to 1 to emulate Win98 behavior.
*/
#ifdef SQLITE_TEST
LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;


#else
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;


#endif

#ifndef SYSCALL
#  define SYSCALL sqlite3_syscall_ptr
#endif

/*







|
|
|

|
|
|

>
>
>
>
>
>
|




>
>


>
>







450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
static int winMemInit(void *pAppData);
static void winMemShutdown(void *pAppData);

const sqlite3_mem_methods *sqlite3MemGetWin32(void);
#endif /* SQLITE_WIN32_MALLOC */

/*
** The following variables are (normally) set once and never change
** thereafter.  They record the major and minor OS version and whether
** the operating system type is Win9x or WinNT.
**
** sqlite3_os_type = 0:   Operating system type is unknown.
** sqlite3_os_type = 1:   Operating system type is Win9x.
** sqlite3_os_type = 2:   Operating system type is WinNT.
**
** For the major and minor versions, the following are the "well-known"
** operating system releases (i.e. the ones that are tested for):
**
** sqlite3_os_major.sqlite3_os_minor = 6.0 = Windows Vista
** sqlite3_os_major.sqlite3_os_minor = 6.2 = Windows 8
**
** In order to facilitate testing on WinNT systems, the test fixture
** can manually set this value to 1 to emulate Win98 behavior.
*/
#ifdef SQLITE_TEST
LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
LONG SQLITE_WIN32_VOLATILE sqlite3_os_major = 0;
LONG SQLITE_WIN32_VOLATILE sqlite3_os_minor = 0;
#else
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_type = 0;
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_major = 0;
static LONG SQLITE_WIN32_VOLATILE sqlite3_os_minor = 0;
#endif

#ifndef SYSCALL
#  define SYSCALL sqlite3_syscall_ptr
#endif

/*
1006
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
#else
  { "SetFilePointerEx",        (SYSCALL)0,                       0 },
#endif

#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
        PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)

#if SQLITE_OS_WINRT

  { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
#else
  { "GetFileInformationByHandleEx", (SYSCALL)0,                  0 },
#endif

#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)







|
>







1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
#else
  { "SetFilePointerEx",        (SYSCALL)0,                       0 },
#endif

#define osSetFilePointerEx ((BOOL(WINAPI*)(HANDLE,LARGE_INTEGER, \
        PLARGE_INTEGER,DWORD))aSyscall[65].pCurrent)

#if SQLITE_OS_WINRT || (defined(SQLITE_WIN32_WIN8_SECTOR_SIZE) && \
        defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN8)
  { "GetFileInformationByHandleEx", (SYSCALL)GetFileInformationByHandleEx, 0 },
#else
  { "GetFileInformationByHandleEx", (SYSCALL)0,                  0 },
#endif

#define osGetFileInformationByHandleEx ((BOOL(WINAPI*)(HANDLE, \
        FILE_INFO_BY_HANDLE_CLASS,LPVOID,DWORD))aSyscall[66].pCurrent)
1129
1130
1131
1132
1133
1134
1135

































1136
1137
1138
1139
1140
1141
1142
  { "FlushViewOfFile",          (SYSCALL)FlushViewOfFile,        0 },
#else
  { "FlushViewOfFile",          (SYSCALL)0,                      0 },
#endif

#define osFlushViewOfFile \
        ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)


































}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  { "FlushViewOfFile",          (SYSCALL)FlushViewOfFile,        0 },
#else
  { "FlushViewOfFile",          (SYSCALL)0,                      0 },
#endif

#define osFlushViewOfFile \
        ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)

#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
        _WIN32_WINNT >= _WIN32_WINNT_VISTA
  { "DeviceIoControl",          (SYSCALL)DeviceIoControl,        0 },
#else
  { "DeviceIoControl",          (SYSCALL)0,                      0 },
#endif

#define osDeviceIoControl ((BOOL(WINAPI*)( \
        HANDLE,DWORD,LPVOID,DWORD,LPVOID,DWORD,LPVOID, \
        LPOVERLAPPED))aSyscall[80].pCurrent)

#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
        _WIN32_WINNT >= _WIN32_WINNT_VISTA
  { "GetVolumeInformationByHandleW", (SYSCALL)GetVolumeInformationByHandleW, 0 },
#else
  { "GetVolumeInformationByHandleW", (SYSCALL)0,                 0 },
#endif

#define osGetVolumeInformationByHandleW ((BOOL(WINAPI*)( \
        HANDLE,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR, \
        DWORD))aSyscall[81].pCurrent)

#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && defined(_WIN32_WINNT) && \
        _WIN32_WINNT >= _WIN32_WINNT_VISTA
  { "GetVolumeInformationW",     (SYSCALL)GetVolumeInformationW, 0 },
#else
  { "GetVolumeInformationW",     (SYSCALL)0,                     0 },
#endif

#define osGetVolumeInformationW ((BOOL(WINAPI*)( \
        LPCWSTR,LPWSTR,DWORD,LPDWORD,LPDWORD,LPDWORD,LPWSTR, \
        DWORD))aSyscall[82].pCurrent)

}; /* End of the overrideable system calls */

/*
** This is the xSetSystemCall() method of sqlite3_vfs for all of the
** "win32" VFSes.  Return SQLITE_OK opon successfully updating the
** system call pointer, or SQLITE_NOTFOUND if there is no configurable
1399
1400
1401
1402
1403
1404
1405

























































1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
# define osIsNT()  (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
# define osIsNT()  (0)
#else
# define osIsNT()  ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
#endif


























































/*
** This function determines if the machine is running a version of Windows
** based on the NT kernel.
*/
int sqlite3_win32_is_nt(void){
#if SQLITE_OS_WINRT
  /*
  ** NOTE: The WinRT sub-platform is always assumed to be based on the NT
  **       kernel.
  */
  return 1;
#elif SQLITE_WIN32_GETVERSIONEX
  if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
    OSVERSIONINFOA sInfo;
    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
    osGetVersionExA(&sInfo);
    osInterlockedCompareExchange(&sqlite3_os_type,
        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#elif defined(SQLITE_WIN32_HAS_WIDE)
    OSVERSIONINFOW sInfo;
    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
    osGetVersionExW(&sInfo);
    osInterlockedCompareExchange(&sqlite3_os_type,
        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
#endif
  }
  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#else
  /*
  ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
  **       deprecated are always assumed to be based on the NT kernel.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












<
<
<
<
|
<
<
<
<
<
<
<
<
<
<







1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526




1527










1528
1529
1530
1531
1532
1533
1534
# define osIsNT()  (1)
#elif !defined(SQLITE_WIN32_HAS_WIDE)
# define osIsNT()  (0)
#else
# define osIsNT()  ((sqlite3_os_type==2) || sqlite3_win32_is_nt())
#endif

/*
** This following version checking macros should evaluate to non-zero only
** when running on Windows Vista (or higher) or Windows 8 (or higher).
*/

#if !SQLITE_WIN32_GETVERSIONEX
# define osIsVistaPlus()  (1)
# define osIsWin8Plus()   (1)
#elif SQLITE_OS_WINCE
# define osIsVistaPlus()  (0)
# define osIsWin8Plus()   (0)
#elif SQLITE_OS_WINRT
# define osIsVistaPlus()  (1)
# define osIsWin8Plus()   (1)
#else
# define osIsVistaPlus()  (winGetVersionEx() && ((sqlite3_os_major>6) || \
    ((sqlite3_os_major==6) && (sqlite3_os_minor>=0))))
# define osIsWin8Plus()   (winGetVersionEx() && ((sqlite3_os_major>6) || \
    ((sqlite3_os_major==6) && (sqlite3_os_minor>=2))))
#endif

/*
** This function populates the Windows version information needed by this
** module.  Use of the GetVersionExA or GetVersionExW function is required.
** The return value will be non-zero if version information was queried.
*/
#if SQLITE_WIN32_GETVERSIONEX
static int winGetVersionEx(){
  if( osInterlockedCompareExchange(&sqlite3_os_type, 0, 0)==0 ){
#if defined(SQLITE_WIN32_HAS_ANSI)
    OSVERSIONINFOA sInfo;
    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
    osGetVersionExA(&sInfo);
    osInterlockedCompareExchange(&sqlite3_os_type,
        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
    osInterlockedCompareExchange(&sqlite3_os_major,
        (LONG)sInfo.dwMajorVersion, 0);
    osInterlockedCompareExchange(&sqlite3_os_minor,
        (LONG)sInfo.dwMinorVersion, 0);
    return 1;
#elif defined(SQLITE_WIN32_HAS_WIDE)
    OSVERSIONINFOW sInfo;
    sInfo.dwOSVersionInfoSize = sizeof(sInfo);
    osGetVersionExW(&sInfo);
    osInterlockedCompareExchange(&sqlite3_os_type,
        (sInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) ? 2 : 1, 0);
    osInterlockedCompareExchange(&sqlite3_os_major,
        (LONG)sInfo.dwMajorVersion, 0);
    osInterlockedCompareExchange(&sqlite3_os_minor,
        (LONG)sInfo.dwMinorVersion, 0);
    return 1;
#endif
  }
  return 0;
}
#endif

/*
** This function determines if the machine is running a version of Windows
** based on the NT kernel.
*/
int sqlite3_win32_is_nt(void){
#if SQLITE_OS_WINRT
  /*
  ** NOTE: The WinRT sub-platform is always assumed to be based on the NT
  **       kernel.
  */
  return 1;
#elif SQLITE_WIN32_GETVERSIONEX




  winGetVersionEx();










  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#elif SQLITE_TEST
  return osInterlockedCompareExchange(&sqlite3_os_type, 2, 2)==2;
#else
  /*
  ** NOTE: All sub-platforms where the GetVersionEx[AW] functions are
  **       deprecated are always assumed to be based on the NT kernel.
3534
3535
3536
3537
3538
3539
3540








































3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551










































































3552
3553
3554
3555
3556
3557
3558
    }
#endif
  }
  OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
  return SQLITE_NOTFOUND;
}









































/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and its journal file) that the sector size will be the
** same for both.
*/
static int winSectorSize(sqlite3_file *id){










































































  (void)id;
  return SQLITE_DEFAULT_SECTOR_SIZE;
}

/*
** Return a vector of device characteristics.
*/







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
    }
#endif
  }
  OSTRACE(("FCNTL file=%p, rc=SQLITE_NOTFOUND\n", pFile->h));
  return SQLITE_NOTFOUND;
}

/*
** Same-volume determination for versions of Windows prior to Windows 8
** is untested, undocumented, and unsupported.  All such code is omitted
** unless the SQLITE_WIN32_VISTA_SECTOR_SIZE define is set at compile-time,
** and that compile-time option is off by default and undocumented.  The
** following code is for reference only.
*/

#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && \
    defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
/*
** This function attempts to determine if the specified file resides on the
** same volume as the corresponding root directory.  If not, the specified
** file may be impacted by a hard link, symbolic link, or reparse point (e.g.
** junction).
**
** This function may return false even when the file is on the same volume
** as the corresponding root directory.  This function may return true only
** when there is no doubt that the specified file is on the same volume as
** the corresponding root directory associated with the volume.
*/
static BOOL winIsOnSameVolume(winFile *pFile){
  WCHAR zRoot[] = L"_:\\\0"; /* underscore will be drive letter */
  DWORD dwFileVolumeSerialNumber = 0;
  DWORD dwRootVolumeSerialNumber = 0;

  if ( !osGetVolumeInformationByHandleW(pFile->h, NULL, 0,
                                        &dwFileVolumeSerialNumber, NULL,
                                        NULL, NULL, 0) ){
    return FALSE;
  }
  zRoot[0] = (WCHAR)pFile->zPath[0]; /* 'A' to 'Z' only, upper/lower case */
  if( !osGetVolumeInformationW(zRoot, NULL, 0, &dwRootVolumeSerialNumber,
                               NULL, NULL, NULL, 0) ){
    return FALSE;
  }
  return (dwFileVolumeSerialNumber == dwRootVolumeSerialNumber);
}
#endif

/*
** Return the sector size in bytes of the underlying block device for
** the specified file. This is almost always 512 bytes, but may be
** larger for some devices.
**
** SQLite code assumes this function cannot fail. It also assumes that
** if two files are created in the same file-system directory (i.e.
** a database and its journal file) that the sector size will be the
** same for both.
*/
static int winSectorSize(sqlite3_file *id){
#if defined(SQLITE_WIN32_WIN8_SECTOR_SIZE) && \
    defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_WIN8
  if( osIsWin8Plus() ){
    winFile *pFile = (winFile*)id;
    FILE_STORAGE_INFO info;
    memset(&info, 0, sizeof(FILE_STORAGE_INFO));
    if( osGetFileInformationByHandleEx(pFile->h, FileStorageInfo,
                                       &info, sizeof(info)) ){
      ULONG size = info.FileSystemEffectivePhysicalBytesPerSectorForAtomicity;
      OSTRACE(("SECTOR file=%p, size=%lu\n", pFile->h, size));
      if( size>0 && size<=2147483647 ){
        return (int)size;
      }
    }else{
      pFile->lastErrno = osGetLastError();
      winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
                  "winSectorSize1", pFile->zPath);
    }
  }
#endif

/*
** Sector-size determination for versions of Windows prior to Windows 8
** is untested, undocumented, and unsupported.  All such code is omitted
** unless the SQLITE_WIN32_VISTA_SECTOR_SIZE define is set at compile-time,
** and that compile-time option is off by default and undocumented.  The
** following code is for reference only.
*/

#if defined(SQLITE_WIN32_VISTA_SECTOR_SIZE) && \
    defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
  if( osIsVistaPlus() ){
    winFile *pFile = (winFile*)id;
    if( winIsDriveLetterAndColon(pFile->zPath) && winIsOnSameVolume(pFile) ){
      WCHAR zDisk[] = L"\\\\.\\_:\0"; /* underscore will be drive letter */
      HANDLE hDisk;
      zDisk[4] = (WCHAR)pFile->zPath[0]; /* 'A' to 'Z' only, upper/lower case */
      assert( (zDisk[4]>=L'A' && zDisk[4]<=L'Z')
           || (zDisk[4]>=L'a' && zDisk[4]<=L'z')
      );
      hDisk = osCreateFileW(zDisk, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
      if( hDisk!=NULL ){
        STORAGE_PROPERTY_QUERY query;
        STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR alignment;
        DWORD bytes = 0;
        memset(&query, 0, sizeof(STORAGE_PROPERTY_QUERY));
        memset(&alignment, 0, sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR));
        query.QueryType  = PropertyStandardQuery;
        query.PropertyId = StorageAccessAlignmentProperty;
        if( osDeviceIoControl(hDisk, IOCTL_STORAGE_QUERY_PROPERTY, &query,
                              sizeof(STORAGE_PROPERTY_QUERY), &alignment,
                              sizeof(STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR),
                              &bytes, NULL) ){
          DWORD size = alignment.BytesPerPhysicalSector;
          OSTRACE(("SECTOR file=%p, size=%lu\n", pFile->h, size));
          if( size>0 && size<=2147483647 ){
            return (int)size;
          }
        }else{
          pFile->lastErrno = osGetLastError();
          winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
                      "winSectorSize2", pFile->zPath);
        }
        osCloseHandle(hDisk);
      }else{
        pFile->lastErrno = osGetLastError();
        winLogError(SQLITE_IOERR_FSTAT, pFile->lastErrno,
                    "winSectorSize3", pFile->zPath);
      }
    }
  }
#endif

  (void)id;
  return SQLITE_DEFAULT_SECTOR_SIZE;
}

/*
** Return a vector of device characteristics.
*/
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
    winGetSystemCall,      /* xGetSystemCall */
    winNextSystemCall,     /* xNextSystemCall */
  };
#endif

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==80 );

  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
#if SQLITE_OS_WINRT
  osGetNativeSystemInfo(&winSysInfo);
#else
  osGetSystemInfo(&winSysInfo);







|







6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
    winGetSystemCall,      /* xGetSystemCall */
    winNextSystemCall,     /* xNextSystemCall */
  };
#endif

  /* Double-check that the aSyscall[] array has been constructed
  ** correctly.  See ticket [bb3a86e890c8e96ab] */
  assert( ArraySize(aSyscall)==83 );

  /* get memory map allocation granularity */
  memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
#if SQLITE_OS_WINRT
  osGetNativeSystemInfo(&winSysInfo);
#else
  osGetSystemInfo(&winSysInfo);