Skip to content

Commit 226108d

Browse files
committed
UID on Windows too
1 parent b244891 commit 226108d

8 files changed

Lines changed: 142 additions & 26 deletions

File tree

CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ foreach(a IN ITEMS
4646
allocate bounds contiguous
4747
array bool error exception
4848
iterator
49-
glibc malloc
49+
malloc
5050
nullptr
5151
opaque pointer poly_function poly_type real struct
5252
sleep string submodule
53-
time vector)
53+
time
54+
uid
55+
vector)
5456

5557
add_subdirectory(test/${a})
5658

src/uid/uid.cpp

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Windows doesn't have a numerid UID like Unix, so we return the SID as a string instead.
2+
3+
#if defined(_WIN32)
4+
#define WIN32_LEAN_AND_MEAN
5+
#include <windows.h>
6+
#include <sddl.h> // For ConvertSidToStringSid
7+
#include <vector>
8+
#include <iostream>
9+
#else
10+
#include <unistd.h>
11+
#include <sys/types.h>
12+
#endif
13+
14+
#include <string>
15+
#include <string_view>
16+
#include <system_error>
17+
18+
#include "uid.h"
19+
20+
21+
extern "C" {
22+
std::string::size_type c_get_uid(char* result, const std::string::size_type buffer_size) {
23+
return str2char(get_uid(), result, buffer_size);
24+
}
25+
}
26+
27+
std::string::size_type str2char(std::string_view s, char* result, const std::string::size_type buffer_size)
28+
{
29+
if(s.length() >= buffer_size) [[unlikely]]
30+
{
31+
std::cerr << "ERROR: " << s << " " << std::make_error_code(std::errc::result_out_of_range) << "\n";
32+
return 0;
33+
}
34+
35+
s.copy(result, buffer_size);
36+
result[s.length()] = '\0';
37+
return s.length();
38+
}
39+
40+
std::string get_uid()
41+
{
42+
#if defined(_WIN32)
43+
HANDLE hToken = nullptr;
44+
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
45+
std::cerr << "OpenProcessToken failed: " << GetLastError() << "\n";
46+
return {};
47+
}
48+
49+
// get required buffer size
50+
DWORD dwLength = 0;
51+
GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwLength);
52+
53+
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
54+
std::cerr << "GetTokenInformation (size) failed: " << GetLastError() << "\n";
55+
CloseHandle(hToken);
56+
return {};
57+
}
58+
59+
std::vector<BYTE> buffer(dwLength);
60+
61+
if (!GetTokenInformation(hToken, TokenUser, buffer.data(), dwLength, &dwLength)) {
62+
std::cerr << "GetTokenInformation failed: " << GetLastError() << "\n";
63+
CloseHandle(hToken);
64+
return {};
65+
}
66+
67+
PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>(buffer.data());
68+
69+
// Convert SID to string
70+
LPSTR sidString = nullptr;
71+
if (!ConvertSidToStringSidA(pTokenUser->User.Sid, &sidString)) {
72+
std::cerr << "ConvertSidToStringSidA failed: " << GetLastError() << "\n";
73+
CloseHandle(hToken);
74+
return {};
75+
}
76+
77+
std::string result = sidString;
78+
LocalFree(sidString);
79+
CloseHandle(hToken);
80+
81+
return result;
82+
83+
#else
84+
return std::to_string(geteuid());
85+
#endif
86+
}

src/uid/uid.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <string>
2+
#include <string_view>
3+
4+
extern "C" {
5+
std::string::size_type c_get_uid(char*, const std::string::size_type);
6+
}
7+
8+
std::string::size_type str2char(std::string_view, char*, const std::string::size_type);
9+
10+
std::string get_uid();

test/glibc/CMakeLists.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

test/glibc/getuid.f90

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/iterator/standalone.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
#include <cstdlib>
22
#include <string>
33
#include <iostream>
4+
45
#include <memory>
6+
#ifndef __cpp_lib_to_address
7+
#error "C++20 std::to_address is required for this test"
8+
#endif
59

610

711
char* iter_ptr(char* c){

test/uid/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set_property(DIRECTORY PROPERTY LABELS uid)
2+
3+
add_executable(getuid getuid.f90 ${PROJECT_SOURCE_DIR}/src/uid/uid.cpp)
4+
add_test(NAME GetUID COMMAND getuid)

test/uid/getuid.f90

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
program guid
2+
3+
use, intrinsic :: iso_c_binding
4+
5+
implicit none
6+
7+
interface
8+
integer(C_SIZE_T) function c_get_uid(result, buffer_size) bind(C)
9+
import
10+
character(kind=C_CHAR), intent(out) :: result(*)
11+
integer(C_SIZE_T), intent(in), value :: buffer_size
12+
end function
13+
end interface
14+
15+
16+
print '(a)', "UID: " // get_uid()
17+
18+
contains
19+
20+
function get_uid() result(r)
21+
character(:), allocatable :: r
22+
character(kind=c_char, len=:), allocatable :: cbuf
23+
integer(C_SIZE_T) :: N
24+
25+
!! 256 is reasonable max length for Windows SID string representation
26+
allocate(character(256) :: cbuf)
27+
N = len(cbuf)
28+
29+
N = c_get_uid(cbuf, N)
30+
31+
r = cbuf(:N)
32+
end function
33+
34+
end program

0 commit comments

Comments
 (0)