forked from ritchielawrence/cmdow
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget_counter_ids.cpp
More file actions
116 lines (100 loc) · 3.04 KB
/
get_counter_ids.cpp
File metadata and controls
116 lines (100 loc) · 3.04 KB
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
#include <algorithm>
#include "header.h"
#include <common_cpp.hpp>
#include <cassert>
#include <string>
#include <iso646.h>
constexpr std::string_view PROCESS_COUNTER = "process";
constexpr std::string_view PROCESSID_COUNTER = "id process";
constexpr std::string_view UNKNOWN_TASK = "Unknown";
static std::string to_lower(const std::string& str)
{
std::string lowerStr = str;
std::ranges::transform(lowerStr,
lowerStr.begin(),
[](const unsigned char c) { return std::tolower(c); });
return lowerStr;
}
/// <summary>
/// Extract the ids of the "process" and "id process"
/// </summary>
/// Buffer consists of pairs of NULL terminated strings, where the first
/// string is an integer id, and the second is a name
/// <param name="buf">Buffer to be searched</param>
/// <param name="dwSize">Buffer length</param>
/// <returns>Tuple of ids (process and id process) or -1, -1</returns>
std::expected<std::tuple<unsigned long, unsigned long>, process_error>
get_counter_ids(
const LPBYTE buf,
const DWORD dwSize)
{
unsigned long process_id = 0;
unsigned long id_process_id = 0;
int ids_found = 0;
// Check first char is at least a digit.
if (not isdigit(buf[0]))
{
return std::unexpected(process_error::bad_first_byte);
}
// Basic check that the buffer looks correct.
assert(isdigit(buf[0]));
const char *p = reinterpret_cast<const char*>(buf);
const char *end = reinterpret_cast<const char*>(buf + dwSize);
bool bContinue = true;
while (p < end && bContinue)
{
size_t len = std::strlen(p);
if (len == 0)
{
++p;
continue;
}
char* endPtr;
auto id = strtoul(p, &endPtr, 10);
if (errno == ERANGE)
{
return std::unexpected(process_error::numeric_conversion_failed);
}
if (p == endPtr)
{
// Break if end of data reached
break;
}
// If p + len != endPtr then there is bad data, e.g. numbers
// followed by non-numbers before he next NULL.,
// Should we error on this or cope with it.
p = p + strlen(p) + 1;
if (*p == 0)
{
return std::unexpected(process_error::missing_process_id);
}
auto name = std::string(p);
if (to_lower(name) == PROCESS_COUNTER)
{
process_id = id;
++ids_found;
// Exit once both ids are found
if (ids_found >= 2)
{
break;
}
}
else if (to_lower(name) == PROCESSID_COUNTER)
{
id_process_id = id;
++ids_found;
// Exit once both ids are found
if (ids_found >= 2)
{
break;
}
}
p = p + name.length() + 1;
}
// Check both ids were found.
if (ids_found != 2)
{
return std::unexpected(process_error::two_ids_not_found);
}
return std::make_tuple(process_id, id_process_id);
}