Platform SDK: Active Directory, ADSI, and Directory Services

Composing SPNs for an RpcNs Service

The following sample code composes the service principal names (SPNs) for an RPC service that has an entry in the RpcServices container in the directory. An RPC service uses the RpcNsBindingExport function to create its RpcServices entry.

An RPC service uses this code to build the SPN or SPNs that identify an instance of the service. The service uses this routine at the following times:

The code uses the distinguished name of the service's RpcServices entry to compose the SPN. So before calling this code, call the RpcNsBindingExport function to create the service's RpcServices entry.

The code calls the DsGetSpn function to build an SPN. The SPN is composed from service's class name and the distinguished name of the service's RpcServices entry.

DWORD
SpnCompose(TCHAR ***pspn, unsigned long *pulSpn) 
{
DWORD   status;
TCHAR   szDsEntryName[MAX_PATH];
 
// Items for ADSI.
IADs    *pRoot=NULL;
VARIANT varDSRoot;
HRESULT hr;
 
hr = CoInitialize(NULL);
 
// First get the defaultNamingContext for the local domain.
hr = ADsGetObject(TEXT("LDAP://RootDSE"),
                  IID_IADs,
                  (void**)&pRoot);
 
hr = pRoot->Get(TEXT("defaultNamingContext"), &varDSRoot);
_tprintf(TEXT("\nDS Root :%s\n"), varDSRoot.bstrVal);
 
if (pRoot)
    pRoot->Release();
 
CoUninitialize();
 
// Compose the DN of the service's entry in the RpcServices container,
// which is created by a call to RpcNsBindingExport.
// The entry for an RPC service is in the System/RpcServices container 
// in the defaultNamingContext of the local domain.
_tcscpy(szDsEntryName,
        TEXT("cn=RpcExampleServiceEntry,cn=RpcServices,cn=System,"));
_tcscat(szDsEntryName,varDSRoot.bstrVal);
 
// Build the SPN for this service using the DN and 
// our service's class, "RpcExample".
status = DsGetSpn(
    DS_SPN_SERVICE,     // Type of SPN to create.
    TEXT("RpcExample"), // Service class - a name in this case.
    szDsEntryName,      // DN of the RpcServices for this RPC service.
    0,                  // Use the default instance port.
    0,                  // Number of additional instance names.
    NULL,               // No additional instance names.
    NULL,               // No additional instance ports.
    pulSpn,             // Size of SPN array.
    pspn                // Returned SPN(s).
    );
 
return status;
}