@@ -1169,8 +1169,9 @@ pub const Dir = struct {
1169
1169
/// Asserts that the path parameter has no null bytes.
1170
1170
pub fn openDir (self : Dir , sub_path : []const u8 , args : OpenDirOptions ) OpenError ! Dir {
1171
1171
if (builtin .os .tag == .windows ) {
1172
- const sub_path_w = try os .windows .sliceToPrefixedFileW (sub_path );
1173
- return self .openDirW (sub_path_w .span ().ptr , args );
1172
+ const nt_path = try os .windows .NtPath .initA (sub_path );
1173
+ defer nt_path .deinit ();
1174
+ return self .openDirWindows (std .fs .path .isAbsoluteWindows (sub_path ), nt_path .str , args );
1174
1175
} else if (builtin .os .tag == .wasi ) {
1175
1176
return self .openDirWasi (sub_path , args );
1176
1177
} else {
@@ -1224,8 +1225,7 @@ pub const Dir = struct {
1224
1225
/// Same as `openDir` except the parameter is null-terminated.
1225
1226
pub fn openDirZ (self : Dir , sub_path_c : [* :0 ]const u8 , args : OpenDirOptions ) OpenError ! Dir {
1226
1227
if (builtin .os .tag == .windows ) {
1227
- const sub_path_w = try os .windows .cStrToPrefixedFileW (sub_path_c );
1228
- return self .openDirW (sub_path_w .span ().ptr , args );
1228
+ return self .openDir (std .mem .spanZ (sub_path_c ), args );
1229
1229
}
1230
1230
const symlink_flags : u32 = if (args .no_follow ) os .O_NOFOLLOW else 0x0 ;
1231
1231
if (! args .iterate ) {
@@ -1236,15 +1236,13 @@ pub const Dir = struct {
1236
1236
}
1237
1237
}
1238
1238
1239
- /// Same as `openDir` except the path parameter is WTF-16 encoded, NT-prefixed .
1239
+ /// Same as `openDir` except the path parameter is WTF-16 encoded.
1240
1240
/// This function asserts the target OS is Windows.
1241
1241
pub fn openDirW (self : Dir , sub_path_w : [* :0 ]const u16 , args : OpenDirOptions ) OpenError ! Dir {
1242
1242
const w = os .windows ;
1243
- // TODO remove some of these flags if args.access_sub_paths is false
1244
- const base_flags = w .STANDARD_RIGHTS_READ | w .FILE_READ_ATTRIBUTES | w .FILE_READ_EA |
1245
- w .SYNCHRONIZE | w .FILE_TRAVERSE ;
1246
- const flags : u32 = if (args .iterate ) base_flags | w .FILE_LIST_DIRECTORY else base_flags ;
1247
- return self .openDirAccessMaskW (sub_path_w , flags , args .no_follow );
1243
+ const nt_path = try w .NtPath .init (sub_path_w );
1244
+ defer nt_path .deinit ();
1245
+ return self .openDirWindows (std .fs .path .isAbsoluteWindowsW (sub_path_w ), nt_path .str , args );
1248
1246
}
1249
1247
1250
1248
/// `flags` must contain `os.O_DIRECTORY`.
@@ -1265,37 +1263,28 @@ pub const Dir = struct {
1265
1263
return Dir { .fd = fd };
1266
1264
}
1267
1265
1268
- fn openDirAccessMaskW (self : Dir , sub_path_w : [ * : 0 ] const u16 , access_mask : u32 , no_follow : bool ) OpenError ! Dir {
1266
+ fn openDirWindows (self : Dir , is_absolute : bool , nt_path : os.windows.UNICODE_STRING , args : OpenDirOptions ) OpenError ! Dir {
1269
1267
const w = os .windows ;
1270
1268
1269
+ // TODO remove some of these flags if args.access_sub_paths is false
1270
+ const base_flags = w .STANDARD_RIGHTS_READ | w .FILE_READ_ATTRIBUTES | w .FILE_READ_EA |
1271
+ w .SYNCHRONIZE | w .FILE_TRAVERSE ;
1272
+ const access_mask : u32 = if (args .iterate ) base_flags | w .FILE_LIST_DIRECTORY else base_flags ;
1273
+
1271
1274
var result = Dir {
1272
1275
.fd = undefined ,
1273
1276
};
1274
1277
1275
- const path_len_bytes = @intCast (u16 , mem .lenZ (sub_path_w ) * 2 );
1276
- var nt_name = w.UNICODE_STRING {
1277
- .Length = path_len_bytes ,
1278
- .MaximumLength = path_len_bytes ,
1279
- .Buffer = @intToPtr ([* ]u16 , @ptrToInt (sub_path_w )),
1280
- };
1278
+ var adjusted_nt_path = if (is_absolute ) nt_path else try w .toRelativeNtPath (nt_path );
1281
1279
var attr = w.OBJECT_ATTRIBUTES {
1282
1280
.Length = @sizeOf (w .OBJECT_ATTRIBUTES ),
1283
- .RootDirectory = if (path . isAbsoluteWindowsW ( sub_path_w ) ) null else self .fd ,
1281
+ .RootDirectory = if (is_absolute ) null else self .fd ,
1284
1282
.Attributes = 0 , // Note we do not use OBJ_CASE_INSENSITIVE here.
1285
- .ObjectName = & nt_name ,
1283
+ .ObjectName = & adjusted_nt_path ,
1286
1284
.SecurityDescriptor = null ,
1287
1285
.SecurityQualityOfService = null ,
1288
1286
};
1289
- if (sub_path_w [0 ] == '.' and sub_path_w [1 ] == 0 ) {
1290
- // Windows does not recognize this, but it does work with empty string.
1291
- nt_name .Length = 0 ;
1292
- }
1293
- if (sub_path_w [0 ] == '.' and sub_path_w [1 ] == '.' and sub_path_w [2 ] == 0 ) {
1294
- // If you're looking to contribute to zig and fix this, see here for an example of how to
1295
- // implement this: https://git.midipix.org/ntapi/tree/src/fs/ntapi_tt_open_physical_parent_directory.c
1296
- @panic ("TODO opening '..' with a relative directory handle is not yet implemented on Windows" );
1297
- }
1298
- const open_reparse_point : w.DWORD = if (no_follow ) w .FILE_OPEN_REPARSE_POINT else 0x0 ;
1287
+ const open_reparse_point : w.DWORD = if (args .no_follow ) w .FILE_OPEN_REPARSE_POINT else 0x0 ;
1299
1288
var io : w.IO_STATUS_BLOCK = undefined ;
1300
1289
const rc = w .ntdll .NtCreateFile (
1301
1290
& result .fd ,
0 commit comments