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