mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 17:32:57 -05:00
Compare commits
5 Commits
v2.0B2
...
pvt-idinfo
Author | SHA1 | Date | |
---|---|---|---|
82f84f5bf7 | |||
97c075e744 | |||
874a223bcc | |||
901a98e118 | |||
0ab4300738 |
8
.github/workflows/avm.yml
vendored
8
.github/workflows/avm.yml
vendored
@ -11,8 +11,8 @@ jobs:
|
|||||||
- uses: billziss-gh/avm@v1
|
- uses: billziss-gh/avm@v1
|
||||||
with:
|
with:
|
||||||
files: |
|
files: |
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.6/winfsp-1.6.20027.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.7/winfsp-1.7.20172.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.8/winfsp-1.8.20304.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.9/winfsp-1.9.21096.msi
|
|
||||||
https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
https://github.com/winfsp/winfsp/releases/download/v1.10/winfsp-1.10.22006.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.11/winfsp-1.11.22176.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.12/winfsp-1.12.22301.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v1.12.22339/winfsp-1.12.22339.msi
|
||||||
|
https://github.com/winfsp/winfsp/releases/download/v2.0B2/winfsp-2.0.23033.msi
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
|
|
||||||
<MyCanonicalVersion>2.0</MyCanonicalVersion>
|
<MyCanonicalVersion>2.0</MyCanonicalVersion>
|
||||||
|
|
||||||
<MyProductVersion>2023 Beta2</MyProductVersion>
|
<MyProductVersion>2023 RC1</MyProductVersion>
|
||||||
<MyProductStage>Beta</MyProductStage>
|
<MyProductStage>RC</MyProductStage>
|
||||||
|
|
||||||
<MyCrossCert>DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer</MyCrossCert>
|
<MyCrossCert>DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer</MyCrossCert>
|
||||||
<MyCertIssuer>DigiCert</MyCertIssuer>
|
<MyCertIssuer>DigiCert</MyCertIssuer>
|
||||||
|
@ -205,6 +205,7 @@ static NTSTATUS FspFsvolQueryDirectoryCopy(
|
|||||||
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
|
ASSERT(sizeof(UINT64) == DirectoryMarker->Length);
|
||||||
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
|
DirectoryMarkerFound = DirectoryNextOffset == *(PUINT64)DirectoryMarker->Buffer;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
/* CopyLength is the same as FileName.Length except on STATUS_BUFFER_OVERFLOW */
|
||||||
|
@ -33,6 +33,8 @@ static NTSTATUS FspFsvolQueryBasicInformation(PFILE_OBJECT FileObject,
|
|||||||
static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd,
|
PVOID *PBuffer, PVOID BufferEnd,
|
||||||
const FSP_FSCTL_FILE_INFO *FileInfo);
|
const FSP_FSCTL_FILE_INFO *FileInfo);
|
||||||
|
static NTSTATUS FspFsvolQueryIdInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd);
|
||||||
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd);
|
PVOID *PBuffer, PVOID BufferEnd);
|
||||||
static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryNameInformation(PFILE_OBJECT FileObject,
|
||||||
@ -106,6 +108,7 @@ FAST_IO_QUERY_OPEN FspFastIoQueryOpen;
|
|||||||
#pragma alloc_text(PAGE, FspFsvolQueryAttributeTagInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryAttributeTagInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryBasicInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryBasicInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryEaInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryEaInformation)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolQueryIdInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryInternalInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryInternalInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryNameInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNameInformation)
|
||||||
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
#pragma alloc_text(PAGE, FspFsvolQueryNetworkOpenInformation)
|
||||||
@ -288,6 +291,32 @@ static NTSTATUS FspFsvolQueryEaInformation(PFILE_OBJECT FileObject,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsvolQueryIdInformation(PFILE_OBJECT FileObject,
|
||||||
|
PVOID *PBuffer, PVOID BufferEnd)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
PFILE_ID_INFORMATION Info = (PFILE_ID_INFORMATION)*PBuffer;
|
||||||
|
FSP_FILE_NODE *FileNode = FileObject->FsContext;
|
||||||
|
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
|
||||||
|
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT64 IndexNumber;
|
||||||
|
FILE_ID_128 FileId;
|
||||||
|
} FileIdBuf = { .IndexNumber = FileNode->IndexNumber };
|
||||||
|
|
||||||
|
if ((PVOID)(Info + 1) > BufferEnd)
|
||||||
|
return STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
Info->VolumeSerialNumber = FsvolDeviceExtension->VolumeParams.VolumeSerialNumber;
|
||||||
|
Info->FileId = FileIdBuf.FileId;
|
||||||
|
|
||||||
|
*PBuffer = (PVOID)(Info + 1);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
static NTSTATUS FspFsvolQueryInternalInformation(PFILE_OBJECT FileObject,
|
||||||
PVOID *PBuffer, PVOID BufferEnd)
|
PVOID *PBuffer, PVOID BufferEnd)
|
||||||
{
|
{
|
||||||
@ -961,6 +990,10 @@ static NTSTATUS FspFsvolQueryInformation(
|
|||||||
case FileHardLinkInformation:
|
case FileHardLinkInformation:
|
||||||
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
|
Result = STATUS_NOT_SUPPORTED; /* no hard link support */
|
||||||
return Result;
|
return Result;
|
||||||
|
case FileIdInformation:
|
||||||
|
Result = FspFsvolQueryIdInformation(FileObject, &Buffer, BufferEnd);
|
||||||
|
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
return Result;
|
||||||
case FileInternalInformation:
|
case FileInternalInformation:
|
||||||
Result = FspFsvolQueryInternalInformation(FileObject, &Buffer, BufferEnd);
|
Result = FspFsvolQueryInternalInformation(FileObject, &Buffer, BufferEnd);
|
||||||
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
Irp->IoStatus.Information = (UINT_PTR)((PUINT8)Buffer - (PUINT8)Irp->AssociatedIrp.SystemBuffer);
|
||||||
|
@ -68,6 +68,27 @@ function Get-ReleaseInfo ($Tag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-HwapiCredentials {
|
||||||
|
$Credentials = (& "$ProjectRoot\tools\wincred.ps1" get "Hardware Dashboard API")
|
||||||
|
if ($Credentials) {
|
||||||
|
try { $Credentials = ConvertFrom-Json $Credentials[1] } catch {;}
|
||||||
|
}
|
||||||
|
if ($Credentials -and $Credentials.TenantId -and $Credentials.ClientId -and $Credentials.ClientId) {
|
||||||
|
return $Credentials
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Start-Sdcm {
|
||||||
|
Start-Job -ArgumentList $args -ScriptBlock {
|
||||||
|
$env:SDCM_CREDS_TENANTID = $using:HwapiCredentials.TenantId
|
||||||
|
$env:SDCM_CREDS_CLIENTID = $using:HwapiCredentials.ClientId
|
||||||
|
$env:SDCM_CREDS_KEY = $using:HwapiCredentials.Key
|
||||||
|
$env:SDCM_CREDS_URL = "https://manage.devcenter.microsoft.com"
|
||||||
|
$env:SDCM_CREDS_URLPREFIX = "v2.0/my"
|
||||||
|
& "$using:ProjectRoot\..\winfsp.sdcm\SurfaceDevCenterManager\bin\Debug\sdcm.exe" -creds envonly @args
|
||||||
|
} | Receive-Job -Wait -AutoRemoveJob
|
||||||
|
}
|
||||||
|
|
||||||
function Get-FileVersion ($FileName) {
|
function Get-FileVersion ($FileName) {
|
||||||
return [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FileName).FileVersion
|
return [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FileName).FileVersion
|
||||||
}
|
}
|
||||||
@ -96,6 +117,12 @@ function Check-Prerequisites {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check scdm.exe
|
||||||
|
if (!(Get-Command "$ProjectRoot\..\winfsp.sdcm\SurfaceDevCenterManager\bin\Debug\sdcm.exe" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find sdcm.exe"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# check gh.exe
|
# check gh.exe
|
||||||
if (!(Get-Command "gh.exe" -ErrorAction SilentlyContinue)) {
|
if (!(Get-Command "gh.exe" -ErrorAction SilentlyContinue)) {
|
||||||
Write-Stderr "error: cannot find gh.exe"
|
Write-Stderr "error: cannot find gh.exe"
|
||||||
@ -137,6 +164,17 @@ function Check-Prerequisites {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# check hardware dashboard api credentials
|
||||||
|
$script:HwapiCredentials = Get-HwapiCredentials
|
||||||
|
if (!$script:HwapiCredentials) {
|
||||||
|
Write-Stderr "error: cannot get Hardware Dashboard API credentials"
|
||||||
|
Write-Stderr ' The expected format of the credentials is as follows:'
|
||||||
|
Write-Stderr ' TargetName: Hardware Dashboard API'
|
||||||
|
Write-Stderr ' UserName: Credentials'
|
||||||
|
Write-Stderr ' Password: {"TenantId":"TENANTID","ClientId":"CLIENTID","Key":"KEY"}'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
if ($State -contains $Name) {
|
if ($State -contains $Name) {
|
||||||
if (!($State -contains "$Tag-$CommitCount-g$Commit")) {
|
if (!($State -contains "$Tag-$CommitCount-g$Commit")) {
|
||||||
Write-Stderr "error: invalid state for tag $Tag"
|
Write-Stderr "error: invalid state for tag $Tag"
|
||||||
@ -149,6 +187,12 @@ function Check-Prerequisites {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Check-Assets {
|
function Check-Assets {
|
||||||
|
# check driver.cab
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\driver.cab" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot find driver.cab"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
# check winfsp.msi
|
# check winfsp.msi
|
||||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi" -ErrorAction SilentlyContinue)) {
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi" -ErrorAction SilentlyContinue)) {
|
||||||
Write-Stderr "error: cannot find winfsp*.msi"
|
Write-Stderr "error: cannot find winfsp*.msi"
|
||||||
@ -192,8 +236,215 @@ function Build-AssetsPhase1 {
|
|||||||
|
|
||||||
Write-Stdout @"
|
Write-Stdout @"
|
||||||
|
|
||||||
Upload file driver.cab to Microsoft Partner Center for attestation signing.
|
Assets have been built but are not properly signed.
|
||||||
When the file has been signed, download and extract to ~\Downloads\drivers
|
Signable assets are ready for submission to the hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Submit-AssetsToHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$MsiFile = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi"
|
||||||
|
$MsiName = Split-Path -Leaf $MsiFile
|
||||||
|
if ($MsiName -match "winfsp-(.+)\.msi") {
|
||||||
|
$Version = $matches[1]
|
||||||
|
}
|
||||||
|
if (!$Version) {
|
||||||
|
Write-Stderr "error: cannot determine version for winfsp.msi"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$DocRequestedSignatures = @()
|
||||||
|
$Documentation = Invoke-WebRequest -Uri "https://raw.githubusercontent.com/MicrosoftDocs/windows-driver-docs/staging/windows-driver-docs-pr/dashboard/get-product-data.md"
|
||||||
|
$Documentation = $Documentation.Content
|
||||||
|
$List = $false
|
||||||
|
foreach ($Line in $Documentation -Split "`n") {
|
||||||
|
if ($Line -match "^### List of Operating System Codes") {
|
||||||
|
$List = $true
|
||||||
|
} elseif ($Line -match "^###") {
|
||||||
|
$List = $false
|
||||||
|
} elseif ($List -and $Line -cmatch "\| *(WINDOWS_v100_[^| ]+) *\|") {
|
||||||
|
$DocRequestedSignatures += $matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($DocRequestedSignatures.length -lt 32) {
|
||||||
|
Write-Stderr "error: cannot determine signatures to request"
|
||||||
|
Write-Stderr ' Does the document at the URL below still contain a "List of Operating System Codes":'
|
||||||
|
Write-Stderr " https://raw.githubusercontent.com/MicrosoftDocs/windows-driver-docs/staging/windows-driver-docs-pr/dashboard/get-product-data.md"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# start with the base signatures and add any new ones found in the docs
|
||||||
|
$RequestedSignatures = @(
|
||||||
|
"WINDOWS_v100_TH2_FULL"
|
||||||
|
"WINDOWS_v100_X64_TH2_FULL"
|
||||||
|
"WINDOWS_v100_RS1_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS1_FULL"
|
||||||
|
"WINDOWS_v100_RS2_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS2_FULL"
|
||||||
|
"WINDOWS_v100_RS3_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS3_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS3_FULL"
|
||||||
|
"WINDOWS_v100_RS4_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS4_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS4_FULL"
|
||||||
|
"WINDOWS_v100_RS5_FULL"
|
||||||
|
"WINDOWS_v100_X64_RS5_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_RS5_FULL"
|
||||||
|
"WINDOWS_v100_19H1_FULL"
|
||||||
|
"WINDOWS_v100_X64_19H1_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_19H1_FULL"
|
||||||
|
"WINDOWS_v100_VB_FULL"
|
||||||
|
"WINDOWS_v100_X64_VB_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_VB_FULL"
|
||||||
|
"WINDOWS_v100_X64_CO_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_CO_FULL"
|
||||||
|
"WINDOWS_v100_X64_NI_FULL"
|
||||||
|
"WINDOWS_v100_ARM64_NI_FULL"
|
||||||
|
)
|
||||||
|
foreach ($Signature in $DocRequestedSignatures) {
|
||||||
|
if ($RequestedSignatures -contains $Signature) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature.Contains("_SERVER_")) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature -eq "WINDOWS_v100_TH1_FULL") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if ($Signature -eq "WINDOWS_v100_X64_TH1_FULL") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$RequestedSignatures += $Signature
|
||||||
|
Write-Stdout "New doc signature: $Signature"
|
||||||
|
}
|
||||||
|
|
||||||
|
$CreateProduct = @{
|
||||||
|
createType = "product"
|
||||||
|
createProduct = @{
|
||||||
|
productName = "winfsp-$Version"
|
||||||
|
testHarness = "attestation"
|
||||||
|
deviceType = "internalExternal"
|
||||||
|
requestedSignatures = $RequestedSignatures
|
||||||
|
# deviceMetaDataIds = $null
|
||||||
|
# firmwareVersion = "0"
|
||||||
|
# isTestSign = $false
|
||||||
|
# isFlightSign = $false
|
||||||
|
# markettingNames = $null
|
||||||
|
# selectedProductTypes = $null
|
||||||
|
# additionalAttributes = $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$CreateSubmission = @{
|
||||||
|
createType = "submission"
|
||||||
|
createSubmission = @{
|
||||||
|
name = "winfsp-$Version"
|
||||||
|
type = "initial"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
New-Item "$ProjectRoot\build\VStudio\build\Release\hwapi" -Type Directory -ErrorAction SilentlyContinue >$null
|
||||||
|
ConvertTo-Json $CreateProduct | Out-File -Encoding Ascii "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateProduct.json"
|
||||||
|
ConvertTo-Json $CreateSubmission | Out-File -Encoding Ascii "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateSubmission.json"
|
||||||
|
|
||||||
|
Start-Sdcm -create "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateProduct.json" | Tee-Object -Variable Output
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot create product on hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if (-not ([string]$Output -match "--- Product: (\d+)")) {
|
||||||
|
Write-Stderr "error: cannot get product id from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$ProductId = $matches[1]
|
||||||
|
|
||||||
|
Start-Sdcm -create "$ProjectRoot\build\VStudio\build\Release\hwapi\CreateSubmission.json" -productid $ProductId | Tee-Object -Variable Output
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot create submission on hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if (-not ([string]$Output -match "---- Submission: (\d+)")) {
|
||||||
|
Write-Stderr "error: cannot get submission id from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$SubmissionId = $matches[1]
|
||||||
|
|
||||||
|
Set-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId" -Value $ProductId
|
||||||
|
Set-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId" -Value $SubmissionId
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Product submission has been prepared on hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Upload-AssetsToHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$ProductId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId"
|
||||||
|
$SubmissionId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId"
|
||||||
|
|
||||||
|
Start-Sdcm -upload "$ProjectRoot\build\VStudio\build\Release\driver.cab" -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot upload driver.cab to hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sdcm -commit -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot commit submission to hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Signable assets have been uploaded to the hardware dashboard.
|
||||||
|
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Download-AssetsFromHwapi {
|
||||||
|
Task -ScriptBlock {
|
||||||
|
Check-Assets
|
||||||
|
|
||||||
|
$ProductId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\ProductId"
|
||||||
|
$SubmissionId = Get-Content "$ProjectRoot\build\VStudio\build\Release\hwapi\SubmissionId"
|
||||||
|
|
||||||
|
Remove-Item -Force "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Recurse -Force "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
Start-Sdcm -download "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -productid $ProductId -submissionid $SubmissionId
|
||||||
|
if ($LastExitCode -ne 0) {
|
||||||
|
Write-Stderr "error: cannot download signed drivers from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot download signed drivers from hardware dashboard"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$ExpandError = ""
|
||||||
|
Expand-Archive "$ProjectRoot\build\VStudio\build\Release\hwapi\Signed-$SubmissionId.zip" -DestinationPath "$ProjectRoot\build\VStudio\build\Release\hwapi" -ErrorVariable ExpandError
|
||||||
|
if ($ExpandError) {
|
||||||
|
Write-Stderr "error: cannot expand signed drivers archive"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Stderr "error: cannot expand signed drivers archive"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Stdout @"
|
||||||
|
|
||||||
|
Signable assets have been downloaded and can be used to complete the build.
|
||||||
|
|
||||||
"@
|
"@
|
||||||
}
|
}
|
||||||
@ -204,16 +455,16 @@ function Build-AssetsPhase2 {
|
|||||||
Check-Assets
|
Check-Assets
|
||||||
|
|
||||||
# check signed drivers folder
|
# check signed drivers folder
|
||||||
if (!(Test-Path ~\Downloads\drivers -ErrorAction SilentlyContinue)) {
|
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers" -ErrorAction SilentlyContinue)) {
|
||||||
Write-Stderr "error: cannot find ~\Downloads\drivers"
|
Write-Stderr "error: cannot find hwapi\drivers"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
$SignedPackage = Resolve-Path ~\Downloads\drivers
|
$SignedPackage = Resolve-Path "$ProjectRoot\build\VStudio\build\Release\hwapi\drivers"
|
||||||
|
|
||||||
$VerX64 = Get-FileVersion "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys"
|
$VerX64 = Get-FileVersion "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys"
|
||||||
if ($VerX64 -ne (Get-FileVersion "$SignedPackage\x64\winfsp-x64.sys")) {
|
if ($VerX64 -ne (Get-FileVersion "$SignedPackage\x64\winfsp-x64.sys")) {
|
||||||
Write-Stderr "error: incompatible versions in ~\Downloads\drivers"
|
Write-Stderr "error: incompatible versions in hwapi\drivers"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,8 +626,12 @@ Check-Prerequisites
|
|||||||
|
|
||||||
# Workflow tasks
|
# Workflow tasks
|
||||||
Build-AssetsPhase1
|
Build-AssetsPhase1
|
||||||
|
Submit-AssetsToHwapi
|
||||||
|
Upload-AssetsToHwapi
|
||||||
|
Download-AssetsFromHwapi
|
||||||
Build-AssetsPhase2
|
Build-AssetsPhase2
|
||||||
Make-GitHubRelease
|
Make-GitHubRelease
|
||||||
Upload-Symbols
|
Upload-Symbols
|
||||||
Make-NugetRelease
|
Make-NugetRelease
|
||||||
Make-ChocoRelease
|
Make-ChocoRelease
|
||||||
|
Write-Stdout "ALL COMPLETE"
|
||||||
|
124
tools/wincred.ps1
Normal file
124
tools/wincred.ps1
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
Start-Job -ArgumentList $args -ScriptBlock {
|
||||||
|
param (
|
||||||
|
[ValidateSet("get", "set", "del")]
|
||||||
|
[string]$Command
|
||||||
|
)
|
||||||
|
|
||||||
|
Add-Type -TypeDefinition @"
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
namespace Win32
|
||||||
|
{
|
||||||
|
public class Api
|
||||||
|
{
|
||||||
|
public static String[] CredRead(
|
||||||
|
String TargetName)
|
||||||
|
{
|
||||||
|
String[] Result = null;
|
||||||
|
IntPtr CredentialPtr;
|
||||||
|
if (CredReadW(TargetName, 1/*CRED_TYPE_GENERIC*/, 0, out CredentialPtr))
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential = Marshal.PtrToStructure<CREDENTIALW>(CredentialPtr);
|
||||||
|
Result = new String[2]{
|
||||||
|
Credential.UserName,
|
||||||
|
Marshal.PtrToStringUni(
|
||||||
|
Credential.CredentialBlob, (int)Credential.CredentialBlobSize / 2)
|
||||||
|
};
|
||||||
|
CredFree(CredentialPtr);
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
public static Boolean CredWrite(
|
||||||
|
String TargetName,
|
||||||
|
String UserName,
|
||||||
|
String Password)
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential = new CREDENTIALW{
|
||||||
|
Type = 1/*CRED_TYPE_GENERIC*/,
|
||||||
|
Persist = 2/*CRED_PERSIST_LOCAL_MACHINE*/,
|
||||||
|
TargetName = TargetName,
|
||||||
|
UserName = UserName,
|
||||||
|
CredentialBlobSize = (UInt32)Password.Length * 2,
|
||||||
|
CredentialBlob = Marshal.StringToCoTaskMemUni(Password),
|
||||||
|
};
|
||||||
|
Boolean Result = CredWriteW(ref Credential, 0);
|
||||||
|
Marshal.FreeCoTaskMem(Credential.CredentialBlob);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
public static Boolean CredDelete(
|
||||||
|
String TargetName)
|
||||||
|
{
|
||||||
|
return CredDeleteW(TargetName, 1/*CRED_TYPE_GENERIC*/, 0);
|
||||||
|
}
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredReadW(
|
||||||
|
String TargetName,
|
||||||
|
UInt32 Type,
|
||||||
|
UInt32 Flags,
|
||||||
|
out IntPtr Credential);
|
||||||
|
[DllImport("advapi32.dll")]
|
||||||
|
private static extern void CredFree(
|
||||||
|
IntPtr Buffer);
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredWriteW(
|
||||||
|
ref CREDENTIALW Credential,
|
||||||
|
UInt32 Flags);
|
||||||
|
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError=true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.U1)]
|
||||||
|
private static extern Boolean CredDeleteW(
|
||||||
|
String TargetName,
|
||||||
|
UInt32 Type,
|
||||||
|
UInt32 Flags);
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
private struct CREDENTIALW
|
||||||
|
{
|
||||||
|
public UInt32 Flags;
|
||||||
|
public UInt32 Type;
|
||||||
|
public String TargetName;
|
||||||
|
public String Comment;
|
||||||
|
public UInt64 LastWritten;
|
||||||
|
public UInt32 CredentialBlobSize;
|
||||||
|
public IntPtr CredentialBlob;
|
||||||
|
public UInt32 Persist;
|
||||||
|
public UInt32 AttributeCount;
|
||||||
|
public IntPtr Attributes;
|
||||||
|
public String TargetAlias;
|
||||||
|
public String UserName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
"@
|
||||||
|
|
||||||
|
function Get-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredRead($TargetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName,
|
||||||
|
[Parameter(Mandatory)][string]$UserName,
|
||||||
|
[Parameter(Mandatory)][string]$Password
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredWrite($TargetName, $UserName, $Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Delete-WindowsCredential {
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory)][string]$TargetName
|
||||||
|
)
|
||||||
|
return [Win32.Api]::CredDelete($TargetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
$Function = @{
|
||||||
|
"get" = "Get-WindowsCredential"
|
||||||
|
"set" = "Set-WindowsCredential"
|
||||||
|
"del" = "Delete-WindowsCredential"
|
||||||
|
}[$Command]
|
||||||
|
& $Function @args
|
||||||
|
|
||||||
|
} | Receive-Job -Wait -AutoRemoveJob
|
@ -38,6 +38,7 @@ enum
|
|||||||
MemfsCaseInsensitive = 0x80000000,
|
MemfsCaseInsensitive = 0x80000000,
|
||||||
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
MemfsFlushAndPurgeOnCleanup = 0x40000000,
|
||||||
MemfsLegacyUnlinkRename = 0x20000000,
|
MemfsLegacyUnlinkRename = 0x20000000,
|
||||||
|
MemfsNoSlowio = 0x10000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
#define MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl, PMemfs)\
|
||||||
|
@ -28,6 +28,52 @@
|
|||||||
|
|
||||||
#include "winfsp-tests.h"
|
#include "winfsp-tests.h"
|
||||||
|
|
||||||
|
typedef struct _FILE_FULL_DIR_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG FileIndex;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
ULONG EaSize;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_FULL_DIR_INFORMATION, *PFILE_FULL_DIR_INFORMATION;
|
||||||
|
|
||||||
|
typedef struct _FILE_DIRECTORY_INFORMATION
|
||||||
|
{
|
||||||
|
ULONG NextEntryOffset;
|
||||||
|
ULONG FileIndex;
|
||||||
|
LARGE_INTEGER CreationTime;
|
||||||
|
LARGE_INTEGER LastAccessTime;
|
||||||
|
LARGE_INTEGER LastWriteTime;
|
||||||
|
LARGE_INTEGER ChangeTime;
|
||||||
|
LARGE_INTEGER EndOfFile;
|
||||||
|
LARGE_INTEGER AllocationSize;
|
||||||
|
ULONG FileAttributes;
|
||||||
|
ULONG FileNameLength;
|
||||||
|
WCHAR FileName[1];
|
||||||
|
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
NtQueryDirectoryFile (
|
||||||
|
HANDLE FileHandle,
|
||||||
|
HANDLE Event,
|
||||||
|
PIO_APC_ROUTINE ApcRoutine,
|
||||||
|
PVOID ApcContext,
|
||||||
|
PIO_STATUS_BLOCK IoStatusBlock,
|
||||||
|
PVOID FileInformation,
|
||||||
|
ULONG Length,
|
||||||
|
FILE_INFORMATION_CLASS FileInformationClass,
|
||||||
|
BOOLEAN ReturnSingleEntry,
|
||||||
|
PUNICODE_STRING FileName,
|
||||||
|
BOOLEAN RestartScan);
|
||||||
|
|
||||||
static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -269,6 +315,212 @@ void querydir_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t hash_chars(const wchar_t *s, size_t length)
|
||||||
|
{
|
||||||
|
/* djb2: see http://www.cse.yorku.ca/~oz/hash.html */
|
||||||
|
size_t h = 5381;
|
||||||
|
for (const wchar_t *t = s + length; t > s; ++s)
|
||||||
|
h = 33 * h + *s;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
static NTSTATUS querydir_nodup_dotest_thread_loop(void *FilePath)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
void *Buffer = 0;
|
||||||
|
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||||
|
IO_STATUS_BLOCK IoStatus;
|
||||||
|
size_t hash[64], hash_count = 0;
|
||||||
|
|
||||||
|
Buffer = malloc(4096);
|
||||||
|
if (0 == Buffer)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle = CreateFileW(
|
||||||
|
FilePath,
|
||||||
|
FILE_LIST_DIRECTORY,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
0,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_FLAG_BACKUP_SEMANTICS,
|
||||||
|
0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Handle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Result = NtQueryDirectoryFile(
|
||||||
|
Handle,
|
||||||
|
0, 0, 0,
|
||||||
|
&IoStatus,
|
||||||
|
Buffer,
|
||||||
|
4096,
|
||||||
|
2/*FileFullDirectoryInformation*/,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
FALSE);
|
||||||
|
if (STATUS_NO_MORE_FILES == Result)
|
||||||
|
break;
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
for (FILE_FULL_DIR_INFORMATION *DirInfo = Buffer;;
|
||||||
|
DirInfo = (PVOID)((PUINT8)DirInfo + DirInfo->NextEntryOffset))
|
||||||
|
{
|
||||||
|
size_t h = hash_chars(DirInfo->FileName, DirInfo->FileNameLength / sizeof(WCHAR));
|
||||||
|
for (size_t i = 0; hash_count > i; i++)
|
||||||
|
if (hash[i] == h)
|
||||||
|
{
|
||||||
|
WCHAR FileName[256];
|
||||||
|
memcpy(FileName, DirInfo->FileName, DirInfo->FileNameLength);
|
||||||
|
FileName[DirInfo->FileNameLength / sizeof(WCHAR)] = L'\0';
|
||||||
|
FspDebugLog(__FUNCTION__ ": duplicate \"%S\"\n", FileName);
|
||||||
|
Result = STATUS_UNSUCCESSFUL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (sizeof hash / sizeof hash[0] > hash_count)
|
||||||
|
hash[hash_count++] = h;
|
||||||
|
if (0 == DirInfo->NextEntryOffset)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Handle)
|
||||||
|
CloseHandle(Handle);
|
||||||
|
|
||||||
|
free(Buffer);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
static unsigned __stdcall querydir_nodup_dotest_thread(void *FilePath)
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": \"%S\"\n", FilePath);
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
for (size_t i = 0; 5000 > i; i++)
|
||||||
|
{
|
||||||
|
Result = querydir_nodup_dotest_thread_loop(FilePath);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void querydir_nodup_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
||||||
|
{
|
||||||
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
|
|
||||||
|
static WCHAR *FileNames[] =
|
||||||
|
{
|
||||||
|
L"Extensions.cs",
|
||||||
|
L"JsonSchema.cs",
|
||||||
|
L"JsonSchemaBuilder.cs",
|
||||||
|
L"JsonSchemaConstants.cs",
|
||||||
|
L"JsonSchemaException.cs",
|
||||||
|
L"JsonSchemaGenerator.cs",
|
||||||
|
L"JsonSchemaModel.cs",
|
||||||
|
L"JsonSchemaModelBuilder.cs",
|
||||||
|
L"JsonSchemaNode.cs",
|
||||||
|
L"JsonSchemaNodeCollection.cs",
|
||||||
|
L"JsonSchemaResolver.cs",
|
||||||
|
L"JsonSchemaType.cs",
|
||||||
|
L"JsonSchemaWriter.cs",
|
||||||
|
L"UndefinedSchemaIdHandling.cs",
|
||||||
|
L"ValidationEventArgs.cs",
|
||||||
|
L"ValidationEventHandler.cs",
|
||||||
|
};
|
||||||
|
HANDLE Handle;
|
||||||
|
BOOL Success;
|
||||||
|
WCHAR FilePath[MAX_PATH];
|
||||||
|
HANDLE Threads[2];
|
||||||
|
DWORD ExitCode;
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
Success = CreateDirectoryW(FilePath, 0);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof FileNames / sizeof FileNames[0] > i; i++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0\\%s",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileNames[i]);
|
||||||
|
Handle = CreateFileW(FilePath, GENERIC_ALL, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||||
|
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||||
|
Success = CloseHandle(Handle);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
for (size_t i = 0; sizeof Threads / sizeof Threads[0] > i; i++)
|
||||||
|
{
|
||||||
|
Threads[i] = (HANDLE)_beginthreadex(0, 0, querydir_nodup_dotest_thread, FilePath, 0, 0);
|
||||||
|
ASSERT(0 != Threads[i]);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; sizeof Threads / sizeof Threads[0] > i; i++)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(Threads[i], INFINITE);
|
||||||
|
GetExitCodeThread(Threads[i], &ExitCode);
|
||||||
|
CloseHandle(Threads[i]);
|
||||||
|
ASSERT(0 == ExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; sizeof FileNames / sizeof FileNames[0] > i; i++)
|
||||||
|
{
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0\\%s",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs), FileNames[i]);
|
||||||
|
Success = DeleteFileW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\dir0",
|
||||||
|
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : memfs_volumename(memfs));
|
||||||
|
Success = RemoveDirectoryW(FilePath);
|
||||||
|
ASSERT(Success);
|
||||||
|
|
||||||
|
memfs_stop(memfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void querydir_nodup_test(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Test GitHub issue #475. Credit for the investigation and reproduction
|
||||||
|
* of this issue goes to GitHub user @hach-que.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (NtfsTests)
|
||||||
|
{
|
||||||
|
WCHAR DirBuf[MAX_PATH];
|
||||||
|
GetTestDirectory(DirBuf);
|
||||||
|
querydir_nodup_dotest(-1, DirBuf, 0);
|
||||||
|
}
|
||||||
|
if (WinFspDiskTests)
|
||||||
|
{
|
||||||
|
querydir_nodup_dotest(MemfsDisk | MemfsNoSlowio, 0, 0);
|
||||||
|
querydir_nodup_dotest(MemfsDisk | MemfsNoSlowio, 0, 1000);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
if (WinFspNetTests)
|
||||||
|
{
|
||||||
|
querydir_nodup_dotest(MemfsNet | MemfsNoSlowio, L"\\\\memfs\\share", 0);
|
||||||
|
querydir_nodup_dotest(MemfsNet | MemfsNoSlowio, L"\\\\memfs\\share", 1000);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void querydir_single_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_single_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -368,36 +620,6 @@ void querydir_expire_cache_test(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _FILE_DIRECTORY_INFORMATION {
|
|
||||||
ULONG NextEntryOffset;
|
|
||||||
ULONG FileIndex;
|
|
||||||
LARGE_INTEGER CreationTime;
|
|
||||||
LARGE_INTEGER LastAccessTime;
|
|
||||||
LARGE_INTEGER LastWriteTime;
|
|
||||||
LARGE_INTEGER ChangeTime;
|
|
||||||
LARGE_INTEGER EndOfFile;
|
|
||||||
LARGE_INTEGER AllocationSize;
|
|
||||||
ULONG FileAttributes;
|
|
||||||
ULONG FileNameLength;
|
|
||||||
WCHAR FileName[1];
|
|
||||||
} FILE_DIRECTORY_INFORMATION, *PFILE_DIRECTORY_INFORMATION;
|
|
||||||
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
NtQueryDirectoryFile (
|
|
||||||
_In_ HANDLE FileHandle,
|
|
||||||
_In_opt_ HANDLE Event,
|
|
||||||
_In_opt_ PIO_APC_ROUTINE ApcRoutine,
|
|
||||||
_In_opt_ PVOID ApcContext,
|
|
||||||
_Out_ PIO_STATUS_BLOCK IoStatusBlock,
|
|
||||||
_Out_writes_bytes_(Length) PVOID FileInformation,
|
|
||||||
_In_ ULONG Length,
|
|
||||||
_In_ FILE_INFORMATION_CLASS FileInformationClass,
|
|
||||||
_In_ BOOLEAN ReturnSingleEntry,
|
|
||||||
_In_opt_ PUNICODE_STRING FileName,
|
|
||||||
_In_ BOOLEAN RestartScan
|
|
||||||
);
|
|
||||||
|
|
||||||
static void querydir_buffer_overflow_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
static void querydir_buffer_overflow_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout, ULONG SleepTimeout)
|
||||||
{
|
{
|
||||||
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
void *memfs = memfs_start_ex(Flags, FileInfoTimeout);
|
||||||
@ -766,6 +988,7 @@ void dirnotify_test(void)
|
|||||||
void dirctl_tests(void)
|
void dirctl_tests(void)
|
||||||
{
|
{
|
||||||
TEST(querydir_test);
|
TEST(querydir_test);
|
||||||
|
TEST_OPT(querydir_nodup_test);
|
||||||
if (!OptShareName)
|
if (!OptShareName)
|
||||||
TEST_OPT(querydir_single_test);
|
TEST_OPT(querydir_single_test);
|
||||||
TEST(querydir_expire_cache_test);
|
TEST(querydir_expire_cache_test);
|
||||||
|
@ -273,6 +273,28 @@ void getfileinfo_dotest(ULONG Flags, PWSTR Prefix, ULONG FileInfoTimeout)
|
|||||||
ASSERT(0 == FileInfo.nFileSizeLow && 0 == FileInfo.nFileSizeHigh);
|
ASSERT(0 == FileInfo.nFileSizeLow && 0 == FileInfo.nFileSizeHigh);
|
||||||
ASSERT(1 == FileInfo.nNumberOfLinks);
|
ASSERT(1 == FileInfo.nNumberOfLinks);
|
||||||
|
|
||||||
|
if (-1 != Flags)
|
||||||
|
{
|
||||||
|
/* WinFsp file systems respond to FileIdInformation queries with the IndexNumber zero-extended */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* FILE_ID_INFO is missing from old version of SDK that we are still using */
|
||||||
|
ULONGLONG VolumeSerialNumber;
|
||||||
|
UINT8 FileId[16];
|
||||||
|
} IdInfo;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
UINT64 IndexNumber;
|
||||||
|
UINT8 FileId[16];
|
||||||
|
} ExpectedFileId = { 0 };
|
||||||
|
Success = GetFileInformationByHandleEx(Handle, 0x12/*FileIdInfo*/, &IdInfo, sizeof IdInfo);
|
||||||
|
if (Success)
|
||||||
|
{
|
||||||
|
ExpectedFileId.IndexNumber = ((UINT64)FileInfo.nFileIndexHigh << 32) | (UINT64)FileInfo.nFileIndexLow;
|
||||||
|
ASSERT(0 == memcmp(&ExpectedFileId.FileId, &IdInfo.FileId, sizeof IdInfo.FileId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(Handle);
|
CloseHandle(Handle);
|
||||||
|
|
||||||
memfs_stop(memfs);
|
memfs_stop(memfs);
|
||||||
|
@ -48,9 +48,9 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
|||||||
FileInfoTimeout,
|
FileInfoTimeout,
|
||||||
1024,
|
1024,
|
||||||
1024 * 1024,
|
1024 * 1024,
|
||||||
50, /*SlowioMaxDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 50, /*SlowioMaxDelay*/
|
||||||
10, /*SlowioPercentDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 10, /*SlowioPercentDelay*/
|
||||||
5, /*SlowioRarefyDelay*/
|
(Flags & MemfsNoSlowio) ? 0 : 5, /*SlowioRarefyDelay*/
|
||||||
0,
|
0,
|
||||||
MemfsNet == Flags ? L"\\memfs\\share" : 0,
|
MemfsNet == Flags ? L"\\memfs\\share" : 0,
|
||||||
0,
|
0,
|
||||||
|
Reference in New Issue
Block a user