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