param( [Parameter(Mandatory=$true)][ValidatePattern('^[A-Z]$')][string]$DriveLetter, [Parameter(Mandatory=$true)][ValidatePattern('^[A-Za-z0-9_.-]+$')][string]$UsbSerial, [ValidateRange(1,64)][int]$SizeMiB=1 ) $ErrorActionPreference='Stop' $disk=@(Get-CimInstance Win32_DiskDrive | Where-Object { $_.InterfaceType -eq 'USB' -and $_.PNPDeviceID -like "USBSTOR\*\$UsbSerial&*" }) if($disk.Count -ne 1){throw 'Expected exactly one approved USB disk'} $partition=Get-Partition -DriveLetter $DriveLetter if($partition.DiskNumber -ne $disk[0].Index){throw 'Drive letter does not belong to the approved USB disk'} $stamp=Get-Date -Format 'yyyyMMdd-HHmmss' $name="VDI_USB_TEST_$stamp" $local=Join-Path $env:TEMP $name $usb=Join-Path "${DriveLetter}:\" $name if((Test-Path -LiteralPath $local) -or (Test-Path -LiteralPath $usb)){throw 'Test directory already exists'} New-Item -ItemType Directory -Path $local,$usb | Out-Null $bytes=New-Object byte[] ($SizeMiB*1MB) $rng=[Security.Cryptography.RandomNumberGenerator]::Create() try{$rng.GetBytes($bytes)}finally{$rng.Dispose()} $source=Join-Path $local 'source.bin' [IO.File]::WriteAllBytes($source,$bytes) $target=Join-Path $usb 'from-windows.bin' $stream=[IO.File]::Open($target,[IO.FileMode]::CreateNew,[IO.FileAccess]::Write,[IO.FileShare]::None) try{$stream.Write($bytes,0,$bytes.Length);$stream.Flush($true)}finally{$stream.Dispose()} $copy=Join-Path $local 'readback.bin' Copy-Item -LiteralPath $target -Destination $copy $a=(Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash $b=(Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash $c=(Get-FileHash -LiteralPath $copy -Algorithm SHA256).Hash if($a -ne $b -or $a -ne $c){throw 'USB read/write hash mismatch'} [IO.File]::WriteAllText((Join-Path $usb 'readme.txt'),"VDI USB device POC test. Only this directory was created by the test.`r`n",[Text.Encoding]::UTF8) [pscustomobject]@{Result='PASS';Model=$disk[0].Model;InterfaceType=$disk[0].InterfaceType;PNPDeviceID=$disk[0].PNPDeviceID;DriveLetter=$DriveLetter;TestDirectory=$usb;LocalDirectory=$local;Bytes=$bytes.Length;SHA256=$a} | ConvertTo-Json