Directory Services

Registering the SPNs for a Service

The following code example registers or unregisters one or more service principal names (SPNs) for a service instance.

The example calls the DsWriteAccountSpn function, which stores the SPNs in Microsoft Active Directory® under the servicePrincipalName attribute of the account object specified by the pszServiceAcctDN parameter. The account object corresponds to the logon account specified in the CreateService call for this service instance. If the logon account is a domain user account, pszServiceAcctDN must be the distinguished name of the account object in Active Directory for that user account. If the service's logon account is the LocalSystem account, pszServiceAcctDN must be the distinguished name of the computer account object for the host computer on which the service is installed.

[C++]
/***************************************************************************

	SpnRegister()

	Register or unregister the SPNs under the service's account.

	If the service runs in LocalSystem account, pszServiceAcctDN is the 
	distinguished name of the local computer account.

	Parameters:

	pszServiceAcctDN - Contains the distinguished name of the logon 
	account for this instance of the service.

	pspn - Contains an array of SPNs to register.

	ulSpn - Contains the number of SPNs in the array.

	Operation - Contains one of the DS_SPN_WRITE_OP values that determines 
	the type of operation to perform on the SPNs.

***************************************************************************/

DWORD SpnRegister(TCHAR *pszServiceAcctDN,
				TCHAR **pspn,
				unsigned long ulSpn,
				DS_SPN_WRITE_OP Operation)
{
	DWORD dwStatus;
	HANDLE hDs;
	TCHAR szSamName[512];
	DWORD dwSize = sizeof(szSamName);
	PDOMAIN_CONTROLLER_INFO pDcInfo;

	// Bind to a domain controller. 
	// Get the domain for the current user.
	if(GetUserNameEx(NameSamCompatible, szSamName, &dwSize))
	{
		TCHAR *pWhack = _tcschr(szSamName, '\\');
		if(pWhack)
		{
			*pWhack = '\0';
	}
} 
	else 
	{
		return GetLastError();
}
	 
	// Get the name of a domain controller in that domain.
	dwStatus = DsGetDcName(NULL,
		szSamName,
		NULL,
		NULL,
		DS_IS_FLAT_NAME |
			DS_RETURN_DNS_NAME |
			DS_DIRECTORY_SERVICE_REQUIRED,
		&pDcInfo);
	if(dwStatus != 0) 
	{
		return dwStatus;
}
	 
	// Bind to the domain controller.
	dwStatus = DsBind(pDcInfo->DomainControllerName, NULL, &hDs);
	 
	// Free the DOMAIN_CONTROLLER_INFO buffer.
	NetApiBufferFree(pDcInfo);
	if(dwStatus != 0) 
	{
		return dwStatus;
}
	 
	// Write the SPNs to the service account or computer account.
	dwStatus = DsWriteAccountSpn(
			hDs, 				// Handle to the directory.
			Operation, 		// Add or remove SPN from account's existing SPNs.
			pszServiceAcctDN,  // DN of service account or computer account.
			ulSpn, 			// Number of SPNs to add.
			(const TCHAR **)pspn);  // Array of SPNs.

	// Unbind the DS in any case.
	DsUnBind(&hDs);
	 
	return dwStatus;
}