Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/submodules/external/Catch2-8ac8190
Browse files Browse the repository at this point in the history
  • Loading branch information
nibanks authored Mar 10, 2024
2 parents 82b9c45 + e01d44e commit 1f3332f
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 4 deletions.
41 changes: 41 additions & 0 deletions inc/usersim/ps.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once
#include "..\src\platform.h"
#include "usersim\io.h"
#include "usersim\rtl.h"

CXPLAT_EXTERN_C_BEGIN

Expand All @@ -16,4 +17,44 @@ PsGetCurrentProcessId();
USERSIM_API
_IRQL_requires_max_(DISPATCH_LEVEL) NTKERNELAPI HANDLE PsGetCurrentThreadId();

typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
} CLIENT_ID;
typedef CLIENT_ID* PCLIENT_ID;

typedef struct _PS_CREATE_NOTIFY_INFO
{
_In_ SIZE_T Size;
union
{
_In_ ULONG Flags;
struct
{
_In_ ULONG FileOpenNameAvailable : 1;
_In_ ULONG IsSubsystemProcess : 1;
_In_ ULONG Reserved : 30;
};
};
_In_ HANDLE ParentProcessId;
_In_ CLIENT_ID CreatingThreadId;
_Inout_ struct _FILE_OBJECT* FileObject;
_In_ PCUNICODE_STRING ImageFileName;
_In_opt_ PCUNICODE_STRING CommandLine;
_Inout_ NTSTATUS CreationStatus;
} PS_CREATE_NOTIFY_INFO, *PPS_CREATE_NOTIFY_INFO;

typedef VOID (*PCREATE_PROCESS_NOTIFY_ROUTINE_EX)(
_Inout_ PEPROCESS process, _In_ HANDLE process_id, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info);

USERSIM_API
NTSTATUS
PsSetCreateProcessNotifyRoutineEx(_In_ PCREATE_PROCESS_NOTIFY_ROUTINE_EX notify_routine, _In_ BOOLEAN remove);

USERSIM_API
void
usersime_invoke_process_creation_notify_routine(
_Inout_ PEPROCESS process, _In_ HANDLE process_id, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info);

CXPLAT_EXTERN_C_END
64 changes: 63 additions & 1 deletion inc/usersim/rtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ typedef struct _UNICODE_STRING
} UNICODE_STRING, *PUNICODE_STRING;
typedef const UNICODE_STRING* PCUNICODE_STRING;

typedef STRING UTF8_STRING;
typedef PSTRING PUTF8_STRING;

#define DECLARE_CONST_UNICODE_STRING(_var, _string) \
const WCHAR _var##_buffer[] = _string; \
__pragma(warning(push)) __pragma(warning(disable : 4221)) __pragma(warning(disable : 4204)) \
Expand All @@ -145,6 +148,65 @@ _IRQL_requires_max_(DISPATCH_LEVEL) _At_(destination_string->Buffer, _Post_equal
USERSIM_API VOID NTAPI
RtlInitUnicodeString(_Out_ PUNICODE_STRING destination_string, _In_opt_z_ __drv_aliasesMem PCWSTR source_string);

_IRQL_requires_max_(DISPATCH_LEVEL)
USERSIM_API
VOID
NTAPI
RtlInitUTF8String(
_Out_ PUTF8_STRING DestinationString,
_In_opt_z_ __drv_aliasesMem const char* SourceString
);

_IRQL_requires_max_(PASSIVE_LEVEL)
USERSIM_API
VOID
NTAPI
RtlFreeUnicodeString(
_Inout_ _At_(UnicodeString->Buffer, _Frees_ptr_opt_)
PUNICODE_STRING UnicodeString
);

_When_(AllocateDestinationString,
_At_(DestinationString->MaximumLength,
_Out_range_(<=, (SourceString->MaximumLength / sizeof(WCHAR)))))
_When_(!AllocateDestinationString,
_At_(DestinationString->Buffer, _Const_)
_At_(DestinationString->MaximumLength, _Const_))
_IRQL_requires_max_(PASSIVE_LEVEL)
_When_(AllocateDestinationString, _Must_inspect_result_)
USERSIM_API
NTSTATUS
NTAPI
RtlUnicodeStringToUTF8String(
_When_(AllocateDestinationString, _Out_ _At_(DestinationString->Buffer, __drv_allocatesMem(Mem)))
_When_(!AllocateDestinationString, _Inout_)
PUTF8_STRING DestinationString,
_In_ PCUNICODE_STRING SourceString,
_In_ BOOLEAN AllocateDestinationString
);

_IRQL_requires_max_(PASSIVE_LEVEL)
_Must_inspect_result_
NTSYSAPI
NTSTATUS
NTAPI
RtlUTF8StringToUnicodeString(
_When_(AllocateDestinationString, _Out_ _At_(DestinationString->Buffer, __drv_allocatesMem(Mem)))
_When_(!AllocateDestinationString, _Inout_)
PUNICODE_STRING DestinationString,
_In_ PUTF8_STRING SourceString,
_In_ BOOLEAN AllocateDestinationString
);

_IRQL_requires_max_(PASSIVE_LEVEL)
USERSIM_API
void
NTAPI
RtlFreeUTF8String(
_Inout_ _At_(utf8String->Buffer, _Frees_ptr_opt_)
PUTF8_STRING utf8String
);

typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
Expand All @@ -167,4 +229,4 @@ USERSIM_API __analysis_noreturn void
RtlAssertCPP(
_In_ PVOID void_failed_assertion, _In_ PVOID void_file_name, _In_ ULONG line_number, _In_opt_ PSTR mutable_message);

#endif
#endif
45 changes: 42 additions & 3 deletions src/ps.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,53 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT

#include "platform.h"
#include "kernel_um.h"
#include "platform.h"
#include "usersim/ps.h"

// Ps* functions.

HANDLE
PsGetCurrentProcessId() { return (HANDLE)(uintptr_t)GetCurrentProcessId(); }

_IRQL_requires_max_(DISPATCH_LEVEL) NTKERNELAPI HANDLE
PsGetCurrentThreadId() { return (HANDLE)(uintptr_t)GetCurrentThreadId(); }
_IRQL_requires_max_(DISPATCH_LEVEL) NTKERNELAPI HANDLE PsGetCurrentThreadId()
{
return (HANDLE)(uintptr_t)GetCurrentThreadId();
}

static PCREATE_PROCESS_NOTIFY_ROUTINE_EX _usersim_process_creation_notify_routine = NULL;

USERSIM_API
NTSTATUS
PsSetCreateProcessNotifyRoutineEx(_In_ PCREATE_PROCESS_NOTIFY_ROUTINE_EX notify_routine, _In_ BOOLEAN remove)
{
if (notify_routine == NULL) {
return STATUS_INVALID_PARAMETER;
}

// Remove the routine.
if (remove) {
if (_usersim_process_creation_notify_routine == NULL) {
return STATUS_INVALID_PARAMETER;
}
_usersim_process_creation_notify_routine = NULL;
return STATUS_SUCCESS;
}
// Only one routine is supported.
if (_usersim_process_creation_notify_routine != NULL) {
return STATUS_INVALID_PARAMETER;
}

// Set the routine.
_usersim_process_creation_notify_routine = notify_routine;
return STATUS_SUCCESS;
}

void
usersime_invoke_process_creation_notify_routine(
_Inout_ PEPROCESS process, _In_ HANDLE process_id, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info)
{
if (_usersim_process_creation_notify_routine != NULL) {
_usersim_process_creation_notify_routine(process, process_id, create_info);
}
}
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ add_executable(usersim_tests
mm_test.cpp
nmr_test.cpp
ob_test.cpp
ps_test.cpp
rtl_test.cpp
se_test.cpp
wdf_test.cpp
Expand Down
44 changes: 44 additions & 0 deletions tests/ps_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT

#if !defined(CMAKE_NUGET)
#include <catch2/catch_all.hpp>
#else
#include <catch2/catch.hpp>
#endif
#include "usersim/ps.h"

TEST_CASE("PsSetCreateProcessNotifyRoutineEx", "[ps]")
{
auto notify_routine = [](PEPROCESS, HANDLE, PPS_CREATE_NOTIFY_INFO) {};
// First call should succeed.
auto status = PsSetCreateProcessNotifyRoutineEx(notify_routine, FALSE);
REQUIRE(status == STATUS_SUCCESS);
// Try to set the routine again, should fail.
status = PsSetCreateProcessNotifyRoutineEx(notify_routine, FALSE);
REQUIRE(status == STATUS_INVALID_PARAMETER);

// Remove the routine. Should succeed.
status = PsSetCreateProcessNotifyRoutineEx(notify_routine, TRUE);
REQUIRE(status == STATUS_SUCCESS);

// Try to remove the routine again, should fail.
status = PsSetCreateProcessNotifyRoutineEx(notify_routine, TRUE);
REQUIRE(status == STATUS_INVALID_PARAMETER);

// Try to remove with a NULL routine, should fail.
status = PsSetCreateProcessNotifyRoutineEx(NULL, TRUE);
REQUIRE(status == STATUS_INVALID_PARAMETER);

// Try set with a NULL routine, should fail.
status = PsSetCreateProcessNotifyRoutineEx(NULL, FALSE);
REQUIRE(status == STATUS_INVALID_PARAMETER);

// Set the routine again, should succeed.
status = PsSetCreateProcessNotifyRoutineEx(notify_routine, FALSE);
REQUIRE(status == STATUS_SUCCESS);

// Remove the routine. Should succeed.
status = PsSetCreateProcessNotifyRoutineEx(notify_routine, TRUE);
REQUIRE(status == STATUS_SUCCESS);
}
26 changes: 26 additions & 0 deletions tests/rtl_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,30 @@ TEST_CASE("RtlInitUnicodeString", "[rtl]")
REQUIRE(unicode_string.Buffer == buffer);
REQUIRE(unicode_string.Length == 8);
REQUIRE(unicode_string.MaximumLength == 10);
}

TEST_CASE("RtlUnicodeStringToUTF8String", "[rtl]")
{
UNICODE_STRING unicode_string = {0};
RtlInitUnicodeString(&unicode_string, L"test");
UTF8_STRING utf8_string = {0};
REQUIRE(RtlUnicodeStringToUTF8String(&utf8_string, &unicode_string, TRUE) == STATUS_SUCCESS);
REQUIRE(utf8_string.Buffer != nullptr);
REQUIRE(utf8_string.Length == 4);
REQUIRE(utf8_string.MaximumLength == 5);
REQUIRE(strcmp(utf8_string.Buffer, "test") == 0);
RtlFreeUTF8String(&utf8_string);
}

TEST_CASE("RtlUTF8StringToUnicodeString", "[rtl]")
{
UTF8_STRING utf8_string = {0};
RtlInitUTF8String(&utf8_string, "test");
UNICODE_STRING unicode_string = {0};
REQUIRE(RtlUTF8StringToUnicodeString(&unicode_string, &utf8_string, TRUE) == STATUS_SUCCESS);
REQUIRE(unicode_string.Buffer != nullptr);
REQUIRE(unicode_string.Length == 8);
REQUIRE(unicode_string.MaximumLength == 10);
REQUIRE(wcscmp(unicode_string.Buffer, L"test") == 0);
RtlFreeUnicodeString(&unicode_string);
}

0 comments on commit 1f3332f

Please sign in to comment.