Export (0) Print
Expand All

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.

Return codeDescription
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 2003

Header

Dsparse.h (include Ntdsapi.h)

Library

Ntdsapi.lib

DLL

Ntdsapi.dll

Unicode and ANSI names

DsCrackSpnW (Unicode) and DsCrackSpnA (ANSI)

See also

Domain Controller and Replication Management Functions

 

 

Show:
© 2015 Microsoft