GetUserNameEx is the most flexible, and offers various user names depending on the context and format you're looking to obtain. I don't know if it works in XP, but it does in Windows 2000 and up (tested up to Windows 7, Server 2008 and Windows Server 2012).
Here's a sample console app that has some type definitions that will help, along with the function declaration and sample code that demonstrates the possibilities. It compiles in both D2007 and Seattle/Berlin.
program Project1;
{$APPTYPE CONSOLE}
uses
System.SysUtils, WinAPI.Windows;
type
EXTENDED_NAME_FORMAT = DWORD;
const
NameUnknown = 0;
NameFullyQualifiedDN = 1;
NameSamCompatible = 2;
NameDisplay = 3;
NameUniqueId = 6;
NameCanonical = 7;
NameUserPrincipal = 8;
NameCanonicalEx = 9;
NameServicePrincipal = 10;
NameDnsDomain = 12;
const
NameFormats: array[0..8] of EXTENDED_NAME_FORMAT = (NameFullyQualifiedDN,
NameSamCompatible,
NameDisplay,
NameUniqueID,
NameCanonical,
NameUserPrincipal,
NameCanonicalEx,
NameServicePrincipal,
NameDnsDomain);
function GetUserNameExW(NameFormat: EXTENDED_NAME_FORMAT; lpNameBuffer: LPWSTR;
var nSize: ULONG): BOOL; stdcall;
external 'secur32.dll' Name 'GetUserNameExW';
var
UserName: String;
Size: ULONG;
i: Integer;
begin
for i := Low(NameFormats) to High(NameFormats) do
begin
Size := 0;
GetUserNameExW(NameFormats[i], nil, Size);
SetLength(UserName, Size);
if GetUserNameExW(NameFormats[i], PWideChar(UserName), Size) then
WriteLn(Ord(NameFormats[i]), #32 + UserName);
end;
ReadLn;
end.