@@ -956,29 +956,29 @@ pub fn QueryObjectName(
956
956
handle : HANDLE ,
957
957
out_buffer : []u16 ,
958
958
) ! []u16 {
959
- var full_buffer : [@sizeOf (OBJECT_NAME_INFORMATION ) + PATH_MAX_WIDE * 2 ]u8 align (@alignOf (OBJECT_NAME_INFORMATION )) = undefined ;
960
- var info = @ptrCast (* OBJECT_NAME_INFORMATION , & full_buffer );
959
+ const out_buffer_aligned = mem .alignInSlice (out_buffer , @alignOf (OBJECT_NAME_INFORMATION )) orelse return error .NameTooLong ;
960
+
961
+ const info = @ptrCast (* OBJECT_NAME_INFORMATION , out_buffer_aligned );
961
962
//buffer size is specified in bytes
963
+ const out_buffer_len = std .math .cast (ULONG , out_buffer_aligned .len * 2 ) catch | e | switch (e ) {
964
+ error .Overflow = > std .math .maxInt (ULONG ),
965
+ };
962
966
//last argument would return the length required for full_buffer, not exposed here
963
- const rc = ntdll .NtQueryObject (handle , .ObjectNameInformation , & full_buffer , full_buffer . len , null );
967
+ const rc = ntdll .NtQueryObject (handle , .ObjectNameInformation , info , out_buffer_len , null );
964
968
switch (rc ) {
965
969
.SUCCESS = > {
966
970
// info.Name.Buffer from ObQueryNameString is documented to be null (and MaximumLength == 0)
967
971
// if the object was "unnamed", not sure if this can happen for file handles
968
972
if (info .Name .MaximumLength == 0 ) return error .Unexpected ;
969
- //resulting string length is specified in bytes
973
+ // resulting string length is specified in bytes
970
974
const path_length_unterminated = @divExact (info .Name .Length , 2 );
971
- if (out_buffer .len < path_length_unterminated ) {
972
- return error .NameTooLong ;
973
- }
974
- mem .copy (WCHAR , out_buffer [0.. path_length_unterminated ], info .Name .Buffer [0.. path_length_unterminated ]);
975
- return out_buffer [0.. path_length_unterminated ];
975
+ return info .Name .Buffer [0.. path_length_unterminated ];
976
976
},
977
977
.ACCESS_DENIED = > return error .AccessDenied ,
978
978
.INVALID_HANDLE = > return error .InvalidHandle ,
979
- .BUFFER_OVERFLOW , .BUFFER_TOO_SMALL = > return error . NameTooLong ,
980
- //name_buffer.len >= @sizeOf(OBJECT_NAME_INFORMATION) holds statically
981
- .INFO_LENGTH_MISMATCH = > unreachable ,
979
+ // triggered when the buffer is too small for the OBJECT_NAME_INFORMATION object (.INFO_LENGTH_MISMATCH) ,
980
+ // or if the buffer is too small for the file path returned (.BUFFER_OVERFLOW, .BUFFER_TOO_SMALL)
981
+ .INFO_LENGTH_MISMATCH , .BUFFER_OVERFLOW , .BUFFER_TOO_SMALL = > return error . NameTooLong ,
982
982
else = > | e | return unexpectedStatus (e ),
983
983
}
984
984
}
@@ -993,10 +993,11 @@ test "QueryObjectName" {
993
993
var out_buffer : [PATH_MAX_WIDE ]u16 = undefined ;
994
994
995
995
var result_path = try QueryObjectName (handle , & out_buffer );
996
+ const required_len_in_u16 = result_path .len + @divExact (@ptrToInt (result_path .ptr ) - @ptrToInt (& out_buffer ), 2 ) + 1 ;
996
997
//insufficient size
997
- std .testing .expectError (error .NameTooLong , QueryObjectName (handle , out_buffer [0 .. result_path . len - 1 ]));
998
+ std .testing .expectError (error .NameTooLong , QueryObjectName (handle , out_buffer [0 .. required_len_in_u16 - 1 ]));
998
999
//exactly-sufficient size
999
- _ = try QueryObjectName (handle , out_buffer [0.. result_path . len ]);
1000
+ _ = try QueryObjectName (handle , out_buffer [0.. required_len_in_u16 ]);
1000
1001
}
1001
1002
1002
1003
pub const GetFinalPathNameByHandleError = error {
@@ -1028,8 +1029,7 @@ pub fn GetFinalPathNameByHandle(
1028
1029
fmt : GetFinalPathNameByHandleFormat ,
1029
1030
out_buffer : []u16 ,
1030
1031
) GetFinalPathNameByHandleError ! []u16 {
1031
- var path_buffer : [math .max (@sizeOf (FILE_NAME_INFORMATION ), @sizeOf (OBJECT_NAME_INFORMATION )) + PATH_MAX_WIDE * 2 ]u8 align (@alignOf (FILE_NAME_INFORMATION )) = undefined ;
1032
- const final_path = QueryObjectName (hFile , mem .bytesAsSlice (u16 , & path_buffer )) catch | err | switch (err ) {
1032
+ const final_path = QueryObjectName (hFile , out_buffer ) catch | err | switch (err ) {
1033
1033
// we assume InvalidHandle is close enough to FileNotFound in semantics
1034
1034
// to not further complicate the error set
1035
1035
error .InvalidHandle = > return error .FileNotFound ,
@@ -1039,11 +1039,7 @@ pub fn GetFinalPathNameByHandle(
1039
1039
switch (fmt .volume_name ) {
1040
1040
.Nt = > {
1041
1041
// the returned path is already in .Nt format
1042
- if (out_buffer .len < final_path .len ) {
1043
- return error .NameTooLong ;
1044
- }
1045
- mem .copy (u16 , out_buffer , final_path );
1046
- return out_buffer [0.. final_path .len ];
1042
+ return final_path ;
1047
1043
},
1048
1044
.Dos = > {
1049
1045
// parse the string to separate volume path from file path
@@ -1152,16 +1148,17 @@ test "GetFinalPathNameByHandle" {
1152
1148
var buffer : [PATH_MAX_WIDE ]u16 = undefined ;
1153
1149
1154
1150
//check with sufficient size
1155
- const nt_length = ( try GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, & buffer )). len ;
1156
- const dos_length = ( try GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, & buffer )). len ;
1151
+ const nt_path = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, & buffer );
1152
+ _ = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, & buffer );
1157
1153
1154
+ const required_len_in_u16 = nt_path .len + @divExact (@ptrToInt (nt_path .ptr ) - @ptrToInt (& buffer ), 2 ) + 1 ;
1158
1155
//check with insufficient size
1159
- std .testing .expectError (error .NameTooLong , GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, buffer [0 .. nt_length - 1 ]));
1160
- std .testing .expectError (error .NameTooLong , GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, buffer [0 .. dos_length - 1 ]));
1156
+ std .testing .expectError (error .NameTooLong , GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, buffer [0 .. required_len_in_u16 - 1 ]));
1157
+ std .testing .expectError (error .NameTooLong , GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, buffer [0 .. required_len_in_u16 - 1 ]));
1161
1158
1162
1159
//check with exactly-sufficient size
1163
- _ = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, buffer [0.. nt_length ]);
1164
- _ = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, buffer [0.. dos_length ]);
1160
+ _ = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Nt }, buffer [0.. required_len_in_u16 ]);
1161
+ _ = try GetFinalPathNameByHandle (handle , .{ .volume_name = .Dos }, buffer [0.. required_len_in_u16 ]);
1165
1162
}
1166
1163
1167
1164
pub const QueryInformationFileError = error {Unexpected };
0 commit comments