USB Device Discovery & Permission Setup (Windows)
Technical guide to discovering USB drives on Windows PC and configuring Xbox permissions for media access.
Overview: USB Discovery vs SSH Drive Query
Important distinction:
| Aspect | SSH Drive Query | USB Device Discovery |
|---|---|---|
| Where | On Xbox (via SSH) | On Windows PC |
| What | Lists available Xbox drives (C:, D:, E:, F:, etc.) | Finds USB sticks plugged into PC |
| Purpose | File Explorer navigation | Prepare USB for Xbox to access |
| Related doc | integration-ssh-sftp-challenges.md | This document |
Workflows:
graph LR
A["SSH Query:<br/>Xbox Drives"]
B["SFTP Browse<br/>Xbox Files"]
C["USB Discovery:<br/>Windows Side"]
D["Permission Setup<br/>(icacls)"]
E["Network Share<br/>or Direct USB"]
A --> B
C --> D --> E
style A fill:#447F3E,stroke:#9ACA3C,color:#fff
style B fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style C fill:#447F3E,stroke:#9ACA3C,color:#fff
style D fill:#447F3E,stroke:#9ACA3C,color:#fff
style E fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
Phase 1: Detecting USB Drives (Windows PC)
Why Detection Matters
Challenge: How to identify which drive is the USB among multiple drives on PC?
Solution: Use Windows WMI (Win32_LogicalDisk) to query USB drives before connecting to Xbox
Detection Method: WMI Query
Code from UsbDriveDetector.cs:
#if WINDOWS
using System.Management;
public class UsbDriveDetector
{
public static List<UsbDriveInfo> FindUsbDrives()
{
var searcher = new ManagementObjectSearcher(
"SELECT * FROM Win32_LogicalDisk WHERE MediaType=2");
var drives = new List<UsbDriveInfo>();
foreach (ManagementObject drive in searcher.Get())
{
var letter = drive["Name"]?.ToString(); // "E:"
var label = drive["VolumeName"]?.ToString(); // "My Games"
var size = drive["Size"]?.ToString(); // Bytes
drives.Add(new UsbDriveInfo
{
Letter = letter,
Label = label,
SizeBytes = long.Parse(size ?? "0")
});
}
return drives;
}
}
#endif
Why MediaType=2?
WMI MediaType codes:
graph TD
A["MediaType Values"]
B["0 = Unknown"]
C["1 = Hard Disk"]
D["2 = Removable Media<br/>(USB drives)"]
E["3 = Network Drive"]
F["4 = CD-ROM"]
G["5 = RAM disk"]
A --> B
A --> C
A --> D
A --> E
A --> F
A --> G
style A fill:#1A1D23,stroke:#447F3E,color:#9ACA3C
style D fill:#9ACA3C,stroke:#447F3E,color:#000
style B fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style C fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style E fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style F fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style G fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
Platform Limitations
Windows-only: System.Management doesn’t exist on Linux/macOS
#if WINDOWS
// WMI code (Windows only)
#else
// Fallback: Return empty list or show error
return new List<UsbDriveInfo>(); // or throw NotSupportedException
#endif
Consequence: USB detection only works on Windows. Other platforms must use manual fallback (user selects folder).
Phase 2: Detecting USB via File System (Fallback)
When to Use Fallback
Scenarios:
- User on Linux/macOS (no WMI)
- WMI query fails (permissions issue, unusual system)
- User has multiple USB sticks, wants manual selection
Simple Fallback: “Browse for Folder”
// Prompt user to select USB root folder
var dialog = new FolderPickerDialog();
dialog.Title = "Select USB Drive Root";
var result = await dialog.ShowAsync(mainWindow);
if (result != null)
{
var usbPath = result[0]; // e.g., "E:\" on Windows, "/mnt/usb" on Linux
return new List<UsbDriveInfo>
{
new UsbDriveInfo { Letter = usbPath, Label = "User-selected" }
};
}
Heuristic Detection (Linux/macOS)
On Linux:
lsblk -d -p -n -l | grep -v '^/dev/.*\(loop\|dm\)' | awk '{print $1}'
# Returns: /dev/sda, /dev/sdb, etc.
On macOS:
diskutil list external | grep "^/dev"
# Returns: /dev/disk1, /dev/disk2, etc.
Code example:
#if LINUX
var proc = Process.Start("lsblk", "-d -p -n -l");
var output = proc.StandardOutput.ReadToEnd();
var devices = output.Split("\n").Where(x => !x.Contains("loop")).ToList();
#endif
Phase 3: Permission Setup (icacls)
The Permission Challenge
Problem: Xbox apps run in sandboxed context (AppContainer) with restricted access
Consequence: Default NTFS permissions block Xbox from reading USB
Solution: Grant “ALL APPLICATION PACKAGES” explicit permissions
Permission Grant Code
From UsbPermissionViewModel.cs:
public async Task<bool> GrantUsbPermissionsAsync(string driveLetter)
{
try
{
// Elevate to admin (required for icacls)
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c icacls \"{driveLetter}\" /grant \"*S-1-15-2-1:(OI)(CI)F\" /T /C",
UseShellExecute = true,
Verb = "runas", // ← Request UAC elevation
CreateNoWindow = true,
RedirectStandardOutput = false
}
};
process.Start();
process.WaitForExit();
if (process.ExitCode == 0)
{
Logger.Info($"USB permissions granted for {driveLetter}");
return true;
}
else
{
Logger.Error($"icacls failed with exit code {process.ExitCode}");
return false;
}
}
catch (Exception ex)
{
Logger.Error(ex, "Failed to grant USB permissions");
return false;
}
}
icacls Parameters Explained
graph TD
CMD["icacls {drive} /grant<br/>*S-1-15-2-1:(OI)(CI)F<br/>/T /C"]
PARAM1["icacls<br/>NTFS Permission Tool"]
PARAM2["{drive}<br/>Target Drive<br/>e.g., 'E:\' or '/dev/sda'"]
PARAM3["/grant<br/>Grant (add)<br/>permission"]
PARAM4["*S-1-15-2-1<br/>ALL APPLICATION<br/>PACKAGES SID"]
PARAM5["(OI)(CI)F<br/>Object Inherit,<br/>Container Inherit,<br/>Full Access"]
PARAM6["/T<br/>Traverse Tree<br/>(recursive)"]
PARAM7["/C<br/>Continue on Error"]
CMD --> PARAM1
CMD --> PARAM2
CMD --> PARAM3
CMD --> PARAM4
CMD --> PARAM5
CMD --> PARAM6
CMD --> PARAM7
style CMD fill:#1A1D23,stroke:#447F3E,color:#9ACA3C
style PARAM1 fill:#447F3E,stroke:#9ACA3C,color:#fff
style PARAM2 fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style PARAM3 fill:#447F3E,stroke:#9ACA3C,color:#fff
style PARAM4 fill:#9ACA3C,stroke:#447F3E,color:#000
style PARAM5 fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style PARAM6 fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
style PARAM7 fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
SID: *S-1-15-2-1 Explained
What is this SID?
S-1-15-2-1= “ALL APPLICATION PACKAGES” (Xbox app container group on Windows)- The
*prefix means “convert string SID to binary” (required syntax)
Why this SID?
- Xbox apps run in AppContainer sandbox (UWP/XAML)
- Default NTFS ACLs don’t include AppContainer permissions
- Explicitly granting to this SID allows Xbox apps read/write access
Permissions breakdown:
(OI) = Object Inherit → Files inherit permission
(CI) = Container Inherit → Subdirectories inherit
F = Full Access → All rights (read, write, execute, delete)
UAC Elevation Required
Quirk: icacls requires admin privileges
Why? Modifying NTFS ACLs is a privileged operation
How it works:
Verb = "runas" // Triggers Windows UAC elevation dialog
User experience:
- User clicks “Grant Permissions”
- Windows UAC dialog appears: “XB Vault wants to make changes”
- User clicks “Yes”
cmd.exeruns with elevated tokenicaclsmodifies ACL on USB drive- Permissions granted, Xbox can now access USB
Phase 4: Verifying Permission Success
Check Permissions
After granting, verify with:
public async Task<bool> VerifyUsbPermissionsAsync(string driveLetter)
{
try
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c icacls \"{driveLetter}\"",
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
};
process.Start();
var output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// Check if S-1-15-2-1 appears in ACL
if (output.Contains("S-1-15-2-1"))
{
Logger.Info($"USB permissions verified for {driveLetter}");
return true;
}
Logger.Warn($"Permission grant may have failed; SID not in ACL");
return false;
}
catch (Exception ex)
{
Logger.Error(ex, "Failed to verify permissions");
return false;
}
}
Expected Output
Before granting:
E:\
Everyone:(OI)(CI)F
BUILTIN\Administrators:(OI)(CI)F
After granting:
E:\
Everyone:(OI)(CI)F
BUILTIN\Administrators:(OI)(CI)F
*S-1-15-2-1:(OI)(CI)F
Real-World Flow: USB Setup Wizard
sequenceDiagram
participant User as User
participant App as XB Vault App
participant WMI as Windows WMI
participant CMD as cmd.exe
participant Xbox as Xbox Dev Mode
User->>App: Click "Enable USB"
App->>WMI: Query USB drives (MediaType=2)
WMI-->>App: Found E:\ "My Games" (64GB)
App->>User: Show "Found USB: E:\"
User->>App: Click "Grant Permissions"
App->>CMD: Run icacls with /grant
CMD-->>App: Request UAC elevation
User->>CMD: Click "Yes" in UAC dialog
CMD->>CMD: Modify NTFS ACL
CMD-->>App: Success (exit code 0)
App->>CMD: Verify permissions (icacls query)
CMD-->>App: SID found in ACL
App-->>User: ✅ USB Ready!<br/>E:\ can now access Xbox
Error Handling & Edge Cases
Case 1: User Denies UAC
What happens:
UAC dialog appears
User clicks "No"
Process exits with code 1
App detects failure, shows "Permission denied" message
Code handling:
if (process.ExitCode != 0)
{
Logger.Warn("User denied UAC elevation");
// Show error: "Admin privileges required to modify USB permissions"
return false;
}
Case 2: USB is FAT32 (No NTFS ACLs)
Problem: FAT32 doesn’t support NTFS ACLs
Symptom: icacls returns error code 5 (access denied)
Solution: Inform user USB must be NTFS formatted
// Detect filesystem type
var drive = new DriveInfo("E:");
if (drive.DriveFormat != "NTFS")
{
Logger.Error("USB is not NTFS formatted");
throw new InvalidOperationException(
"USB must be formatted as NTFS, not " + drive.DriveFormat);
}
Case 3: Permission Already Granted
What happens:
- User runs “Grant Permissions” twice
icacls /grantadds duplicate SID entries (ACL has S-1-15-2-1 twice)- Not a problem, but redundant
Optional cleanup:
// Remove before granting
await RunCommandAsync($"icacls \"{driveLetter}\" /remove \"*S-1-15-2-1\" /T /C");
// Then grant fresh
await GrantUsbPermissionsAsync(driveLetter);
Case 4: Antivirus Blocks icacls
Problem: Some antivirus software may block permission modification
Symptom: icacls hangs or fails silently
Mitigation: Whitelist cmd.exe or allow icacls in antivirus settings
Related Concepts
USB vs Network Share
USB Direct Access:
- Pros: Plug & play, fast, no network overhead
- Cons: USB cable required, single connection
Network Share (SMB):
- Pros: Wireless, multiple connections, central storage
- Cons: Slower, requires network setup
XB Vault supports both: USB for direct access, SMB for network streaming
Comparison with Linux/macOS
| Platform | Detection | Permission | Notes |
|---|---|---|---|
| Windows | WMI (easy) | icacls (easy) | UAC elevation required |
| Linux | lsblk (CLI) | chmod (easy) | No sandbox restrictions |
| macOS | diskutil (CLI) | chmod (easy) | APFS/HFS+ different from NTFS |
See Also
- integration-ssh-sftp-challenges.md — SSH drive discovery (ON Xbox, not PC)
- docs/tech-debt.md — Known issues with USB detection (#14)