summaryrefslogtreecommitdiff
path: root/network/netadaptercx/netvadapterlibrary/code/enlthreads.cpp
blob: ffe70d6e7538f7a1e95007754e666ad39d8b01c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (C) Microsoft Corporation. All rights reserved.
#include "pch.hpp"
//#include <ntassert.h>
#include "enlthreads.h"

#ifdef _KERNEL_MODE
unique_thread::operator bool(
    void
) const
{
    return !!NtHandle;
}

void unique_thread::reset(
)
{
    NtHandle.reset();
    ObHandle.reset();
}
#endif

ENL_THREAD
EnlGetCurrentThread(
    void
)
{
#ifdef _KERNEL_MODE
    return KeGetCurrentThread();
#else
    return GetCurrentThreadId();
#endif
}

_Use_decl_annotations_
NTSTATUS
EnlThreadCreate(
    ENL_START_ROUTINE StartRoutine,
    void * Context,
    unique_thread & Thread
)
{
#ifdef _KERNEL_MODE

    unique_zw_handle ntHandle;
    unique_pkthread obHandle;

    auto const ntStatus = PsCreateSystemThread(
        &ntHandle,
        THREAD_ALL_ACCESS,
        nullptr,
        nullptr,
        nullptr,
        StartRoutine,
        Context);

    if (ntStatus != STATUS_SUCCESS)
    {
        return ntStatus;
    }

    NT_FRE_ASSERT(
        NT_SUCCESS(
            ObReferenceObjectByHandle(
                ntHandle.get(),
                THREAD_ALL_ACCESS,
                nullptr,
                KernelMode,
                reinterpret_cast<void **>(&obHandle),
                nullptr)));

    Thread.NtHandle = wistd::move(ntHandle);
    Thread.ObHandle = wistd::move(obHandle);

#else
    wil::unique_handle thread{ CreateThread(nullptr, 0, StartRoutine, Context, 0, nullptr) };

    if (!thread)
    {
        return NTSTATUS_FROM_WIN32(GetLastError());
    }

    Thread = wistd::move(thread);
#endif

    return STATUS_SUCCESS;
}

void
EnlThreadSetPriority(
    unique_thread & Thread,
    ENL_THREAD_PRIORITY Priority
)
{
#ifdef _KERNEL_MODE
    // KeSetBasePriorityThread does not take the actual priority, but an increment
    // to be added to the current base priority. Calculate this value.
    auto const increment = Priority - (LOW_REALTIME_PRIORITY + LOW_PRIORITY) / 2;
    KeSetBasePriorityThread(Thread.ObHandle.get(), increment);
#else
    SetThreadPriority(Thread.get(), Priority);
#endif
}

_Use_decl_annotations_
void
EnlThreadSetAffinity(
    PGROUP_AFFINITY GroupAffinity,
    PGROUP_AFFINITY PreviousAffinity
)
{
#ifdef _KERNEL_MODE
    KeSetSystemGroupAffinityThread(GroupAffinity, PreviousAffinity);
#else
    SetThreadGroupAffinity(GetCurrentThread(), GroupAffinity, PreviousAffinity);
#endif
}

_Use_decl_annotations_
void
EnlThreadWaitForTermination(
    unique_thread & Thread
)
{
#ifdef _KERNEL_MODE
    KeWaitForSingleObject(
        Thread.ObHandle.get(),
        KWAIT_REASON::Executive,
        KernelMode,
        FALSE,
        nullptr);
#else
    WaitForSingleObject(
        Thread.get(),
        INFINITE);
#endif
}