/*
 *  strsafe.h   Safe string functions
 *
 * =========================================================================
 *
 *                          Open Watcom Project
 *
 * Copyright (c) 2004-2010 The Open Watcom Contributors. All Rights Reserved.
 *
 *    This file is automatically generated. Do not edit directly.
 *
 * =========================================================================
 */

#ifndef _STRSAFE_H_INCLUDED_
#define _STRSAFE_H_INCLUDED_

#ifndef _ENABLE_AUTODEPEND
 #pragma read_only_file;
#endif

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>

#ifdef __cplusplus
extern "C" {
#endif

/* Safe string maximum length */
#ifndef STRSAFE_MAX_CCH
    #define STRSAFE_MAX_CCH 2147483647
#endif
#define STRSAFE_MAX_LENGTH  (STRSAFE_MAX_CCH - 1)

/* Safe string flags */
#define STRSAFE_IGNORE_NULLS        0x00000100L
#define STRSAFE_FILL_BEHIND_NULL    0x00000200L
#define STRSAFE_FILL_ON_FAILURE     0x00000400L
#define STRSAFE_NULL_ON_FAILURE     0x00000800L
#define STRSAFE_NO_TRUNCATION       0x00001000L
#define STRSAFE_VALID_FLAGS \
    (0x000000FFL | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | \
    STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)

/* Macros to manipulate safe string flags */
#define STRSAFE_FILL_BYTE( x ) \
    ((DWORD)(((x) & 0x000000FFL) | STRSAFE_FILL_BEHIND_NULL))
#define STRSAFE_FAILURE_BYTE( x ) \
    ((DWORD)(((x) & 0x000000FFL) | STRSAFE_FILL_ON_FAILURE))
#define STRSAFE_GET_FILL_PATTERN( x )   ((int)((x) & 0x000000FFL))

/* Safe string error codes */
#define STRSAFE_E_INSUFFICIENT_BUFFER   0x8007007AL
#define STRSAFE_E_INVALID_PARAMETER     0x80070057L
#define STRSAFE_E_END_OF_FILE           0x80070026L

/* Map generic function names to the appropriate ANSI or Unicode version. */
#ifdef UNICODE
    #define StringCbCat         StringCbCatW
    #define StringCbCatEx       StringCbCatExW
    #define StringCbCatN        StringCbCatNW
    #define StringCbCatNEx      StringCbCatNExW
    #define StringCbCopy        StringCbCopyW
    #define StringCbCopyEx      StringCbCopyExW
    #define StringCbCopyN       StringCbCopyNW
    #define StringCbCopyNEx     StringCbCopyNExW
    #define StringCbGets        StringCbGetsW
    #define StringCbGetsEx      StringCbGetsExW
    #define StringCbLength      StringCbLengthW
    #define StringCbPrintf      StringCbPrintfW
    #define StringCbPrintfEx    StringCbPrintfExW
    #define StringCbVPrintf     StringCbVPrintfW
    #define StringCbVPrintfEx   StringCbVPrintfExW
    #define StringCchCat        StringCchCatW
    #define StringCchCatEx      StringCchCatExW
    #define StringCchCatN       StringCchCatNW
    #define StringCchCatNEx     StringCchCatNExW
    #define StringCchCopy       StringCchCopyW
    #define StringCchCopyEx     StringCchCopyExW
    #define StringCchCopyN      StringCchCopyNW
    #define StringCchCopyNEx    StringCchCopyNExW
    #define StringCchGets       StringCchGetsW
    #define StringCchGetsEx     StringCchGetsExW
    #define StringCchLength     StringCchLengthW
    #define StringCchPrintf     StringCchPrintfW
    #define StringCchPrintfEx   StringCchPrintfExW
    #define StringCchVPrintf    StringCchVPrintfW
    #define StringCchVPrintfEx  StringCchVPrintfExW
#else
    #define StringCbCat         StringCbCatA
    #define StringCbCatEx       StringCbCatExA
    #define StringCbCatN        StringCbCatNA
    #define StringCbCatNEx      StringCbCatNExA
    #define StringCbCopy        StringCbCopyA
    #define StringCbCopyEx      StringCbCopyExA
    #define StringCbCopyN       StringCbCopyNA
    #define StringCbCopyNEx     StringCbCopyNExA
    #define StringCbGets        StringCbGetsA
    #define StringCbGetsEx      StringCbGetsExA
    #define StringCbLength      StringCbLengthA
    #define StringCbPrintf      StringCbPrintfA
    #define StringCbPrintfEx    StringCbPrintfExA
    #define StringCbVPrintf     StringCbVPrintfA
    #define StringCbVPrintfEx   StringCbVPrintfExA
    #define StringCchCat        StringCchCatA
    #define StringCchCatEx      StringCchCatExA
    #define StringCchCatN       StringCchCatNA
    #define StringCchCatNEx     StringCchCatNExA
    #define StringCchCopy       StringCchCopyA
    #define StringCchCopyEx     StringCchCopyExA
    #define StringCchCopyN      StringCchCopyNA
    #define StringCchCopyNEx    StringCchCopyNExA
    #define StringCchGets       StringCchGetsA
    #define StringCchGetsEx     StringCchGetsExA
    #define StringCchLength     StringCchLengthA
    #define StringCchPrintf     StringCchPrintfA
    #define StringCchPrintfEx   StringCchPrintfExA
    #define StringCchVPrintf    StringCchVPrintfA
    #define StringCchVPrintfEx  StringCchVPrintfExA
#endif

__inline HRESULT StringCchCatA( LPSTR lpszDestination, size_t cchDestination,
                                LPCSTR lpszSource )
{
    int cchInit;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = strlen( lpszDestination );
    strncat( lpszDestination, lpszSource, cchDestination - cchInit - 1 );
    if( cchInit + strlen( lpszSource ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCatW( LPWSTR lpszDestination, size_t cchDestination,
                                LPCWSTR lpszSource )
{
    int cchInit;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = wcslen( lpszDestination );
    wcsncat( lpszDestination, lpszSource, cchDestination - cchInit - 1 );
    if( cchInit + wcslen( lpszSource ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCatExA( LPSTR lpszDestination, size_t cchDestination,
                                  LPCSTR lpszSource, LPSTR *lplpszDestinationEnd,
                                  size_t *pcchRemaining, DWORD dwFlags )
{
    int cchInit;
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = strlen( lpszDestination );
    cchSource = strlen( lpszSource );
    strncat( lpszDestination, lpszSource, cchDestination - cchInit - 1 );
    if( cchInit + cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchInit - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchInit + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchInit + cchSource + 1,
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchInit - cchSource - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchCatExW( LPWSTR lpszDestination, size_t cchDestination,
                                  LPCWSTR lpszSource, LPWSTR *lplpszDestinationEnd,
                                  size_t *pcchRemaining, DWORD dwFlags )
{
    int cchInit;
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = wcslen( lpszDestination );
    cchSource = wcslen( lpszSource );
    wcsncat( lpszDestination, lpszSource, cchDestination - cchInit - 1 );
    if( cchInit + cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchInit - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchInit + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchInit + cchSource + 1,
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchInit - cchSource - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCchCatNA( LPSTR lpszDestination, size_t cchDestination,
                                 LPCSTR lpszSource, size_t cchMaxAppend )
{
    int cchInit;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = strlen( lpszDestination );
    strncat( lpszDestination, lpszSource,
             max( cchDestination - cchInit - 1, cchMaxAppend ) );
    if( cchInit + min( strlen( lpszSource ), cchMaxAppend ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCatNW( LPWSTR lpszDestination, size_t cchDestination,
                                 LPCWSTR lpszSource, size_t cchMaxAppend )
{
    int cchInit;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = wcslen( lpszDestination );
    wcsncat( lpszDestination, lpszSource,
             max( cchDestination - cchInit - 1, cchMaxAppend ) );
    if( cchInit + min( wcslen( lpszSource ), cchMaxAppend ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCatNExA( LPSTR lpszDestination, size_t cchDestination,
                                   LPCSTR lpszSource, size_t cchMaxAppend,
                                   LPSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                   DWORD dwFlags )
{
    int cchInit;
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = strlen( lpszDestination );
    cchSource = strlen( lpszSource );
    strncat( lpszDestination, lpszSource, 
             max( cchDestination - cchInit - 1, cchMaxAppend ) );
    if( cchInit + min( cchSource, cchMaxAppend ) >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchInit - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchInit + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchInit + cchSource + 1,
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchInit - cchSource - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchCatNExW( LPWSTR lpszDestination, size_t cchDestination,
                                   LPCWSTR lpszSource, size_t cchMaxAppend,
                                   LPWSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                   DWORD dwFlags )
{
    int cchInit;
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchInit = wcslen( lpszDestination );
    cchSource = wcslen( lpszSource );
    wcsncat( lpszDestination, lpszSource, 
             max( cchDestination - cchInit - 1, cchMaxAppend ) );
    if( cchInit + min( cchSource, cchMaxAppend ) >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchInit - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchInit + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchInit + cchSource + 1,
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchInit - cchSource - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCchCopyA( LPSTR lpszDestination, size_t cchDestination,
                                 LPCSTR lpszSource )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    strncpy( lpszDestination, lpszSource, cchDestination - 1 );
    if( strlen( lpszSource ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCopyW( LPWSTR lpszDestination, size_t cchDestination,
                                 LPCWSTR lpszSource )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    wcsncpy( lpszDestination, lpszSource, cchDestination - 1 );
    if( wcslen( lpszSource ) >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCopyExA( LPSTR lpszDestination, size_t cchDestination,
                                   LPCSTR lpszSource, LPSTR *lplpszDestinationEnd,
                                   size_t *pcchRemaining, DWORD dwFlags )
{
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchSource = strlen( lpszSource );
    strncat( lpszDestination, lpszSource, cchDestination - 1 );
    if( cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchSource + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchSource - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchCopyExW( LPWSTR lpszDestination, size_t cchDestination,
                                   LPCWSTR lpszSource, LPWSTR *lplpszDestinationEnd,
                                   size_t *pcchRemaining, DWORD dwFlags )
{
    int cchSource;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchSource = wcslen( lpszSource );
    wcsncat( lpszDestination, lpszSource, cchDestination - 1 );
    if( cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchSource + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchSource - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCchCopyNA( LPSTR lpszDestination, size_t cchDestination,
                                  LPCSTR lpszSource, size_t cchSource )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    strncpy( lpszDestination, lpszSource, min( cchDestination - 1, cchSource ) );
    if( cchSource >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCopyNW( LPWSTR lpszDestination, size_t cchDestination,
                                  LPCWSTR lpszSource, size_t cchSource )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    wcsncpy( lpszDestination, lpszSource, min( cchDestination - 1, cchSource ) );
    if( cchSource >= cchDestination ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchCopyNExA( LPSTR lpszDestination, size_t cchDestination,
                                    LPCSTR lpszSource, int cchSource, 
                                    LPSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                    DWORD dwFlags )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    strncat( lpszDestination, lpszSource, min( cchDestination - 1, cchSource ) );
    if( cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchSource + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchSource - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchCopyNExW( LPWSTR lpszDestination, size_t cchDestination,
                                    LPCWSTR lpszSource, int cchSource, 
                                    LPWSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                    DWORD dwFlags )
{
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    wcsncat( lpszDestination, lpszSource, min( cchDestination - 1, cchSource ) );
    if( cchSource >= cchDestination ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchSource;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchSource;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchSource + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchSource - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCchGetsA( LPSTR lpszDestination, size_t cchDestination )
{
    int ch;
    int i;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    for( i = 0; i < cchDestination; i++ ) {
        ch = getchar();
        if( ch == EOF ) {
            lpszDestination[i] = '\0';
            return( STRSAFE_E_END_OF_FILE );
        } else if( ch == '\n' ) {
            lpszDestination[i] = '\0';
            return( S_OK );
        } else {
            lpszDestination[i] = ch;
        }
    }
    lpszDestination[cchDestination] = '\0';
    return( STRSAFE_E_INSUFFICIENT_BUFFER );
}

__inline HRESULT StringCchGetsW( LPWSTR lpszDestination, size_t cchDestination )
{
    wint_t  ch;
    int     i;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    for( i = 0; i < cchDestination; i++ ) {
        ch = getwchar();
        if( ch == WEOF ) {
            lpszDestination[i] = L'\0';
            return( STRSAFE_E_END_OF_FILE );
        } else if( ch == L'\n' ) {
            lpszDestination[i] = L'\0';
            return( S_OK );
        } else {
            lpszDestination[i] = ch;
        }
    }
    lpszDestination[cchDestination] = L'\0';
    return( STRSAFE_E_INSUFFICIENT_BUFFER );
}

__inline HRESULT StringCchGetsExA( LPSTR lpszDestination, size_t cchDestination,
                                   LPSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                   DWORD dwFlags )
{
    int ch;
    int i;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    for( i = 0; i < cchDestination; i++ ) {
        ch = getchar();
        if( ch == EOF ) {
            break;
        } else if( ch == '\n' ) {
            lpszDestination[i] = '\0';
            if( pcchRemaining != NULL ) {
                *pcchRemaining = cchDestination - i;
            }
            if( lplpszDestinationEnd != NULL ) {
                *lplpszDestinationEnd = lpszDestination + i;
            }
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + i + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - i - 1) );
            }
            return( S_OK );
        } else {
            lpszDestination[i] = ch;
        }
    }
    lpszDestination[cchDestination] = '\0';
    if( dwFlags & STRSAFE_NO_TRUNCATION ) {
        lpszDestination[0] = '\0';
        if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
            memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
        }
    } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
        memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - 1 );
        lpszDestination[cchDestination - 1] = '\0';
    } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
        memset( lpszDestination, '\0', cchDestination );
    }
    if( ch == EOF ) {
        return( STRSAFE_E_END_OF_FILE );
    } else {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
}

__inline HRESULT StringCchGetsExW( LPWSTR lpszDestination, size_t cchDestination,
                                   LPWSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                   DWORD dwFlags )
{
    wint_t  ch;
    int     i;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    for( i = 0; i < cchDestination; i++ ) {
        ch = getwchar();
        if( ch == WEOF ) {
            break;
        } else if( ch == L'\n' ) {
            lpszDestination[i] = L'\0';
            if( pcchRemaining != NULL ) {
                *pcchRemaining = cchDestination - i;
            }
            if( lplpszDestinationEnd != NULL ) {
                *lplpszDestinationEnd = lpszDestination + i;
            }
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + i + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - i - 1) * sizeof( wchar_t ) );
            }
            return( S_OK );
        } else {
            lpszDestination[i] = ch;
        }
    }
    lpszDestination[cchDestination] = L'\0';
    if( dwFlags & STRSAFE_NO_TRUNCATION ) {
        lpszDestination[0] = L'\0';
        if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
            memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
        }
    } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
        memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - 1) * sizeof( wchar_t ) );
        lpszDestination[cchDestination - 1] = L'\0';
    } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
        memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
    }
    if( ch == WEOF ) {
        return( STRSAFE_E_END_OF_FILE );
    } else {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
}

__inline HRESULT StringCchLengthA( LPCSTR lpsz, size_t cchMax, size_t *pcch )
{
    if( lpsz == NULL || cchMax > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    *pcch = strlen( lpsz );
    if( *pcch > cchMax ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchLengthW( LPCWSTR lpsz, size_t cchMax, size_t *pcch )
{
    if( lpsz == NULL || cchMax > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    *pcch = wcslen( lpsz );
    if( *pcch > cchMax ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchPrintfA( LPSTR lpszDestination, size_t cchDestination,
                                   LPCSTR lpszFormat, ... )
{
    va_list args;
    int     cchResult;
    va_start( args, lpszFormat );
    if( cchDestination > STRSAFE_MAX_CCH ) {
        va_end( args );
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnprintf( lpszDestination, cchDestination, lpszFormat, args );
    va_end( args );
    if( cchResult < 0 ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchPrintfW( LPWSTR lpszDestination, size_t cchDestination,
                                   LPCWSTR lpszFormat, ... )
{
    va_list args;
    int     cchResult;
    va_start( args, lpszFormat );
    if( cchDestination > STRSAFE_MAX_CCH ) {
        va_end( args );
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnwprintf( lpszDestination, cchDestination, lpszFormat, args );
    va_end( args );
    if( cchResult < 0 ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchPrintfExA( LPSTR lpszDestination, size_t cchDestination,
                                     LPSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                     DWORD dwFlags, LPCSTR lpszFormat, ... )
{
    va_list args;
    int     cchResult;
    va_start( args, lpszFormat );
    if( cchDestination > STRSAFE_MAX_CCH ) {
        va_end( args );
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnprintf( lpszDestination, cchDestination, lpszFormat, args );
    va_end( args );
    if( cchResult < 0 ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchResult;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchResult;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchResult + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchResult - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchPrintfExW( LPWSTR lpszDestination, size_t cchDestination,
                                     LPWSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                     DWORD dwFlags, LPCWSTR lpszFormat, ... )
{
    va_list args;
    int     cchResult;
    va_start( args, lpszFormat );
    if( cchDestination > STRSAFE_MAX_CCH ) {
        va_end( args );
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnwprintf( lpszDestination, cchDestination, lpszFormat, args );
    va_end( args );
    if( cchResult < 0 ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = L'\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + sizeof( wchar_t ),
                        STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchResult;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchResult;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + (cchResult + 1) * sizeof( wchar_t ),
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchResult - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCchVPrintfA( LPSTR lpszDestination, size_t cchDestination,
                                    LPCSTR lpszFormat, va_list args )
{
    int     cchResult;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnprintf( lpszDestination, cchDestination, lpszFormat, args );
    if( cchResult < 0 ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchVPrintfW( LPWSTR lpszDestination, size_t cchDestination,
                                    LPCWSTR lpszFormat, va_list args )
{
    int     cchResult;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnwprintf( lpszDestination, cchDestination, lpszFormat, args );
    if( cchResult < 0 ) {
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    } else {
        return( S_OK );
    }
}

__inline HRESULT StringCchVPrintfExA( LPSTR lpszDestination, size_t cchDestination,
                                      LPSTR *lplpszDestinationEnd, size_t *pcchRemaining,
                                      DWORD dwFlags, LPCSTR lpszFormat, va_list args )
{
    int     cchResult;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnprintf( lpszDestination, cchDestination, lpszFormat, args );
    if( cchResult < 0 ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = '\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        cchDestination - 1 );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    cchDestination - 1 );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchResult;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchResult;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + cchResult + 1, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                cchDestination - cchResult - 1 );
    }
    return( S_OK );
}

__inline HRESULT StringCchVPrintfExW( LPWSTR lpszDestination, size_t cchDestination,
                                      LPWSTR *lplpszDestinationEnd,
                                      size_t *pcchRemaining, DWORD dwFlags,
                                      LPCWSTR lpszFormat, va_list args )
{
    int     cchResult;
    if( cchDestination > STRSAFE_MAX_CCH ) {
        return( STRSAFE_E_INVALID_PARAMETER );
    }
    cchResult = _vsnwprintf( lpszDestination, cchDestination, lpszFormat, args );
    if( cchResult < 0 ) {
        if( dwFlags & STRSAFE_NO_TRUNCATION ) {
            lpszDestination[0] = L'\0';
            if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
                memset( lpszDestination + sizeof( wchar_t ),
                        STRSAFE_GET_FILL_PATTERN( dwFlags ),
                        (cchDestination - 1) * sizeof( wchar_t ) );
            }
        } else if( dwFlags & STRSAFE_FILL_ON_FAILURE ) {
            memset( lpszDestination, STRSAFE_GET_FILL_PATTERN( dwFlags ),
                    (cchDestination - 1) * sizeof( wchar_t ) );
            lpszDestination[cchDestination - 1] = '\0';
        } else if( dwFlags & STRSAFE_NULL_ON_FAILURE ) {
            memset( lpszDestination, '\0', cchDestination * sizeof( wchar_t ) );
        }
        return( STRSAFE_E_INSUFFICIENT_BUFFER );
    }
    if( pcchRemaining != NULL ) {
        *pcchRemaining = cchDestination - cchResult;
    }
    if( lplpszDestinationEnd != NULL ) {
        *lplpszDestinationEnd = lpszDestination + cchResult;
    }
    if( dwFlags & STRSAFE_FILL_BEHIND_NULL ) {
        memset( lpszDestination + (cchResult + 1) * sizeof( wchar_t ),
                STRSAFE_GET_FILL_PATTERN( dwFlags ),
                (cchDestination - cchResult - 1) * sizeof( wchar_t ) );
    }
    return( S_OK );
}

__inline HRESULT StringCbCatA( LPSTR lpszDestination, size_t cbDestination,
                               LPCSTR lpszSource )
{
    return( StringCchCatA( lpszDestination, cbDestination / sizeof( char ),
                           lpszSource ) );
}

__inline HRESULT StringCbCatW( LPWSTR lpszDestination, size_t cbDestination,
                               LPCWSTR lpszSource )
{
    return( StringCchCatW( lpszDestination, cbDestination / sizeof( wchar_t ),
                           lpszSource ) );
}

__inline HRESULT StringCbCatExA( LPSTR lpszDestination, size_t cbDestination,
                                 LPCSTR lpszSource, LPSTR *lplpszDestinationEnd,
                                 size_t *pcbRemaining, DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCatExA( lpszDestination, cbDestination / sizeof( char ), lpszSource,
                           lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbCatExW( LPWSTR lpszDestination, size_t cbDestination,
                                 LPCWSTR lpszSource, LPWSTR *lplpszDestinationEnd,
                                 size_t *pcbRemaining, DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCatExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                           lpszSource, lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbCatNA( LPSTR lpszDestination, size_t cbDestination,
                                LPCSTR lpszSource, size_t cbMaxAppend )
{
    return( StringCchCatNA( lpszDestination, cbDestination / sizeof( char ), lpszSource,
                            cbMaxAppend / sizeof( char ) ) );
}

__inline HRESULT StringCbCatNW( LPWSTR lpszDestination, size_t cbDestination,
                                LPCWSTR lpszSource, size_t cbMaxAppend )
{
    return( StringCchCatNW( lpszDestination, cbDestination / sizeof( wchar_t ),
                            lpszSource, cbMaxAppend / sizeof( wchar_t ) ) );
}

__inline HRESULT StringCbCatNExA( LPSTR lpszDestination, size_t cbDestination,
                                  LPCSTR lpszSource, size_t cbMaxAppend,
                                  LPSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                  DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCatNExA( lpszDestination, cbDestination / sizeof( char ), lpszSource,
                            cbMaxAppend / sizeof( char ), lplpszDestinationEnd,
                            pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbCatNExW( LPWSTR lpszDestination, size_t cbDestination,
                                  LPCWSTR lpszSource, size_t cbMaxAppend,
                                  LPWSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                  DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCatNExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                            lpszSource, cbMaxAppend / sizeof( wchar_t ),
                            lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbCopyA( LPSTR lpszDestination, size_t cbDestination,
                                LPCSTR lpszSource )
{
    return( StringCchCopyA( lpszDestination, cbDestination / sizeof( char ),
                            lpszSource ) );
}

__inline HRESULT StringCbCopyW( LPWSTR lpszDestination, size_t cbDestination,
                                LPCWSTR lpszSource )
{
    return( StringCchCopyW( lpszDestination, cbDestination / sizeof( wchar_t ),
                            lpszSource ) );
}

__inline HRESULT StringCbCopyExA( LPSTR lpszDestination, size_t cbDestination,
                                  LPCSTR lpszSource, LPSTR *lplpszDestinationEnd,
                                  size_t *pcbRemaining, DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCopyExA( lpszDestination, cbDestination / sizeof( char ), lpszSource,
                            lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbCopyExW( LPWSTR lpszDestination, size_t cbDestination,
                                  LPCWSTR lpszSource, LPWSTR *lplpszDestinationEnd,
                                  size_t *pcbRemaining, DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCopyExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                            lpszSource, lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbCopyNA( LPSTR lpszDestination, size_t cbDestination,
                                 LPCSTR lpszSource, size_t cbSource )
{
    return( StringCchCopyNA( lpszDestination, cbDestination / sizeof( char ),
                             lpszSource, cbSource / sizeof( char ) ) );
}

__inline HRESULT StringCbCopyNW( LPWSTR lpszDestination, size_t cbDestination,
                                 LPCWSTR lpszSource, size_t cbSource )
{
    return( StringCchCopyNW( lpszDestination, cbDestination / sizeof( wchar_t ),
                             lpszSource, cbSource / sizeof( wchar_t ) ) );
}

__inline HRESULT StringCbCopyNExA( LPSTR lpszDestination, size_t cbDestination,
                                   LPCSTR lpszSource, size_t cbSource, 
                                   LPSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                   DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCopyNExA( lpszDestination, cbDestination / sizeof( char ),
                             lpszSource, cbSource / sizeof( char ),
                             lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbCopyNExW( LPWSTR lpszDestination, size_t cbDestination,
                                   LPCWSTR lpszSource, size_t cbSource,
                                   LPWSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                   DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchCopyNExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                             lpszSource, cbSource / sizeof( wchar_t ),
                             lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbGetsA( LPSTR lpszDestination, size_t cbDestination )
{
    return( StringCchGetsA( lpszDestination, cbDestination / sizeof( char ) ) );
}

__inline HRESULT StringCbGetsW( LPWSTR lpszDestination, size_t cbDestination )
{
    return( StringCchGetsW( lpszDestination, cbDestination / sizeof( wchar_t ) ) );
}

__inline HRESULT StringCbGetsExA( LPSTR lpszDestination, size_t cbDestination,
                                  LPSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                  DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchGetsExA( lpszDestination, cbDestination / sizeof( char ),
                            lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbGetsExW( LPWSTR lpszDestination, size_t cbDestination,
                                  LPWSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                  DWORD dwFlags )
{
    HRESULT ret;
    ret = StringCchGetsExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                            lplpszDestinationEnd, pcbRemaining, dwFlags );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbLengthA( LPCSTR lpsz, size_t cbMax, size_t *pcb )
{
    HRESULT ret;
    ret = StringCchLengthA( lpsz, cbMax / sizeof( char ), pcb );
    if( pcb != NULL ) {
        *pcb *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbLengthW( LPCWSTR lpsz, size_t cbMax, size_t *pcb )
{
    HRESULT ret;
    ret = StringCchLengthW( lpsz, cbMax / sizeof( wchar_t ), pcb );
    if( pcb != NULL ) {
        *pcb *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbPrintfA( LPSTR lpszDestination, size_t cbDestination,
                                  LPCSTR lpszFormat, ... )
{
    HRESULT ret;
    va_list args;
    va_start( args, lpszFormat );
    ret = StringCchVPrintfA( lpszDestination, cbDestination / sizeof( char ),
                             lpszFormat, args );
    va_end( args );
    return( ret );
}

__inline HRESULT StringCbPrintfW( LPWSTR lpszDestination, size_t cbDestination,
                                  LPCWSTR lpszFormat, ... )
{
    HRESULT ret;
    va_list args;
    va_start( args, lpszFormat );
    ret = StringCchVPrintfW( lpszDestination, cbDestination / sizeof( wchar_t ),
                             lpszFormat, args );
    va_end( args );
    return( ret );
}

__inline HRESULT StringCbPrintfExA( LPSTR lpszDestination, size_t cbDestination,
                                    LPSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                    DWORD dwFlags, LPCSTR lpszFormat, ... )
{
    HRESULT ret;
    va_list args;
    va_start( args, lpszFormat );
    ret = StringCchVPrintfExA( lpszDestination, cbDestination / sizeof( char ),
                               lplpszDestinationEnd, pcbRemaining, dwFlags, lpszFormat,
                               args );
    va_end( args );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbPrintfExW( LPWSTR lpszDestination, size_t cbDestination,
                                    LPWSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                    DWORD dwFlags, LPCWSTR lpszFormat, ... )
{
    HRESULT ret;
    va_list args;
    va_start( args, lpszFormat );
    ret = StringCchVPrintfExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                               lplpszDestinationEnd, pcbRemaining, dwFlags, lpszFormat,
                               args );
    va_end( args );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

__inline HRESULT StringCbVPrintfA( LPSTR lpszDestination, size_t cbDestination,
                                   LPCSTR lpszFormat, va_list args )
{
    return( StringCchVPrintfA( lpszDestination, cbDestination / sizeof( char ),
                               lpszFormat, args ) );
}

__inline HRESULT StringCbVPrintfW( LPWSTR lpszDestination, size_t cbDestination,
                                   LPCWSTR lpszFormat, va_list args )
{
    return( StringCchVPrintfW( lpszDestination, cbDestination / sizeof( wchar_t ),
                               lpszFormat, args ) );
}

__inline HRESULT StringCbVPrintfExA( LPSTR lpszDestination, size_t cbDestination,
                                     LPSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                     DWORD dwFlags, LPCSTR lpszFormat, va_list args )
{
    HRESULT ret;
    ret = StringCchVPrintfExA( lpszDestination, cbDestination / sizeof( char ),
                               lplpszDestinationEnd, pcbRemaining, dwFlags, lpszFormat,
                               args );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( char );
    }
    return( ret );
}

__inline HRESULT StringCbVPrintfExW( LPWSTR lpszDestination, size_t cbDestination,
                                     LPWSTR *lplpszDestinationEnd, size_t *pcbRemaining,
                                     DWORD dwFlags, LPCWSTR lpszFormat, va_list args )
{
    HRESULT ret;
    ret = StringCchVPrintfExW( lpszDestination, cbDestination / sizeof( wchar_t ),
                               lplpszDestinationEnd, pcbRemaining, dwFlags, lpszFormat,
                               args );
    if( pcbRemaining != NULL ) {
        *pcbRemaining *= sizeof( wchar_t );
    }
    return( ret );
}

#ifdef __cplusplus
} /* extern "C" */
#endif

#endif /* _STRSAFE_H_INCLUDED_ */
