Introduction
Anyone who has ever used advanced security in Windows NT has probably run across SIDs before. SID is an acronym for Security
IDentifier. A SID is a structure of variable length that uniquely identifies a user or group on Windows NT. SIDs are often viewed in string form, for example 'S-1-5-21-1431262831-1455604309-1834353910-1000'. However all the Win32 API that work with SIDs use the binary representation. As such the programmer may need to convert between string and binary representations of SIDs.
Starting in Windows 2000 Microsoft added two APIs for converting SIDs. They are
ConvertStringSidToSid() and ConvertSidToStringSid(). The down-side to these APIs is they require the Platform SDK (for the file SDDL.H) and they don't work on Windows NT. If you are content with these restrictions, then I encourage you to use the Microsoft APIs. But if you need to convert SIDs in Windows NT then you'll need to write your own functions. Realizing there was no built-in way to convert SIDs in Windows NT, Microsoft released two Knowledgebase articles Q198907 and Q131320. These articles provide two functions to handle the conversion. I took these two functions, fixed a few minor bugs, and cleaned up the code to result in the following functions. It should be noted that no SID conversion functions work on Win95/98/ME. Only NT-based operating systems use SIDs and therefore only those systems contain the Win32 APIs that use SIDs.
PSID GetBinarySid(LPCTSTR szSid)
{
_ASSERTE(szSid);
_ASSERTE(lstrlen(szSid));
PSID pSid = NULL;
LPTSTR szSidCopy = NULL;
try
{
int i;
LPTSTR ptr, ptr1;
SID_IDENTIFIER_AUTHORITY sia; ZeroMemory(&sia, sizeof(sia));
BYTE nByteAuthorityCount = 0;
DWORD dwSubAuthority[8] = {0, 0, 0, 0, 0, 0, 0, 0};
szSidCopy = new TCHAR[lstrlen(szSid) + 1];
lstrcpy(szSidCopy, szSid);
if(!(ptr = _tcschr(szSidCopy, _T('-'))))
return NULL;
ptr++;
if(!(ptr = _tcschr(ptr, _T('-'))))
return NULL;
ptr++;
if(!(ptr1 = _tcschr(ptr, _T('-'))))
return NULL;
*ptr1= 0;
if((*ptr == _T('0')) && (*(ptr + 1) == _T('x')))
{
_stscanf(ptr, _T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
&sia.Value[0],
&sia.Value[1],
&sia.Value[2],
&sia.Value[3],
&sia.Value[4],
&sia.Value[5]);
}
else
{
DWORD dwValue;
_stscanf(ptr, _T("%lu"), &dwValue);
sia.Value[5] = (BYTE)(dwValue & 0x000000FF);
sia.Value[4] = (BYTE)(dwValue & 0x0000FF00) >> 8;
sia.Value[3] = (BYTE)(dwValue & 0x00FF0000) >> 16;
sia.Value[2] = (BYTE)(dwValue & 0xFF000000) >> 24;
}
*ptr1 = '-';
ptr = ptr1;
ptr1++;
for(i = 0; i < 8; i++)
{
if(!(ptr = _tcschr(ptr, _T('-'))))
break;
*ptr = 0;
ptr++;
nByteAuthorityCount++;
}
for(i = 0; i < nByteAuthorityCount; i++)
{
_stscanf(ptr1, _T("%lu"), &dwSubAuthority[i]);
ptr1 += lstrlen(ptr1) + 1;
}
delete[] szSidCopy;
szSidCopy = NULL;
if(!AllocateAndInitializeSid(&sia,
nByteAuthorityCount,
dwSubAuthority[0],
dwSubAuthority[1],
dwSubAuthority[2],
dwSubAuthority[3],
dwSubAuthority[4],
dwSubAuthority[5],
dwSubAuthority[6],
dwSubAuthority[7],
&pSid))
{
pSid = NULL;
}
}
catch(...)
{
delete[] szSidCopy;
pSid = NULL;
}
return pSid;
}
bool GetTextualSid(const PSID pSid, LPTSTR szSid, DWORD &dwBufferSize)
{
_ASSERTE(pSid);
_ASSERTE(szSid);
bool bRtnVal = true;
try
{
PSID_IDENTIFIER_AUTHORITY psia;
DWORD dwSidSize, dwSubAuthorities;
if(!IsValidSid(pSid))
return false;
psia = GetSidIdentifierAuthority(pSid);
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
if(dwBufferSize < dwSidSize)
{
dwBufferSize = dwSidSize;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return false;
}
dwSidSize = _stprintf(szSid, _T("S-%lu-"), SID_REVISION);
if((psia->Value[0] != 0) || (psia->Value[1] != 0))
{
dwSidSize += _stprintf(szSid + lstrlen(szSid),
_T("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
(USHORT)psia->Value[0],
(USHORT)psia->Value[1],
(USHORT)psia->Value[2],
(USHORT)psia->Value[3],
(USHORT)psia->Value[4],
(USHORT)psia->Value[5]);
}
else
{
dwSidSize += _stprintf(szSid + lstrlen(szSid),
_T("%lu"),
(ULONG)(psia->Value[5]) +
(ULONG)(psia->Value[4] << 8) +
(ULONG)(psia->Value[3] << 16) +
(ULONG)(psia->Value[2] << 24) );
}
for(DWORD dwCounter = 0; dwCounter < dwSubAuthorities; dwCounter++)
{
dwSidSize += _stprintf(szSid + dwSidSize, _T("-%lu"),
*GetSidSubAuthority(pSid, dwCounter));
}
}
catch(...)
{
bRtnVal = false;
}
return bRtnVal;
}