Directory Services |
The DsCrackSpn function parses a service principal name (SPN) into its component strings.
DWORD DsCrackSpn( LPCTSTR pszSPN, DWORD* pcServiceClass, LPTSTR ServiceClass, DWORD* pcServiceName, LPTSTR ServiceName, DWORD* pcInstanceName, LPTSTR InstanceName, USHORT* pInstancePort );
<service class>/<instance name>:<port number>/<service name>
If this parameter is null, contains zero, or ServiceClass is null, this parameter and ServiceClass are ignored.
To obtain the number of characters required for the ServiceClass string, including the null terminator, call this function with a valid SPN, a non-null ServiceClass and this parameter set to 1.
If this parameter is null, contains zero, or ServiceName is null, this parameter and ServiceName are ignored.
To obtain the number of characters required for the ServiceName string, including the null terminator, call this function with a valid SPN, a non-null ServiceName and this parameter set to 1.
If this parameter is null, contains zero, or InstanceName is null, this parameter and InstanceName are ignored.
To obtain the number of characters required for the InstanceName string, including the null terminator, call this function with a valid SPN, a non-null InstanceName and this parameter set to 1.
Return Code | Description |
---|---|
ERROR_SUCCESS | The function was successful. |
ERROR_INVALID_PARAMETER | pszSPN or the SPN string is not valid. |
ERROR_BUFFER_OVERFLOW | If any of the buffer sizes is too small, the function fails with this error and returns the required buffer size in the corresponding buffer-length parameter. To determine which buffer was too small, compare the returned sizes to the input sizes. Also, the function ignores buffers that are NULL or have a zero size on input. So, it does not return an error or required buffer size in these cases. |
The following code example demonstrates how to use DsCrackSpn to obtain the proper buffer sizes, allocate the appropriate buffers and use DsCrackSpn to parse the SPN.
//*************************************************************************** // // SafeCrackSpn() // // The caller must free any allocated buffers with CoTaskMemFree(). // //*************************************************************************** HRESULT SafeCrackSpn( LPCTSTR pszSPN, LPTSTR *ppszServClass, LPTSTR *ppszServName, LPTSTR *ppszInstName, USHORT *pPortNum) { if(!pszSPN) { return E_INVALIDARG; } // Set the default values. if(ppszServClass) { *ppszServClass = NULL; } if(ppszServName) { *ppszServName = NULL; } if(ppszInstName) { *ppszInstName = NULL; } if(pPortNum) { *pPortNum = 0; } DWORD dwRet; DWORD dwServClassSize; DWORD dwServNameSize; DWORD dwInstNameSize; TCHAR szTemp[1]; dwServClassSize = 1; dwServNameSize = 1; dwInstNameSize = 1; // Call DsCrackSpn to get the sizes of the strings. dwRet = DsCrackSpn( pszSPN, &dwServClassSize, szTemp, &dwServNameSize, szTemp, &dwInstNameSize, szTemp, NULL); if(ERROR_BUFFER_OVERFLOW == dwRet) { HRESULT hr = S_OK; // Allocate the requested buffers and call DsCrackSpn again. if(ppszServClass) { *ppszServClass = (LPTSTR)CoTaskMemAlloc(dwServClassSize * sizeof(TCHAR)); if(!*ppszServClass) { hr = E_OUTOFMEMORY; } } if(ppszServName) { *ppszServName = (LPTSTR)CoTaskMemAlloc(dwServNameSize * sizeof(TCHAR)); if(!*ppszServName) { hr = E_OUTOFMEMORY; } } if(ppszInstName) { *ppszInstName = (LPTSTR)CoTaskMemAlloc(dwInstNameSize * sizeof(TCHAR)); if(!*ppszInstName) { hr = E_OUTOFMEMORY; } } if(SUCCEEDED(hr)) { dwRet = DsCrackSpn( pszSPN, &dwServClassSize, *ppszServClass, &dwServNameSize, *ppszServName, &dwInstNameSize, *ppszInstName, pPortNum); hr = HRESULT_FROM_WIN32(dwRet); } // If a failure occurs, cleanup and return an error code. if(FAILED(hr)) { if(ppszServClass && *ppszServClass) { CoTaskMemFree(*ppszServClass); *ppszServClass = NULL; } if(ppszServName && *ppszServName) { CoTaskMemFree(*ppszServName); *ppszServName = NULL; } if(ppszInstName && *ppszInstName) { CoTaskMemFree(*ppszInstName); *ppszInstName = NULL; } } return hr; } else if(ERROR_SUCCESS == dwRet) { // This should not occur, but if it does, return an error. return E_FAIL; } // An error occurred. Return the error value. return HRESULT_FROM_WIN32(dwRet); } /************************************************************************** main() **************************************************************************/ void main(void) { HRESULT hr; LPTSTR pszServClass; LPTSTR pszServName; LPTSTR pszInstName; USHORT uPortNum; LPCTSTR pszSPN = TEXT("Service Class/Instance Name:80/Service Name"); hr = SafeCrackSpn( pszSPN, &pszServClass, &pszServName, &pszInstName, &uPortNum); if(SUCCEEDED(hr)) { CoTaskMemFree(pszServClass); CoTaskMemFree(pszServName); CoTaskMemFree(pszInstName); } }
Client: Included in Windows XP and
Windows 2000 Professional.
Server: Included in Windows Server 2003 and
Windows 2000 Server.
Redistributable: Requires Active Directory Client Extension
on Windows NT 4.0 SP6a and Windows 95/98/Me.
Unicode: Implemented as Unicode and ANSI versions on Windows
NT/2000/XP.
Header: Declared in Ntdsapi.h.
Library: Use Ntdsapi.lib.