/// <summary> /// Query a variable buffer from the object. /// </summary> /// <param name="info_class">The information class to query.</param> /// <param name="init_buffer">A buffer to initialize the initial query. Can be null.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The result of the query.</returns> /// <exception cref="NtException">Thrown on error.</exception> public virtual NtResult <SafeHGlobalBuffer> QueryRawBuffer(Q info_class, byte[] init_buffer, bool throw_on_error) { NtStatus status; int return_length; // First try base size before trying to reallocate. using (var buffer = init_buffer.ToBuffer()) { status = QueryInformation(info_class, buffer, out return_length); if (status.IsSuccess()) { return(status.CreateResult(false, () => buffer.Detach(return_length))); } } if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } // If the function returned a length then trust it. if (return_length > 0 && GetTrustReturnLength(info_class)) { using (var buffer = new SafeHGlobalBuffer(return_length)) { return(QueryInformation(info_class, buffer, out return_length).CreateResult(throw_on_error, () => buffer.Detach(return_length))); } } // Function length can't be trusted, we'll need to brute force it. return_length = 256; int max_length = GetMaximumBruteForceLength(info_class); while (return_length <= max_length) { using (var buffer = new SafeHGlobalBuffer(return_length)) { status = QueryInformation(info_class, buffer, out int dummy_length); if (status.IsSuccess()) { if (dummy_length > 0 && dummy_length < return_length) { return_length = dummy_length; } return(status.CreateResult(throw_on_error, () => buffer.Detach(return_length))); } else if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } return_length *= 2; } } return(NtStatus.STATUS_BUFFER_TOO_SMALL.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); }
private NtResult <SafeHGlobalBuffer> CreateRelativeSecurityDescriptor(bool throw_on_error) { using (var sd_buffer = CreateAbsoluteSecurityDescriptor(throw_on_error)) { if (!sd_buffer.IsSuccess) { return(sd_buffer); } int total_length = 0; NtStatus status = NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer.Result, SafeHGlobalBuffer.Null, ref total_length); if (status != NtStatus.STATUS_BUFFER_TOO_SMALL) { return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error)); } using (var relative_sd = new SafeHGlobalBuffer(total_length)) { return(NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer.Result, relative_sd, ref total_length) .CreateResult(throw_on_error, () => relative_sd.Detach())); } } }