Platform SDK: Active Directory, ADSI, and Directory Services

Manipulating Security Descriptors and SIDs

The following examples demonstrate how to obtain the SID for a user name, create a security descriptor, and convert them to a string of hexadecimal digits.

Example Code for Getting the SID

LPTSTR pUsername = USERNAME;
LPTSTR pDCName = PDC_NAME;
unsigned long ulSidLen = 0;
LPTSTR pDomain = NULL;
unsigned long ulDomLen = 0;
SID_NAME_USE peUse;
BOOL bSuccess = FALSE;
PSID pSid = NULL;

if (LookupAccountName(pDCName,
                      pUsername,
                      pSid,
                      &ulSidLen,
                      pDomain,
                      &ulDomLen,
                      &peUse) == 0)
{
    pSid = (PSID)new char[ulSidLen];
    pDomain = new wchar_t[ulDomLen];

    if (pSid && pDomain)
    {
        bSuccess = LookupAccountName(pDCName,
                                     pUsername,
                                     pSid,
                                     &ulSidLen,
                                     pDomain,
                                     &ulDomLen,
                                     &peUse);

    }
    delete [] pDomain;
}

// Must convert the binary SID structure to a string of hex digits
BinaryToOctetString((byte *)pSid, ulSidLen, &pSASID);
delete [] pSid;

Note: This example is specific to Exchange Server version 5.5 and below, and is not upwardly compatible with Exchange 6.0. Management and access of Exchange 6.0 Servers should be made through the CDO Exchange Management interfaces instead.

Example Code for Setting Security Descriptors

TRUSTEE ownerTrustee;
TRUSTEE groupTrustee;
EXPLICIT_ACCESS expAccess[1];
SECURITY_DESCRIPTOR *pSD;
ULONG ulSDLen;
LPWSTR strLogin = DOMAIN_USERNAME
SAFEARRAY *pSASD;

ownerTrustee.pMultipleTrustee = NULL;
ownerTrustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
ownerTrustee.TrusteeForm = TRUSTEE_IS_NAME;
ownerTrustee.TrusteeType = TRUSTEE_IS_USER;
ownerTrustee.ptstrName = strLogin;

groupTrustee.pMultipleTrustee = NULL;
groupTrustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
groupTrustee.TrusteeForm = TRUSTEE_IS_NAME;
groupTrustee.TrusteeType = TRUSTEE_IS_GROUP;
groupTrustee.ptstrName = strLogin;

expAccess[0].grfAccessPermissions = ACCESS_MASK; // magic number
expAccess[0].grfAccessMode = SET_ACCESS;
expAccess[0].grfInheritance = NO_INHERITANCE;
memcpy(&(expAccess[0].Trustee), &ownerTrustee, sizeof(TRUSTEE));
expAccess[0].Trustee.ptstrName = strLogin;

if (BuildSecurityDescriptor(&ownerTrustee,
                            &groupTrustee,
                            1, expAccess,
                            0, NULL, NULL,
                            &ulSDLen, (void**)&pSD)==ERROR_SUCCESS)
{
    BinaryToOctetString((byte *)pSD, ulSDLen, &pSASD);
{
else
{
      wprintf(L"Invalid SD");
      return 1;
}
delete [] strLogin;

// Converting to Hexadecimal
void BinaryToOctetString(byte* buf, unsigned long ulLen, SAFEARRAY **saOctStr)
{
    unsigned long i;
    SAFEARRAY* pSATemp; 
    SAFEARRAYBOUND rgsabound[1];
    char elm[3];
    long dim[1];

    rgsabound[0].lLbound = 0;
    rgsabound[0].cElements = 2 * ulLen;

    pSATemp = SafeArrayCreate(VT_UI1, 1, rgsabound);

    if (pSATemp) 
    {
        for (i=0; i < ulLen; i++)
        {
            sprintf(elm, "%02hx", buf[i] );
            dim[0] = i * 2;
            SafeArrayPutElement(pSATemp, dim, elm);
            dim[0] = i * 2 + 1;
            SafeArrayPutElement(pSATemp, dim, &(elm[1]));
        }
        *saOctStr = pSATemp;
    }
}

Note: This example is specific to Exchange Server version 5.5 and below, and is not upwardly compatible with Exchange 6.0. Management and access of Exchange 6.0 Servers should be made through the CDO Exchange Management interfaces instead.