DsCrackSpn function
The DsCrackSpn function parses a service principal name (SPN) into its component strings.
Syntax
DWORD DsCrackSpn( _In_ LPCTSTR pszSPN, _Inout_opt_ DWORD *pcServiceClass, _Out_opt_ LPTSTR ServiceClass, _Inout_opt_ DWORD *pcServiceName, _Out_opt_ LPTSTR ServiceName, _Inout_opt_ DWORD *pcInstanceName, _Out_opt_ LPTSTR InstanceName, _Out_opt_ USHORT *pInstancePort );
Parameters
- pszSPN [in]
-
Pointer to a constant null-terminated string that contains the SPN to parse. The SPN has the following format, in which the <service class> and <instance name> components must be present and the <port number> and <service name> components are optional. The <port number> component must be a numeric string value.
<service class>/<instance name>:<port number>/<service name>
- pcServiceClass [in, out, optional]
-
Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the ServiceClass buffer, including the terminating null character. On exit, this parameter contains the number of TCHARs in the ServiceClass string, including the terminating null character.
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.
- ServiceClass [out, optional]
-
Pointer to a TCHAR buffer that receives a null-terminated string containing the <service class> component of the SPN. This buffer must be at least *pcServiceClass TCHARs in size. This parameter may be NULL if the service class is not required.
- pcServiceName [in, out, optional]
-
Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the ServiceName buffer, including the terminating null character. On exit, this parameter contains the number of TCHARs in the ServiceName string, including the terminating null character.
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.
- ServiceName [out, optional]
-
Pointer to a TCHAR buffer that receives a null-terminated string containing the <service name> component of the SPN. This buffer must be at least *pcServiceName TCHARs in size. If the <service name> component is not present in the SPN, this buffer receives the <instance name> component. This parameter may be NULL if the service name is not required.
- pcInstanceName [in, out, optional]
-
Pointer to a DWORD value that, on entry, contains the size, in TCHARs, of the InstanceName buffer, including the terminating null character. On exit, this parameter contains the number of TCHARs in the InstanceName string, including the terminating null character.
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.
- InstanceName [out, optional]
-
Pointer to a TCHAR buffer that receives a null-terminated string containing the <instance name> component of the SPN. This buffer must be at least *pcInstanceName TCHARs in size. This parameter may be NULL if the instance name is not required.
- pInstancePort [out, optional]
-
Pointer to a DWORD value that receives the integer value of the <port number> component of the SPN. If the SPN does not contain a <port number> component, this parameter receives zero. This parameter may be NULL if the port number is not required.
Return value
Returns a Win32 error code, including the following.
- 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.
Examples
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); } }
Requirements
Minimum supported client |
Windows Vista |
---|---|
Minimum supported server |
Windows Server 2008 |
Header |
|
Library |
|
DLL |
|
Unicode and ANSI names |
DsCrackSpnW (Unicode) and DsCrackSpnA (ANSI) |
See also