I'm sharing some code here.
It's not completely tested and might contain serious mistakes, repetitions, bad style and readabilty.
But it seems to work.
Critique, improvements and feedback might help.
Demonstration
This code retrieves username of the current windows user using Windows API (Win32).
WindowsGetUserName.d
import core.sys.windows.windows;
import std.conv;
import std.stdio;
import std.range;
pragma(lib, "advapi32.lib");
/**
* Retrieves the currently logged-in user's name in a safe manner.
*
* This function first determines the required buffer size, allocates memory for the username,
* and then retrieves the username.
*
* Returns:
* - The username as a string if successful.
* - An empty string if an error occurs.
*/
string getSafeUsername() @system {
wchar[] userName;
DWORD userNameSize = 0;
// First, try GetUserNameW (Unicode version)
if (!GetUserNameW(null, &userNameSize)) {
int error = GetLastError();
if (error != ERROR_INSUFFICIENT_BUFFER) {
// Failed for a reason other than an insufficient buffer
return "";
}
}
// Allocate memory for userName
scope(exit) userName.length = 0; // Ensure memory is released if an exception occurs
userName.length = userNameSize;
// Retrieve the user name by calling GetUserNameW
if (GetUserNameW(userName.ptr, &userNameSize)) {
// Successfully retrieved the user name, convert it to a string
return to!string(userName);
}
// If GetUserNameW fails, try GetUserNameA (ANSI version)
char[] userNameA;
userNameSize = 0;
if (!GetUserNameA(null, &userNameSize)) {
int errorA = GetLastError();
if (errorA != ERROR_INSUFFICIENT_BUFFER) {
// Failed for a reason other than an insufficient buffer
return "";
}
}
// Allocate memory for userNameA
scope(exit) userNameA.length = 0; // Ensure memory is released if an exception occurs
userNameA.length = userNameSize;
// Retrieve the user name by calling GetUserNameA
if (GetUserNameA(userNameA.ptr, &userNameSize)) {
// Successfully retrieved the user name using ANSI version, convert it to a string
return to!string(userNameA);
}
// Both GetUserNameW and GetUserNameA failed, return an empty string
return "";
}
/**
* The entry point of the application.
*/
void main() {
string username = getSafeUsername();
if (!username.empty) {
writeln("Logged-in user name: ", username);
} else {
writeln("Failed to retrieve the user name.");
}
}
Footnotes
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getusernamea
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getusernamew
https://github.com/dlang/dmd/blob/master/druntime/src/core/sys/windows/winbase.d#L1903-L1904