Microsoft KB Archive/288900

{|
 * width="100%"|

HOWTO: Use Visual Basic to Construct a Well-Known SID

 * }

Q288900

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), used with:
 * the operating system: Microsoft Windows 2000
 * the operating system: Microsoft Windows NT 4.0

-

SUMMARY
A security identifier (SID) is used by the operating system to uniquely identify a well-known user account or group account, irrespective of the localized language used by the system. This article contains sample code demonstrating how you can construct a well-known SID by using Microsoft Visual Basic.

MORE INFORMATION
An SID is a variable-length numeric value that consists of a SID structure revision number, a one-byte subauthority count, a 48-bit identifier authority value, and a variable number of 32-bit subauthority or relative identifier (RID) values.

The identifier authority value identifies the agent that issued the SID. The following identifier authorities are predefined:

There are several categories of well-known SIDs. For some types of well-known SIDs, the identifier authority and all of the subauthority values are predefined. In this case, the well-known SID can be constructed using the AllocateAndInitializeSid API. Examples (a) through (c) below describe these categories of well-known SIDs:

(a) Universal well-known SIDs (like Everyone) have only one RID value relative to the identifier authority SECURITY_WORLD_SID_AUTHORITY.

The predefined RID values for universal well-known SIDs are defined in the winnt.h header file as follows:

#define SECURITY_NULL_RID                (0x00000000L)
 * 1) define SECURITY_WORLD_RID               (0x00000000L)
 * 2) define SECURITY_LOCAL_RID               (0x00000000L)


 * 1) define SECURITY_CREATOR_OWNER_RID       (0x00000000L)
 * 2) define SECURITY_CREATOR_GROUP_RID       (0x00000001L)

(b) NT well-known SIDs (like Local System) have only one RID value relative to the identifier authority SECURITY_NT_AUTHORITY.
 * 1) define SECURITY_CREATOR_OWNER_SERVER_RID (0x00000002L)
 * 2) define SECURITY_CREATOR_GROUP_SERVER_RID (0x00000003L)

(c) Well-known aliases (like Administrators and Guests) have two RID values. The first RID value is SECURITY_BUILTIN_DOMAIN_RID and the second is the predefined RID value corresponding to the well-known alias.

The predefined RID values for well-known aliases are defined in the winnt.h header file as follows:

// well-known aliases ...


 * 1) define DOMAIN_ALIAS_RID_ADMINS       (0x00000220L)
 * 2) define DOMAIN_ALIAS_RID_USERS        (0x00000221L)
 * 3) define DOMAIN_ALIAS_RID_GUESTS       (0x00000222L)

There is a final category of well-known SIDs in which the initial subauthority values uniquely identify a specific domain and the final subauthority value is predefined. Example (d) below describes this category of well-known SIDs:

(d) Well-known users (like Domain Admin and Domain Guest) have a predefined RID value relative to a variable domain SID. To construct a well-known SID for one of these accounts, it is first necessary to retrieve the domain SID and then tag on the appropriate predefined RID value.

The predefined RID values for well-known users are defined in the winnt.h header file as follows:

/////////////////////////////////////////////////////////////////////////// // well-known domain relative sub-authority values (RIDs)... // ///////////////////////////////////////////////////////////////////////////

To obtain a SID for the domain, you can use the NetUserModalsGet API. You can use the InitializeSid API to create a copy of the domain SID. You can then construct a well-known SID by appending the final predefined RID value to the SID.
 * 1) define DOMAIN_USER_RID_ADMIN         (0x000001F4L)
 * 2) define DOMAIN_USER_RID_GUEST         (0x000001F5L)

Sample Code
The following Visual Basic sample code implements a sub procedure called ConstructUniversalAndNTWellKnownSids. This procedure uses the AllocateAndInitializeSid API to construct a number of well-known SIDs.

This code also contains a sub procedure called GetWellKnownUserSIDFromRID. This procedure uses the NetUserModalsGet API to retrieve the SID of the domain to which the local computer belongs. It then uses the InitializeSid API to construct a SID for a well-known user in that domain.

Option Explicit

' ' APIs needed to manipulate the RAW SID ' Declare Function AllocateAndInitializeSid Lib &quot;advapi32.dll&quot; _ (pIdentifierAuthority As SID_IDENTIFIER_AUTHORITY, _     ByVal nSubAuthorityCount As Byte, ByVal nSubAuthority0 As Long, _      ByVal nSubAuthority1 As Long, ByVal nSubAuthority2 As Long, _      ByVal nSubAuthority3 As Long, ByVal nSubAuthority4 As Long, _      ByVal nSubAuthority5 As Long, ByVal nSubAuthority6 As Long, _      ByVal nSubAuthority7 As Long, lpPSid As Long) As Long

Declare Sub FreeSid Lib &quot;advapi32.dll&quot; (ByVal pSid As Long)

Declare Function LookupAccountSid Lib &quot;advapi32.dll&quot; _ Alias &quot;LookupAccountSidA&quot; (ByVal lpSystemName As String, _     ByVal Sid As Long, ByVal Name As String, cbName As Long, _      ByVal ReferencedDomainName As String, _      cbReferencedDomainName As Long, peUse As Integer) As Long

Private Declare Function InitializeSid Lib &quot;advapi32.dll&quot; _ (ByVal Sid As Long, ByVal pIndentifierAuthority As Long, _     ByVal nSubAuthorityCount As Byte) As Long

Private Declare Function GetSidSubAuthority Lib &quot;advapi32.dll&quot; _ (ByVal Sid As Long, ByVal nSubAuthority As Long) As Long

Private Declare Function GetSidSubAuthorityCount Lib &quot;advapi32.dll&quot; _ (ByVal Sid As Long) As Long

Private Declare Function GetSidIdentifierAuthority Lib &quot;advapi32.dll&quot; _ (ByVal Sid As Long) As Long Private Declare Function GetSidLengthRequired Lib &quot;advapi32.dll&quot; _ (ByVal nSubAuthorityCount As Byte) As Long

' ' APIs needed to manipulate pointers in VB ' Private Declare Sub CopyMemory Lib &quot;kernel32&quot; Alias &quot;RtlMoveMemory&quot; _ (hpvDest As Any, ByVal hpvSource As Long, ByVal cbCopy As Long) Private Declare Sub CopyDWORDFromPtr Lib &quot;kernel32&quot; Alias &quot;RtlMoveMemory&quot; _ (ByVal hpvDest As Long, ByVal hpvSource As Long, _     ByVal cbCopy As Long)

Private Declare Sub CopyDWORD Lib &quot;kernel32&quot; Alias &quot;RtlMoveMemory&quot; _ (ByVal hpvDest As Long, hpvSource As Long, ByVal cbCopy As Long) Private Declare Function GetProcessHeap Lib &quot;kernel32&quot; As Long

Private Declare Function HeapAlloc Lib &quot;kernel32&quot; (ByVal hHeap As Long, _     ByVal dwFlags As Long, ByVal dwBytes As Long) As Long Private Declare Function HeapFree Lib &quot;kernel32&quot; (ByVal hHeap As Long, _     ByVal dwFlags As Long, ByVal lpMem As Long) As Long ' ' APIs, structures, and constants necessary to obtain the domain SID ' Private Declare Function NetApiBufferFree Lib &quot;netapi32&quot; _ (ByVal Buffer As Long) As Long Private Declare Function NetUserModalsGet Lib &quot;netapi32&quot; _ (ByVal serverName As Long, ByVal level As Long, _     BufPtr As Long) As Long Type USER_MODALS_INFO_2 usrmod2_domain_name As Long usrmod2_domain_id As Long End Type

Public Const NERR_Success = 0 ' ' Constants from WINNT.H for the various well-known SIDs, users and groups ' Public Const SECURITY_WORLD_SID_AUTHORITY = &H1 Public Const SECURITY_NT_AUTHORITY = &H5

Public Const SECURITY_BUILTIN_DOMAIN_RID = &H20& Public Const DOMAIN_ALIAS_RID_ADMINS = &H220& Public Const DOMAIN_ALIAS_RID_USERS = &H221& Public Const SECURITY_LOCAL_SYSTEM_RID = &H12 Public Const SECURITY_WORLD_RID = &H0

Public Const DOMAIN_USER_RID_ADMIN = &H1F4 Public Const DOMAIN_USER_RID_GUEST = &H1F5

Public Const DOMAIN_GROUP_RID_ADMINS = &H200

Type SID_IDENTIFIER_AUTHORITY Value(6) As Byte End Type ' ' Helper function to lookup a SID and display the name as a test ' Public Sub DisplayNameOfSid(ByVal lSid As Long)

Dim result As Long Dim userName As String Dim cbUserName As Long Dim domainName As String Dim cbDomainName As Long Dim peUse As Integer ' Lookup the constructed SID to get the name userName = Space(255) domainName = Space(255) cbUserName = 255 cbDomainName = 255 result = LookupAccountSid(vbNullString, lSid, userName, cbUserName, _        domainName, cbDomainName, peUse)

If result <> 0 Then MsgBox userName End If

End Sub

Public Function GetWellKnownUserSIDFromRID(ByVal Rid As Long) As Long

Dim userInfo As USER_MODALS_INFO_2 Dim wszServerName As Byte Dim BufPtr As Long Dim result As Long Dim pSid As Long Dim Index, Count As Long Dim SubAuthorityCount As Byte Dim domainName As String Dim cbDomainName As Long Dim peUse As Integer Dim srcPtr As Long Dim dstPtr As Long GetWellKnownUserSIDFromRID = 0 ' Get the SID of the local machine result = NetUserModalsGet(ByVal 0&, 2, BufPtr) If result <> NERR_Success Then GetWellKnownUserSIDFromRID = 0 Exit Function End If

' Copy the data in the buffer into USER_MODALS_INFO_2 structure CopyMemory userInfo, BufPtr, Len(userInfo) ' Allocate storage for the new Sid: account domain Sid + account Rid CopyMemory SubAuthorityCount, _ GetSidSubAuthorityCount(userInfo.usrmod2_domain_id), 1 Count = SubAuthorityCount pSid = HeapAlloc(GetProcessHeap, 0, _        GetSidLengthRequired(SubAuthorityCount + 1)) If pSid <> 0 Then If InitializeSid(pSid, _           GetSidIdentifierAuthority(userInfo.usrmod2_domain_id), _            SubAuthorityCount + 1) <> 0 Then ' Copy the existing subauthorities from the account domain Sid ' into the new Sid For Index = 0 To Count - 1 dstPtr = GetSidSubAuthority(pSid, Index) srcPtr = GetSidSubAuthority(userInfo.usrmod2_domain_id, Index) CopyDWORDFromPtr dstPtr, srcPtr, 4 Next Index ' append Rid to new Sid dstPtr = GetSidSubAuthority(pSid, Index) CopyDWORD dstPtr, Rid, 4 End If  End If   NetApiBufferFree BufPtr GetWellKnownUserSIDFromRID = pSid

End Function

Public Sub ConstructWellKnownUserSids

Dim lSid As Long

' Construct SID for Well-known user &quot;Administrator&quot; lSid = GetWellKnownUserSIDFromRID(DOMAIN_USER_RID_ADMIN) If lSid <> 0 Then ' Use the constructed SID in the application DisplayNameOfSid lSid ' Free the heap memory block allocated in     ' GetWellKnownUserSIDFromRID function for the SID HeapFree GetProcessHeap, 0, lSid End If

' Construct SID for Well-known user &quot;Guest&quot; lSid = GetWellKnownUserSIDFromRID(DOMAIN_USER_RID_GUEST) If lSid <> 0 Then ' Use the constructed SID in the application DisplayNameOfSid lSid ' Free the heap memory block allocated in     ' GetWellKnownUserSIDFromRID VB function for the SID HeapFree GetProcessHeap, 0, lSid End If End Sub

Public Sub ConstructUniversalAndNTWellKnownSids Dim result As Long Dim siaNtAuthority As SID_IDENTIFIER_AUTHORITY Dim lSid As Long ' Construct SID for System &quot;NT well-known SID&quot; siaNtAuthority.Value(5) = SECURITY_NT_AUTHORITY result = AllocateAndInitializeSid(siaNtAuthority, 1, _        SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, lSid) ' Use the constructed SID in the application DisplayNameOfSid lSid ' Free the memory allocated for the SID using FreeSid API FreeSid lSid ' Construct SID for Everyone &quot;Universal well-known SID&quot; siaNtAuthority.Value(5) = SECURITY_WORLD_SID_AUTHORITY result = AllocateAndInitializeSid(siaNtAuthority, 1, _        SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, lSid) ' Use the constructed SID in the application DisplayNameOfSid lSid ' Free the memory allocated for the SID using FreeSid API FreeSid lSid ' Construct SID for Administrators &quot;Well-known group&quot; siaNtAuthority.Value(5) = SECURITY_NT_AUTHORITY result = AllocateAndInitializeSid(siaNtAuthority, 2, _        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, _         0, 0, 0, 0, 0, 0, lSid) ' Use the constructed SID in the application DisplayNameOfSid (lSid) ' Free the memory allocated for the SID using FreeSid API FreeSid lSid ' Construct SID for Users &quot;Well-known group&quot; siaNtAuthority.Value(5) = SECURITY_NT_AUTHORITY result = AllocateAndInitializeSid(siaNtAuthority, 2, _        SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, _         0, 0, 0, 0, 0, 0, lSid) ' Use the constructed SID in the application DisplayNameOfSid lSid ' Free the memory allocated for the SID using FreeSid API FreeSid lSid

End Sub Additional query words:

Keywords : kbAPI kbKernBase kbLSA kbSDKWin32 kbSecurity kbDSupport kbGrpDSKernBase

Issue type : kbhowto

Technology : kbAudDeveloper kbWin32sSearch kbWin32API