[PSDK]
authorRafal Harabien <rafalh@reactos.org>
Fri, 25 Mar 2011 21:42:48 +0000 (21:42 +0000)
committerRafal Harabien <rafalh@reactos.org>
Fri, 25 Mar 2011 21:42:48 +0000 (21:42 +0000)
Import strsafe.h from mingw-w64. It's more complete compared to our headers

[DDK]
Import ntstrsafe.h from mingw-w64 (converted from strsafe.h). It's more complete compared to our headers

[NTOSKRNL]
Use sizeof instead of magic numbers

Let's use strsafe functions now instead of strncpy/wcsncpy, which doesn't always NULL terminate :)

svn path=/trunk/; revision=51135

reactos/base/applications/notepad/notepad.h
reactos/include/ddk/ntstrsafe.h
reactos/include/psdk/strsafe.h
reactos/ntoskrnl/ex/init.c

index bc910ab..909eca2 100644 (file)
@@ -1,3 +1,7 @@
+#ifndef STRSAFE_NO_DEPRECATE
+#define STRSAFE_NO_DEPRECATE
+#endif
+
 #include <assert.h>
 #include <stdio.h>
 #include <windows.h>
 #include <assert.h>
 #include <stdio.h>
 #include <windows.h>
index c107a0d..d34b889 100644 (file)
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         This file is in the public domain.
- * FILE:            include/ddk/ntstrsafe.h
- * PURPOSE:         Safe String Library for NT Code (Native/Kernel)
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
  */
  */
-
-/* INCLUDES ******************************************************************/
-
 #ifndef _NTSTRSAFE_H_INCLUDED_
 #define _NTSTRSAFE_H_INCLUDED_
 
 #ifndef _NTSTRSAFE_H_INCLUDED_
 #define _NTSTRSAFE_H_INCLUDED_
 
-//
-// Dependencies
-//
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
 
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
 
-//
-// Maximum limits: allow overriding the maximum
-//
+#ifndef C_ASSERT
+#ifdef _MSC_VER
+# define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
+#else
+# define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
+#endif
+#endif /* C_ASSERT */
+
+#ifdef __cplusplus
+#define _STRSAFE_EXTERN_C extern "C"
+#else
+#define _STRSAFE_EXTERN_C extern
+#endif
+
+#define NTSTRSAFEAPI static __inline NTSTATUS NTAPI
+#define NTSTRSAFE_INLINE_API static __inline NTSTATUS NTAPI
+
 #ifndef NTSTRSAFE_MAX_CCH
 #ifndef NTSTRSAFE_MAX_CCH
-#define NTSTRSAFE_MAX_CCH       2147483647
+#define NTSTRSAFE_MAX_CCH 2147483647
 #endif
 #endif
-#define NTSTRSAFE_MAX_LENGTH    (NTSTRSAFE_MAX_CCH - 1)
 
 
-//
-// Typedefs
-//
-typedef unsigned long DWORD;
+#ifndef _STRSAFE_H_INCLUDED_
+#define STRSAFE_IGNORE_NULLS 0x00000100
+#define STRSAFE_FILL_BEHIND_NULL 0x00000200
+#define STRSAFE_FILL_ON_FAILURE 0x00000400
+#define STRSAFE_NULL_ON_FAILURE 0x00000800
+#define STRSAFE_NO_TRUNCATION 0x00001000
+#define STRSAFE_IGNORE_NULL_UNICODE_STRINGS 0x00010000
+#define STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED 0x00020000
+
+#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
+#define STRSAFE_UNICODE_STRING_VALID_FLAGS (STRSAFE_VALID_FLAGS | STRSAFE_IGNORE_NULL_UNICODE_STRINGS | STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED)
 
 
-/* PRIVATE FUNCTIONS *********************************************************/
+#define STRSAFE_FILL_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
+#define STRSAFE_FAILURE_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
 
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringLengthWorkerA(IN LPCSTR String,
-                       IN SIZE_T MaxLength,
-                       OUT PSIZE_T ReturnLength OPTIONAL)
+#define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)((dwFlags) & 0x000000FF))
+#endif
+
+typedef char *STRSAFE_LPSTR;
+typedef const char *STRSAFE_LPCSTR;
+typedef wchar_t *STRSAFE_LPWSTR;
+typedef const wchar_t *STRSAFE_LPCWSTR;
+
+typedef ULONG STRSAFE_DWORD;
+
+NTSTRSAFEAPI RtlStringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+NTSTRSAFEAPI RtlStringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy);
+NTSTRSAFEAPI RtlStringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy);
+NTSTRSAFEAPI RtlStringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+NTSTRSAFEAPI RtlStringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend);
+NTSTRSAFEAPI RtlStringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend);
+NTSTRSAFEAPI RtlStringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength);
+NTSTRSAFEAPI RtlStringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength);
+
+NTSTRSAFEAPI RtlStringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+
+
+NTSTRSAFEAPI RtlStringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc)
 {
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    SIZE_T LocalMax = MaxLength;
+    return (cchDest > NTSTRSAFE_MAX_CCH ? STATUS_INVALID_PARAMETER : RtlStringCopyWorkerA(pszDest,cchDest,pszSrc));
+}
 
 
-    while (MaxLength && (*String != ANSI_NULL))
-    {
-        String++;
-        MaxLength--;
-    }
+NTSTRSAFEAPI RtlStringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyWorkerW(pszDest,cchDest,pszSrc);
+}
 
 
-    if (!MaxLength) Status = STATUS_INVALID_PARAMETER;
 
 
-    if (ReturnLength)
-    {
-        if (NT_SUCCESS(Status))
-        {
-            *ReturnLength = LocalMax - MaxLength;
-        }
-        else
-        {
-            *ReturnLength = 0;
-        }
-    }
+NTSTRSAFEAPI RtlStringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc);
 
 
-    return Status;
+
+NTSTRSAFEAPI RtlStringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc)
+{
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyWorkerA(pszDest,cbDest,pszSrc);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringValidateDestA(IN LPSTR Destination,
-                       IN SIZE_T Length,
-                       OUT PSIZE_T ReturnLength OPTIONAL,
-                       IN SIZE_T MaxLength)
+NTSTRSAFEAPI RtlStringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc)
 {
 {
-    NTSTATUS Status = STATUS_SUCCESS;
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyWorkerW(pszDest,cchDest,pszSrc);
+}
+
+
+NTSTRSAFEAPI RtlStringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+
+NTSTRSAFEAPI RtlStringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyExWorkerA(pszDest,cchDest,cchDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+NTSTRSAFEAPI RtlStringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    size_t cbDest;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    cbDest = cchDest * sizeof(wchar_t);
+    return RtlStringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+
+NTSTRSAFEAPI RtlStringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
 
 
-    if (!(Length) || (Length > MaxLength)) Status = STATUS_INVALID_PARAMETER;
 
 
-    if (ReturnLength)
+NTSTRSAFEAPI RtlStringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchRemaining = 0;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    Status = RtlStringCopyExWorkerA(pszDest,cbDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+    if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
     {
     {
-        if (NT_SUCCESS(Status))
-        {
-            Status = RtlStringLengthWorkerA(Destination,
-                                            Length,
-                                            ReturnLength);
-        }
-        else
-        {
-            *ReturnLength = 0;
-        }
+        if (pcbRemaining)
+            *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
     }
     }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    size_t cchRemaining = 0;
 
 
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    Status = RtlStringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (pcbRemaining)
+            *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+    }
     return Status;
 }
 
     return Status;
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringExValidateDestA(IN OUT LPSTR *Destination,
-                         IN OUT PSIZE_T DestinationLength,
-                         OUT PSIZE_T ReturnLength OPTIONAL,
-                         IN SIZE_T MaxLength,
-                         IN DWORD Flags)
+
+NTSTRSAFEAPI RtlStringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy);
+NTSTRSAFEAPI RtlStringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy);
+
+
+NTSTRSAFEAPI RtlStringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy)
 {
 {
-    ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
-    return RtlStringValidateDestA(*Destination,
-                                  *DestinationLength,
-                                  ReturnLength,
-                                  MaxLength);
+    if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNWorkerA(pszDest,cchDest,pszSrc,cchToCopy);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringExValidateSrcA(IN OUT LPCSTR *Source OPTIONAL,
-                        IN OUT PSIZE_T ReturnLength OPTIONAL,
-                        IN SIZE_T MaxLength,
-                        IN DWORD Flags)
+NTSTRSAFEAPI RtlStringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy)
 {
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+    if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy);
+}
 
 
-    if ((ReturnLength) && (*ReturnLength >= MaxLength))
-    {
-        Status = STATUS_INVALID_PARAMETER;
-    }
 
 
-    return Status;
+NTSTRSAFEAPI RtlStringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy);
+NTSTRSAFEAPI RtlStringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy);
+
+
+NTSTRSAFEAPI RtlStringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy)
+{
+    if (cbDest > NTSTRSAFE_MAX_CCH || cbToCopy > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNWorkerA(pszDest,cbDest,pszSrc,cbToCopy);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringVPrintfWorkerA(OUT LPSTR Destination,
-                        IN SIZE_T Length,
-                        OUT PSIZE_T NewLength OPTIONAL,
-                        IN LPCSTR Format,
-                        IN va_list argList)
+NTSTRSAFEAPI RtlStringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy)
 {
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    LONG Return;
-    SIZE_T MaxLength, LocalNewLength = 0;
+    size_t cchDest  = cbDest / sizeof(wchar_t);
+    size_t cchToCopy = cbToCopy / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH || cchToCopy > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy);
+}
 
 
-    MaxLength = Length - 1;
 
 
-    Return = _vsnprintf(Destination, MaxLength, Format, argList);
-    if ((Return < 0) || ((SIZE_T)Return > MaxLength))
-    {
-        Destination += MaxLength;
-        *Destination = ANSI_NULL;
+NTSTRSAFEAPI RtlStringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
 
 
-        LocalNewLength = MaxLength;
 
 
-        Status = STATUS_BUFFER_OVERFLOW;
-    }
-    else if ((SIZE_T)Return == MaxLength)
-    {
-        Destination += MaxLength;
-        *Destination = ANSI_NULL;
+NTSTRSAFEAPI RtlStringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNExWorkerA(pszDest,cchDest,cchDest,pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags);
+}
 
 
-        LocalNewLength = MaxLength;
-    }
+NTSTRSAFEAPI RtlStringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCopyNExWorkerW(pszDest,cchDest,cchDest * sizeof(wchar_t),pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+
+NTSTRSAFEAPI RtlStringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+
+NTSTRSAFEAPI RtlStringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchRemaining = 0;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
     else
     else
-    {
-        LocalNewLength = Return;
-    }
+        Status = RtlStringCopyNExWorkerA(pszDest,cbDest,cbDest,pszSrc,cbToCopy,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = cchRemaining;
+    return Status;
+}
 
 
-    if (NewLength) *NewLength = LocalNewLength;
+NTSTRSAFEAPI RtlStringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchDest;
+    size_t cchToCopy;
+    size_t cchRemaining = 0;
+    cchDest = cbDest / sizeof(wchar_t);
+    cchToCopy = cbToCopy / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringCopyNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
     return Status;
 }
 
     return Status;
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringCopyWorkerA(OUT LPSTR Destination,
-                     IN SIZE_T Length,
-                     OUT PSIZE_T NewLength OPTIONAL,
-                     IN LPCSTR Source,
-                     IN SIZE_T CopyLength)
+
+NTSTRSAFEAPI RtlStringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+
+
+NTSTRSAFEAPI RtlStringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc)
 {
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    SIZE_T LocalNewLength = 0;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatWorkerA(pszDest,cchDest,pszSrc);
+}
 
 
-    while ((Length) && (CopyLength) && (*Source != ANSI_NULL))
-    {
-        *Destination++ = *Source++;
-        Length--;
-        CopyLength--;
+NTSTRSAFEAPI RtlStringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatWorkerW(pszDest,cchDest,pszSrc);
+}
 
 
-        LocalNewLength++;
-    }
 
 
-    if (!Length)
-    {
-        Destination--;
-        LocalNewLength--;
+NTSTRSAFEAPI RtlStringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc);
+NTSTRSAFEAPI RtlStringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc);
 
 
-        Status = STATUS_BUFFER_OVERFLOW;
-    }
 
 
-    *Destination = ANSI_NULL;
+NTSTRSAFEAPI RtlStringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc)
+{
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatWorkerA(pszDest,cbDest,pszSrc);
+}
 
 
-    if (NewLength) *NewLength = LocalNewLength;
-    return Status;
+NTSTRSAFEAPI RtlStringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc)
+{
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatWorkerW(pszDest,cchDest,pszSrc);
 }
 
 }
 
-/* PUBLIC FUNCTIONS **********************************************************/
 
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringCchCopyA(IN LPSTR Destination,
-                  IN SIZE_T cchDest,
-                  IN LPCSTR pszSrc)
+NTSTRSAFEAPI RtlStringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+
+NTSTRSAFEAPI RtlStringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
 {
 {
-    ASSERTMSG("RtlStringCchCopyA is UNIMPLEMENTED!\n", FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatExWorkerA(pszDest,cchDest,cchDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
 }
 
 }
 
-static __inline
-NTSTATUS
-RtlStringCbPrintfA(OUT LPSTR Destination,
-                   IN SIZE_T Length,
-                   IN LPCSTR Format,
-                   ...)
+NTSTRSAFEAPI RtlStringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
 {
 {
-    NTSTATUS Status;
-    SIZE_T CharLength = Length / sizeof(CHAR);
-    va_list argList;
+    size_t cbDest = cchDest*sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
 
 
-    Status = RtlStringValidateDestA(Destination,
-                                    CharLength,
-                                    NULL,
-                                    NTSTRSAFE_MAX_CCH);
-    if (NT_SUCCESS(Status))
-    {
-        va_start(argList, Format);
-        Status = RtlStringVPrintfWorkerA(Destination,
-                                         CharLength,
-                                         NULL,
-                                         Format,
-                                         argList);
-        va_end(argList);
-    }
 
 
+NTSTRSAFEAPI RtlStringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+
+NTSTRSAFEAPI RtlStringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchRemaining = 0;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringCatExWorkerA(pszDest,cbDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
     return Status;
 }
 
     return Status;
 }
 
-static __inline
-NTSTATUS
-RtlStringCbPrintfExA(OUT LPSTR Destination,
-                     IN SIZE_T Length,
-                     OUT LPSTR *DestinationEnd OPTIONAL,
-                     OUT PSIZE_T RemainingSize OPTIONAL,
-                     IN DWORD Flags,
-                     IN LPCSTR Format,
-                     ...)
+NTSTRSAFEAPI RtlStringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
 {
     NTSTATUS Status;
 {
     NTSTATUS Status;
-    SIZE_T CharLength = Length / sizeof(CHAR), Remaining, LocalNewLength = 0;
-    PCHAR LocalDestinationEnd;
-    va_list argList;
-    ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    size_t cchRemaining = 0;
 
 
-    Status = RtlStringExValidateDestA(&Destination,
-                                      &CharLength,
-                                      NULL,
-                                      NTSTRSAFE_MAX_CCH,
-                                      Flags);
-    if (NT_SUCCESS(Status))
-    {
-        LocalDestinationEnd = Destination;
-        Remaining = CharLength;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+    return Status;
+}
 
 
-        Status = RtlStringExValidateSrcA(&Format,
-                                         NULL,
-                                         NTSTRSAFE_MAX_CCH,
-                                         Flags);
-        if (NT_SUCCESS(Status))
-        {
-            if (!Length)
-            {
-                if (*Format != ANSI_NULL)
-                {
-                    if (!Destination)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-                    else
-                    {
-                        Status = STATUS_BUFFER_OVERFLOW;
-                    }
-                }
-            }
-            else
-            {
-                va_start(argList, Format);
-                Status = RtlStringVPrintfWorkerA(Destination,
-                                                 CharLength,
-                                                 &LocalNewLength,
-                                                 Format,
-                                                 argList);
-                va_end(argList);
 
 
-                LocalDestinationEnd = Destination + LocalNewLength;
-                Remaining = CharLength - LocalNewLength;
-            }
-        }
-        else
-        {
-            if (Length) *Destination = ANSI_NULL;
-        }
+NTSTRSAFEAPI RtlStringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend);
+NTSTRSAFEAPI RtlStringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend);
 
 
-        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
-        {
-            if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
 
 
-            if (RemainingSize)
-            {
-                *RemainingSize = (Remaining * sizeof(CHAR)) +
-                                 (Length % sizeof(CHAR));
-            }
-        }
-    }
+NTSTRSAFEAPI RtlStringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNWorkerA(pszDest,cchDest,pszSrc,cchToAppend);
+}
 
 
-    return Status;
+NTSTRSAFEAPI RtlStringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringCbCopyExA(OUT LPSTR Destination,
-                   IN SIZE_T Length,
-                   IN LPCSTR Source,
-                   OUT LPSTR *DestinationEnd OPTIONAL,
-                   OUT PSIZE_T RemainingSize OPTIONAL,
-                   IN DWORD Flags)
+
+NTSTRSAFEAPI RtlStringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend);
+NTSTRSAFEAPI RtlStringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend);
+
+
+NTSTRSAFEAPI RtlStringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend)
 {
 {
-    NTSTATUS Status;
-    SIZE_T CharLength = Length / sizeof(CHAR), Copied = 0, Remaining;
-    PCHAR LocalDestinationEnd;
-    ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
-
-    Status = RtlStringExValidateDestA(&Destination,
-                                      &Length,
-                                      NULL,
-                                      NTSTRSAFE_MAX_CCH,
-                                      Flags);
-    if (NT_SUCCESS(Status))
-    {
-        LocalDestinationEnd = Destination;
-        Remaining = CharLength;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNWorkerA(pszDest,cbDest,pszSrc,cbToAppend);
+}
 
 
-        Status = RtlStringExValidateSrcA(&Source,
-                                         NULL,
-                                         NTSTRSAFE_MAX_CCH,
-                                         Flags);
-        if (NT_SUCCESS(Status))
-        {
-            if (!CharLength)
-            {
-                if (*Source != ANSI_NULL)
-                {
-                    if (!Destination)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-                    else
-                    {
-                        Status = STATUS_BUFFER_OVERFLOW;
-                    }
-                }
-            }
-            else
-            {
-                Status = RtlStringCopyWorkerA(Destination,
-                                              CharLength,
-                                              &Copied,
-                                              Source,
-                                              NTSTRSAFE_MAX_LENGTH);
+NTSTRSAFEAPI RtlStringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend)
+{
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    size_t cchToAppend = cbToAppend / sizeof(wchar_t);
 
 
-                LocalDestinationEnd = Destination + Copied;
-                Remaining = CharLength - Copied;
-            }
-        }
-        else
-        {
-            if (CharLength) *Destination = ANSI_NULL;
-        }
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend);
+}
 
 
-        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
-        {
-            if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
 
 
-            if (RemainingSize)
-            {
-                *RemainingSize = (Remaining * sizeof(CHAR)) +
-                                 (Length % sizeof(CHAR));
-            }
-        }
-    }
+NTSTRSAFEAPI RtlStringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
 
 
-    return Status;
+
+NTSTRSAFEAPI RtlStringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNExWorkerA(pszDest,cchDest,cchDest,pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags);
 }
 
 }
 
-static __inline
-NTSTATUS
-RtlStringCbPrintfW(
-    LPWSTR pszDest,
-    IN size_t cbDest,
-    IN LPCWSTR pszFormat,
-    ...)
+NTSTRSAFEAPI RtlStringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
 {
 {
-    ASSERTMSG("RtlStringCbPrintfW is UNIMPLEMENTED!\n", FALSE);
-    return STATUS_NOT_IMPLEMENTED;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringCatNExWorkerW(pszDest,cchDest,(cchDest*sizeof(wchar_t)),pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringCbCatExA(IN OUT LPSTR Destination,
-                  IN SIZE_T Length,
-                  IN LPCSTR Source,
-                  OUT LPSTR *DestinationEnd OPTIONAL,
-                  OUT PSIZE_T RemainingSize OPTIONAL,
-                  IN DWORD Flags)
+
+NTSTRSAFEAPI RtlStringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+NTSTRSAFEAPI RtlStringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+
+NTSTRSAFEAPI RtlStringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
 {
     NTSTATUS Status;
 {
     NTSTATUS Status;
-    SIZE_T CharLength = Length / sizeof(CHAR);
-    SIZE_T DestinationLength, Remaining, Copied = 0;
-    PCHAR LocalDestinationEnd;
-    ASSERTMSG("We don't support Extended Flags yet!\n", Flags == 0);
-
-    Status = RtlStringExValidateDestA(&Destination,
-                                      &CharLength,
-                                      &DestinationLength,
-                                      NTSTRSAFE_MAX_CCH,
-                                      Flags);
-    if (NT_SUCCESS(Status))
-    {
-        LocalDestinationEnd = Destination + DestinationLength;
-        Remaining = CharLength - DestinationLength;
+    size_t cchRemaining = 0;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringCatNExWorkerA(pszDest,cbDest,cbDest,pszSrc,cbToAppend,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+    return Status;
+}
 
 
-        Status = RtlStringExValidateSrcA(&Source,
-                                         NULL,
-                                         NTSTRSAFE_MAX_CCH,
-                                         Flags);
-        if (NT_SUCCESS(Status))
-        {
-            if (Remaining <= 1)
-            {
-                if (*Source != ANSI_NULL)
-                {
-                    if (!Destination)
-                    {
-                        Status = STATUS_INVALID_PARAMETER;
-                    }
-                    else
-                    {
-                        Status = STATUS_BUFFER_OVERFLOW;
-                    }
-                }
-            }
-            else
-            {
-                Status = RtlStringCopyWorkerA(LocalDestinationEnd,
-                                              Remaining,
-                                              &Copied,
-                                              Source,
-                                              NTSTRSAFE_MAX_LENGTH);
+NTSTRSAFEAPI RtlStringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status;
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    size_t cchToAppend = cbToAppend / sizeof(wchar_t);
+    size_t cchRemaining = 0;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringCatNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,&cchRemaining,dwFlags);
+    if ((NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) && pcbRemaining)
+        *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+    return Status;
+}
 
 
-                LocalDestinationEnd = LocalDestinationEnd + Copied;
-                Remaining = Remaining - Copied;
-            }
-        }
 
 
-        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
-        {
-            if (DestinationEnd) *DestinationEnd = LocalDestinationEnd;
+NTSTRSAFEAPI RtlStringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
 
 
-            if (RemainingSize)
-            {
-                *RemainingSize = (Remaining * sizeof(CHAR)) +
-                                 (Length % sizeof(CHAR));
-            }
-        }
-    }
 
 
-    return Status;
+NTSTRSAFEAPI RtlStringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList);
 }
 
 }
 
-static __inline
-NTSTATUS
-NTAPI
-RtlStringCbCopyA(OUT LPSTR Destination,
-                 IN SIZE_T Length,
-                 IN LPCSTR Source)
+NTSTRSAFEAPI RtlStringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList)
 {
 {
-    NTSTATUS Status;
-    SIZE_T CharLength = Length / sizeof(CHAR);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+}
 
 
-    Status = RtlStringValidateDestA(Destination,
-                                    CharLength,
-                                    NULL,
-                                    NTSTRSAFE_MAX_CCH);
-    if (NT_SUCCESS(Status))
-    {
-        Status = RtlStringCopyWorkerA(Destination,
-                                      CharLength,
-                                      NULL,
-                                      Source,
-                                      NTSTRSAFE_MAX_LENGTH);
-    }
 
 
+NTSTRSAFEAPI RtlStringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+
+NTSTRSAFEAPI RtlStringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringVPrintfWorkerA(pszDest,cbDest,pszFormat,argList);
+}
+
+NTSTRSAFEAPI RtlStringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList)
+{
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    return RtlStringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+}
+
+
+NTSTRSAFEAPI RtlStringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...);
+NTSTRSAFEAPI RtlStringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...);
+
+
+NTSTRSAFEAPI RtlStringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    va_list argList;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList);
+    va_end(argList);
     return Status;
 }
 
     return Status;
 }
 
-#endif /* _NTSTRSAFE_H_INCLUDED_ */
+NTSTRSAFEAPI RtlStringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    va_list argList;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+    va_end(argList);
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...);
+NTSTRSAFEAPI RtlStringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...);
+
+
+NTSTRSAFEAPI RtlStringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    va_list argList;
+    if (cbDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfWorkerA(pszDest,cbDest,pszFormat,argList);
+    va_end(argList);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    va_list argList;
+    size_t cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+    va_end(argList);
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...);
+NTSTRSAFEAPI RtlStringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...);
+
+
+NTSTRSAFEAPI RtlStringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    va_list argList;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfExWorkerA(pszDest,cchDest,cchDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+    va_end(argList);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    size_t cbDest = cchDest * sizeof(wchar_t);
+    va_list argList;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        return STATUS_INVALID_PARAMETER;
+    va_start(argList,pszFormat);
+    Status = RtlStringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+    va_end(argList);
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...);
+NTSTRSAFEAPI RtlStringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...);
+
+
+NTSTRSAFEAPI RtlStringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+    cchDest = cbDest / sizeof(char);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        va_list argList;
+        va_start(argList,pszFormat);
+        Status = RtlStringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+        va_end(argList);
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (pcbRemaining)
+        {
+            *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...)
+{
+    NTSTATUS Status;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+    cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        va_list argList;
+        va_start(argList,pszFormat);
+        Status = RtlStringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+        va_end(argList);
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (pcbRemaining)
+        {
+            *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+
+NTSTRSAFEAPI RtlStringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        size_t cbDest;
+        cbDest = cchDest*sizeof(char);
+        Status = RtlStringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status;
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        size_t cbDest;
+        cbDest = cchDest*sizeof(wchar_t);
+        Status = RtlStringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+    }
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+NTSTRSAFEAPI RtlStringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+
+NTSTRSAFEAPI RtlStringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+    cchDest = cbDest / sizeof(char);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (pcbRemaining)
+        {
+            *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+        }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status;
+    size_t cchDest;
+    size_t cchRemaining = 0;
+    cchDest = cbDest / sizeof(wchar_t);
+    if (cchDest > NTSTRSAFE_MAX_CCH)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (pcbRemaining)
+        {
+            *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+        }
+    }
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength);
+NTSTRSAFEAPI RtlStringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength);
+
+
+NTSTRSAFEAPI RtlStringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength)
+{
+    NTSTATUS Status;
+    if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringLengthWorkerA(psz,cchMax,pcchLength);
+    if (!NT_SUCCESS(Status) && pcchLength)
+    {
+        *pcchLength = 0;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength)
+{
+    NTSTATUS Status;
+    if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringLengthWorkerW(psz,cchMax,pcchLength);
+    if (!NT_SUCCESS(Status) && pcchLength)
+    {
+        *pcchLength = 0;
+    }
+    return Status;
+}
+
+
+NTSTRSAFEAPI RtlStringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength);
+NTSTRSAFEAPI RtlStringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength);
+
+
+NTSTRSAFEAPI RtlStringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength)
+{
+    NTSTATUS Status;
+    size_t cchMax;
+    size_t cchLength = 0;
+    cchMax = cbMax / sizeof(char);
+    if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringLengthWorkerA(psz,cchMax,&cchLength);
+    if (pcbLength)
+    {
+        if (NT_SUCCESS(Status))
+        {
+            *pcbLength = cchLength*sizeof(char);
+        }
+        else
+        {
+            *pcbLength = 0;
+        }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength)
+{
+    NTSTATUS Status;
+    size_t cchMax;
+    size_t cchLength = 0;
+    cchMax = cbMax / sizeof(wchar_t);
+    if (!psz || (cchMax > NTSTRSAFE_MAX_CCH))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        Status = RtlStringLengthWorkerW(psz,cchMax,&cchLength);
+    if (pcbLength)
+    {
+        if (NT_SUCCESS(Status))
+        {
+            *pcbLength = cchLength*sizeof(wchar_t);
+        }
+        else
+        {
+            *pcbLength = 0;
+        }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        while(cchDest && (*pszSrc!='\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+        }
+        if (cchDest==0)
+        {
+            pszDest--;
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        *pszDest= '\0';
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        while(cchDest && (*pszSrc!=L'\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+        }
+        if (cchDest==0)
+        {
+            pszDest--;
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        *pszDest= L'\0';
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest!=0) || (cbDest!=0))
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            if (!pszSrc)
+                pszSrc = "";
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+                if (*pszSrc!='\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+                while(cchRemaining && (*pszSrc!='\0'))
+                {
+                    *pszDestEnd++ = *pszSrc++;
+                    cchRemaining--;
+                }
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+                    }
+                }
+                else
+                {
+                    pszDestEnd--;
+                    cchRemaining++;
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                *pszDestEnd = '\0';
+            }
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPWSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest!=0) || (cbDest!=0))
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            if (!pszSrc)
+                pszSrc = L"";
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+                if (*pszSrc!=L'\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = cchDest;
+                while(cchRemaining && (*pszSrc!=L'\0'))
+                {
+                    *pszDestEnd++ = *pszSrc++;
+                    cchRemaining--;
+                }
+                if (cchRemaining > 0)
+                {
+                    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                    {
+                        memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                    }
+                }
+                else
+                {
+                    pszDestEnd--;
+                    cchRemaining++;
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                *pszDestEnd = L'\0';
+            }
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchSrc)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        while(cchDest && cchSrc && (*pszSrc!='\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+            cchSrc--;
+        }
+        if (cchDest==0)
+        {
+            pszDest--;
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        *pszDest= '\0';
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        while(cchDest && cchToCopy && (*pszSrc!=L'\0'))
+        {
+            *pszDest++ = *pszSrc++;
+            cchDest--;
+            cchToCopy--;
+        }
+        if (cchDest==0)
+        {
+            pszDest--;
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        *pszDest= L'\0';
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        if (cchToCopy > NTSTRSAFE_MAX_CCH)
+            Status = STATUS_INVALID_PARAMETER;
+        else
+        {
+            if (dwFlags & STRSAFE_IGNORE_NULLS)
+            {
+                if (!pszDest)
+                {
+                    if ((cchDest!=0) || (cbDest!=0))
+                        Status = STATUS_INVALID_PARAMETER;
+                }
+                if (!pszSrc)
+                    pszSrc = "";
+            }
+            if (NT_SUCCESS(Status))
+            {
+                if (cchDest==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = 0;
+                    if ((cchToCopy!=0) && (*pszSrc!='\0'))
+                    {
+                        if (!pszDest)
+                            Status = STATUS_INVALID_PARAMETER;
+                        else
+                            Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                }
+                else
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    while(cchRemaining && cchToCopy && (*pszSrc!='\0'))
+                    {
+                        *pszDestEnd++ = *pszSrc++;
+                        cchRemaining--;
+                        cchToCopy--;
+                    }
+                    if (cchRemaining > 0)
+                    {
+                        if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                        {
+                            memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+                        }
+                    }
+                    else
+                    {
+                        pszDestEnd--;
+                        cchRemaining++;
+                        Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPWSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        if (cchToCopy > NTSTRSAFE_MAX_CCH)
+            Status = STATUS_INVALID_PARAMETER;
+        else
+        {
+            if (dwFlags & STRSAFE_IGNORE_NULLS)
+            {
+                if (!pszDest)
+                {
+                    if ((cchDest!=0) || (cbDest!=0))
+                        Status = STATUS_INVALID_PARAMETER;
+                }
+                if (!pszSrc)
+                    pszSrc = L"";
+            }
+            if (NT_SUCCESS(Status))
+            {
+                if (cchDest==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = 0;
+                    if ((cchToCopy!=0) && (*pszSrc!=L'\0'))
+                    {
+                        if (!pszDest)
+                            Status = STATUS_INVALID_PARAMETER;
+                        else
+                            Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                }
+                else
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    while(cchRemaining && cchToCopy && (*pszSrc!=L'\0'))
+                    {
+                        *pszDestEnd++ = *pszSrc++;
+                        cchRemaining--;
+                        cchToCopy--;
+                    }
+                    if (cchRemaining > 0)
+                    {
+                        if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                        {
+                            memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                        }
+                    }
+                    else
+                    {
+                        pszDestEnd--;
+                        cchRemaining++;
+                        Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc)
+{
+    NTSTATUS Status;
+    size_t cchDestLength;
+    Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+    if (NT_SUCCESS(Status))
+        Status = RtlStringCopyWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc)
+{
+    NTSTATUS Status;
+    size_t cchDestLength;
+    Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+    if (NT_SUCCESS(Status))
+        Status = RtlStringCopyWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        size_t cchDestLength;
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest==0) && (cbDest==0))
+                    cchDestLength = 0;
+                else
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            else
+            {
+                Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+                if (NT_SUCCESS(Status))
+                {
+                    pszDestEnd = pszDest + cchDestLength;
+                    cchRemaining = cchDest - cchDestLength;
+                }
+            }
+            if (!pszSrc)
+                pszSrc = "";
+        }
+        else
+        {
+            Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+            if (NT_SUCCESS(Status))
+            {
+                pszDestEnd = pszDest + cchDestLength;
+                cchRemaining = cchDest - cchDestLength;
+            }
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                if (*pszSrc!='\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+                Status = RtlStringCopyExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+            }
+            if (dwFlags & STRSAFE_NULL_ON_FAILURE)
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPWSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        size_t cchDestLength;
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest==0) && (cbDest==0))
+                    cchDestLength = 0;
+                else
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            else
+            {
+                Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+                if (NT_SUCCESS(Status))
+                {
+                    pszDestEnd = pszDest + cchDestLength;
+                    cchRemaining = cchDest - cchDestLength;
+                }
+            }
+            if (!pszSrc)
+                pszSrc = L"";
+        }
+        else
+        {
+            Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+            if (NT_SUCCESS(Status))
+            {
+                pszDestEnd = pszDest + cchDestLength;
+                cchRemaining = cchDest - cchDestLength;
+            }
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                if (*pszSrc!=L'\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+                Status = RtlStringCopyExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+            }
+            if (dwFlags & STRSAFE_NULL_ON_FAILURE)
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend)
+{
+    NTSTATUS Status;
+    size_t cchDestLength;
+    Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+    if (NT_SUCCESS(Status))
+        Status = RtlStringCopyNWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend)
+{
+    NTSTATUS Status;
+    size_t cchDestLength;
+    Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+    if (NT_SUCCESS(Status))
+        Status = RtlStringCopyNWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend);
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    size_t cchDestLength = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        if (cchToAppend > NTSTRSAFE_MAX_CCH)
+            Status = STATUS_INVALID_PARAMETER;
+        else
+        {
+            if (dwFlags & STRSAFE_IGNORE_NULLS)
+            {
+                if (!pszDest)
+                {
+                    if ((cchDest==0) && (cbDest==0))
+                        cchDestLength = 0;
+                    else
+                        Status = STATUS_INVALID_PARAMETER;
+                }
+                else
+                {
+                    Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+                    if (NT_SUCCESS(Status))
+                    {
+                        pszDestEnd = pszDest + cchDestLength;
+                        cchRemaining = cchDest - cchDestLength;
+                    }
+                }
+                if (!pszSrc)
+                    pszSrc = "";
+            }
+            else
+            {
+                Status = RtlStringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+                if (NT_SUCCESS(Status))
+                {
+                    pszDestEnd = pszDest + cchDestLength;
+                    cchRemaining = cchDest - cchDestLength;
+                }
+            }
+            if (NT_SUCCESS(Status))
+            {
+                if (cchDest==0)
+                {
+                    if ((cchToAppend!=0) && (*pszSrc!='\0'))
+                    {
+                        if (!pszDest)
+                            Status = STATUS_INVALID_PARAMETER;
+                        else
+                            Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                }
+                else
+                    Status = RtlStringCopyNExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPWSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    size_t cchDestLength = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+        if (cchToAppend > NTSTRSAFE_MAX_CCH)
+            Status = STATUS_INVALID_PARAMETER;
+        else
+        {
+            if (dwFlags & STRSAFE_IGNORE_NULLS)
+            {
+                if (!pszDest)
+                {
+                    if ((cchDest==0) && (cbDest==0))
+                        cchDestLength = 0;
+                    else
+                        Status = STATUS_INVALID_PARAMETER;
+                }
+                else
+                {
+                    Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+                    if (NT_SUCCESS(Status))
+                    {
+                        pszDestEnd = pszDest + cchDestLength;
+                        cchRemaining = cchDest - cchDestLength;
+                    }
+                }
+                if (!pszSrc)
+                    pszSrc = L"";
+            }
+            else
+            {
+                Status = RtlStringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+                if (NT_SUCCESS(Status))
+                {
+                    pszDestEnd = pszDest + cchDestLength;
+                    cchRemaining = cchDest - cchDestLength;
+                }
+            }
+            if (NT_SUCCESS(Status))
+            {
+                if (cchDest==0)
+                {
+                    if ((cchToAppend!=0) && (*pszSrc!=L'\0'))
+                    {
+                        if (!pszDest)
+                            Status = STATUS_INVALID_PARAMETER;
+                        else
+                            Status = STATUS_BUFFER_OVERFLOW;
+                    }
+                }
+                else
+                    Status = RtlStringCopyNExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+            }
+        }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        int iRet;
+        size_t cchMax;
+        cchMax = cchDest - 1;
+        iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList);
+        if ((iRet < 0) || (((size_t)iRet) > cchMax))
+        {
+            pszDest += cchMax;
+            *pszDest = '\0';
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        else
+            if (((size_t)iRet)==cchMax)
+            {
+                pszDest += cchMax;
+                *pszDest = '\0';
+            }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    if (cchDest==0)
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        int iRet;
+        size_t cchMax;
+        cchMax = cchDest - 1;
+        iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList);
+        if ((iRet < 0) || (((size_t)iRet) > cchMax))
+        {
+            pszDest += cchMax;
+            *pszDest = L'\0';
+            Status = STATUS_BUFFER_OVERFLOW;
+        }
+        else
+            if (((size_t)iRet)==cchMax)
+            {
+                pszDest += cchMax;
+                *pszDest = L'\0';
+            }
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest!=0) || (cbDest!=0))
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            if (!pszFormat)
+                pszFormat = "";
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+                if (*pszFormat!='\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+            {
+                int iRet;
+                size_t cchMax;
+                cchMax = cchDest - 1;
+                iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList);
+                if ((iRet < 0) || (((size_t)iRet) > cchMax))
+                {
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+                    *pszDestEnd = '\0';
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                else
+                    if (((size_t)iRet)==cchMax)
+                    {
+                        pszDestEnd = pszDest + cchMax;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+                    else
+                        if (((size_t)iRet) < cchMax)
+                        {
+                            pszDestEnd = pszDest + iRet;
+                            cchRemaining = cchDest - iRet;
+                            if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                            {
+                                memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+                            }
+                        }
+            }
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = '\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = '\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    STRSAFE_LPWSTR pszDestEnd = pszDest;
+    size_t cchRemaining = 0;
+    if (dwFlags & (~STRSAFE_VALID_FLAGS))
+        Status = STATUS_INVALID_PARAMETER;
+    else
+    {
+        if (dwFlags & STRSAFE_IGNORE_NULLS)
+        {
+            if (!pszDest)
+            {
+                if ((cchDest!=0) || (cbDest!=0))
+                    Status = STATUS_INVALID_PARAMETER;
+            }
+            if (!pszFormat)
+                pszFormat = L"";
+        }
+        if (NT_SUCCESS(Status))
+        {
+            if (cchDest==0)
+            {
+                pszDestEnd = pszDest;
+                cchRemaining = 0;
+                if (*pszFormat!=L'\0')
+                {
+                    if (!pszDest)
+                        Status = STATUS_INVALID_PARAMETER;
+                    else
+                        Status = STATUS_BUFFER_OVERFLOW;
+                }
+            }
+            else
+            {
+                int iRet;
+                size_t cchMax;
+                cchMax = cchDest - 1;
+                iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList);
+                if ((iRet < 0) || (((size_t)iRet) > cchMax))
+                {
+                    pszDestEnd = pszDest + cchMax;
+                    cchRemaining = 1;
+                    *pszDestEnd = L'\0';
+                    Status = STATUS_BUFFER_OVERFLOW;
+                }
+                else
+                    if (((size_t)iRet)==cchMax)
+                    {
+                        pszDestEnd = pszDest + cchMax;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+                    else
+                        if (((size_t)iRet) < cchMax)
+                        {
+                            pszDestEnd = pszDest + iRet;
+                            cchRemaining = cchDest - iRet;
+                            if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
+                            {
+                                memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+                            }
+                        }
+            }
+        }
+    }
+    if (!NT_SUCCESS(Status))
+    {
+        if (pszDest)
+        {
+            if (dwFlags & STRSAFE_FILL_ON_FAILURE)
+            {
+                memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+                if (STRSAFE_GET_FILL_PATTERN(dwFlags)==0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                }
+                else
+                    if (cchDest > 0)
+                    {
+                        pszDestEnd = pszDest + cchDest - 1;
+                        cchRemaining = 1;
+                        *pszDestEnd = L'\0';
+                    }
+            }
+            if (dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION))
+            {
+                if (cchDest > 0)
+                {
+                    pszDestEnd = pszDest;
+                    cchRemaining = cchDest;
+                    *pszDestEnd = L'\0';
+                }
+            }
+        }
+    }
+    if (NT_SUCCESS(Status) || (Status==STATUS_BUFFER_OVERFLOW))
+    {
+        if (ppszDestEnd)
+            *ppszDestEnd = pszDestEnd;
+        if (pcchRemaining)
+            *pcchRemaining = cchRemaining;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    size_t cchMaxPrev = cchMax;
+    while(cchMax && (*psz!='\0'))
+    {
+        psz++;
+        cchMax--;
+    }
+    if (cchMax==0)
+        Status = STATUS_INVALID_PARAMETER;
+    if (pcchLength)
+    {
+        if (NT_SUCCESS(Status))
+            *pcchLength = cchMaxPrev - cchMax;
+        else
+            *pcchLength = 0;
+    }
+    return Status;
+}
+
+NTSTRSAFEAPI RtlStringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+    size_t cchMaxPrev = cchMax;
+    while(cchMax && (*psz!=L'\0'))
+    {
+        psz++;
+        cchMax--;
+    }
+    if (cchMax==0)
+        Status = STATUS_INVALID_PARAMETER;
+    if (pcchLength)
+    {
+        if (NT_SUCCESS(Status))
+            *pcchLength = cchMaxPrev - cchMax;
+        else
+            *pcchLength = 0;
+    }
+    return Status;
+}
+
+
+
+#define RtlStringCopyWorkerA RtlStringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define RtlStringCopyWorkerW RtlStringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define RtlStringCopyExWorkerA RtlStringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define RtlStringCopyExWorkerW RtlStringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define RtlStringCatWorkerA RtlStringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define RtlStringCatWorkerW RtlStringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define RtlStringCatExWorkerA RtlStringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define RtlStringCatExWorkerW RtlStringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define RtlStringCatNWorkerA RtlStringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
+#define RtlStringCatNWorkerW RtlStringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
+#define RtlStringCatNExWorkerA RtlStringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
+#define RtlStringCatNExWorkerW RtlStringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
+#define RtlStringVPrintfWorkerA RtlStringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define RtlStringVPrintfWorkerW RtlStringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define RtlStringVPrintfExWorkerA RtlStringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define RtlStringVPrintfExWorkerW RtlStringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define RtlStringLengthWorkerA RtlStringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
+#define RtlStringLengthWorkerW RtlStringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
+
+#endif
index 0f84a20..f3f7eac 100644 (file)
-#ifndef __STRSAFE_H_
-#define __STRSAFE_H_
-
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the w64 mingw-runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#ifndef _STRSAFE_H_INCLUDED_
+#define _STRSAFE_H_INCLUDED_
+
+#include <_mingw_unicode.h>
 #include <stdio.h>
 #include <stdio.h>
-#include <stdlib.h>
+#include <string.h>
 #include <stdarg.h>
 #include <stdarg.h>
+#include <specstrings.h>
+
+#ifndef _SIZE_T_DEFINED
+#define _SIZE_T_DEFINED
+#undef size_t
+#ifdef _WIN64
+__MINGW_EXTENSION typedef unsigned __int64 size_t;
+#else
+typedef unsigned int size_t;
+#endif
+#endif
+
+#ifndef _SSIZE_T_DEFINED
+#define _SSIZE_T_DEFINED
+#undef ssize_t
+#ifdef _WIN64
+__MINGW_EXTENSION typedef __int64 ssize_t;
+#else
+typedef int ssize_t;
+#endif
+#endif
+
+#ifndef _WCHAR_T_DEFINED
+#define _WCHAR_T_DEFINED
+typedef unsigned short wchar_t;
+#endif
 
 
-#if defined(STRSAFE_NO_CCH_FUNCTIONS) && defined(STRSAFE_NO_CB_FUNCTIONS)
-#error Both STRSAFE_NO_CCH_FUNCTIONS and STRSAFE_NO_CB_FUNCTIONS are defined
+#ifndef _HRESULT_DEFINED
+#define _HRESULT_DEFINED
+typedef long HRESULT;
 #endif
 
 #ifndef SUCCEEDED
 #endif
 
 #ifndef SUCCEEDED
-#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
+#define SUCCEEDED(hr) ((HRESULT)(hr) >= 0)
+#endif
+
+#ifndef FAILED
+#define FAILED(hr) ((HRESULT)(hr) < 0)
+#endif
+
+#ifndef S_OK
+#define S_OK ((HRESULT)0x00000000L)
+#endif
+
+#ifndef C_ASSERT
+#ifdef _MSC_VER
+# define C_ASSERT(e) typedef char __C_ASSERT__[(e)?1:-1]
+#else
+# define C_ASSERT(e) extern void __C_ASSERT__(int [(e)?1:-1])
+#endif
+#endif /* C_ASSERT */
+
+#ifdef __cplusplus
+#define _STRSAFE_EXTERN_C extern "C"
+#else
+#define _STRSAFE_EXTERN_C extern
 #endif
 #endif
+
+#ifndef WINAPI
+#define WINAPI __stdcall
+#endif
+
+#define STRSAFEAPI static __inline HRESULT WINAPI
+#define STRSAFE_INLINE_API __CRT_INLINE HRESULT WINAPI
+
 #define STRSAFE_MAX_CCH 2147483647
 #define STRSAFE_MAX_CCH 2147483647
-#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L)
-#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL)
-#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L)
 
 
+#ifndef _NTSTRSAFE_H_INCLUDED_
+#define STRSAFE_IGNORE_NULLS 0x00000100
 #define STRSAFE_FILL_BEHIND_NULL 0x00000200
 #define STRSAFE_FILL_BEHIND_NULL 0x00000200
-#define STRSAFE_IGNORE_NULLS 0x00000200
 #define STRSAFE_FILL_ON_FAILURE 0x00000400
 #define STRSAFE_NULL_ON_FAILURE 0x00000800
 #define STRSAFE_NO_TRUNCATION 0x00001000
 #define STRSAFE_FILL_ON_FAILURE 0x00000400
 #define STRSAFE_NULL_ON_FAILURE 0x00000800
 #define STRSAFE_NO_TRUNCATION 0x00001000
+#define STRSAFE_IGNORE_NULL_UNICODE_STRINGS 0x00010000
+#define STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED 0x00020000
 
 
-#ifndef S_OK
-#define S_OK  ((HRESULT)0x00000000L)
-#endif
+#define STRSAFE_VALID_FLAGS (0x000000FF | STRSAFE_IGNORE_NULLS | STRSAFE_FILL_BEHIND_NULL | STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)
+#define STRSAFE_UNICODE_STRING_VALID_FLAGS (STRSAFE_VALID_FLAGS | STRSAFE_IGNORE_NULL_UNICODE_STRINGS | STRSAFE_UNICODE_STRING_DEST_NULL_TERMINATED)
 
 
-#define STRSAFE_MIN(a,b) (((a) < (b))?(a):(b))
+#define STRSAFE_FILL_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_BEHIND_NULL))
+#define STRSAFE_FAILURE_BYTE(x) ((STRSAFE_DWORD)(((x) & 0x000000FF) | STRSAFE_FILL_ON_FAILURE))
 
 
-#ifndef _HRESULT_DEFINED
-#define _HRESULT_DEFINED
-typedef long HRESULT;
+#define STRSAFE_GET_FILL_PATTERN(dwFlags) ((int)((dwFlags) & 0x000000FF))
 #endif
 
 #endif
 
-typedef char * STRSAFE_LPSTR;
-typedef const char * STRSAFE_LPCSTR;
-typedef wchar_t * STRSAFE_LPWSTR;
-typedef const wchar_t * STRSAFE_LPCWSTR;
-typedef unsigned long STRSAFE_DWORD;
-
-#define STRSAFE_PASS2
-
-/* Implement Cb functions for ansi and unicode */
-#ifndef STRSAFE_NO_CB_FUNCTIONS
-#define STRSAFE_CB
-#define STRSAFE_UNICODE 0
-# include <strsafe.h>
-#undef STRSAFE_UNICODE
-#define STRSAFE_UNICODE 1
-# include <strsafe.h>
-#undef STRSAFE_UNICODE
-#undef STRSAFE_CB
-#endif // !STRSAFE_NO_CB_FUNCTIONS
-
-/* Implement Cch functions for ansi and unicode */
-#ifndef STRSAFE_NO_CCH_FUNCTIONS
-#define STRSAFE_UNICODE 0
-# include <strsafe.h>
-#undef STRSAFE_UNICODE
-#define STRSAFE_UNICODE 1
-# include <strsafe.h>
-#undef STRSAFE_UNICODE
-#endif // !STRSAFE_NO_CCH_FUNCTIONS
-
-#undef STRSAFE_PASS2
-
-/* Now define the functions depending on UNICODE */
-#if defined(UNICODE)
-# define STRSAFE_UNICODE 1
-#else
-# define STRSAFE_UNICODE 0
-#endif
-#include <strsafe.h>
-#undef STRSAFE_UNICODE
-
-#endif // !__STRSAFE_H_
-
-/*****************************************************************************/
-
-#if defined(STRSAFE_UNICODE)
-#if (STRSAFE_UNICODE == 1)
-
-#define STRSAFE_LPTSTR STRSAFE_LPWSTR
-#define STRSAFE_LPCTSTR STRSAFE_LPCWSTR
-#define STRSAFE_TCHAR wchar_t
-
-#define StringCbCat StringCbCatW
-#define StringCbCatEx StringCbCatExW
-#define StringCbCatN StringCbCatNW
-#define StringCbCatNEx StringCbCatNExW
-#define StringCbCatWorker StringCxxCatWorkerW
-#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 StringCchCatWorker StringCchCatWorkerW
-#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
-#define _vsnprintfAW _vsnwprintf
-
-#else // (STRSAFE_UNICODE != 1)
-
-#define STRSAFE_LPTSTR STRSAFE_LPSTR
-#define STRSAFE_LPCTSTR STRSAFE_LPCSTR
-#define STRSAFE_TCHAR char
-
-#define StringCbCat StringCbCatA
-#define StringCbCatEx StringCbCatExA
-#define StringCbCatN StringCbCatNA
-#define StringCbCatNEx StringCbCatNExA
-#define StringCbCatWorker StringCxxCatWorkerA
-#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 StringCchCatWorker StringCchCatWorkerA
-#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
-#define _vsnprintfAW _vsnprintf
-
-#endif // (STRSAFE_UNICODE != 1)
-#endif // defined(STRSAFE_UNICODE)
-
-/*****************************************************************************/
-
-#if defined (STRSAFE_PASS2)
-
-#if defined(STRSAFE_CB)
-
-#define STRSAFE_CXXtoCB(x) (x)
-#define STRSAFE_CBtoCXX(x) (x)
-#define STRSAFE_CXXtoCCH(x) (x)/sizeof(STRSAFE_TCHAR)
-#define STRSAFE_CCHtoCXX(x) (x)*sizeof(STRSAFE_TCHAR)
-#define StringCxxCat StringCbCat
-#define StringCxxCatEx StringCbCatEx
-#define StringCxxCatN StringCbCatN
-#define StringCxxCatNEx StringCbCatNEx
-#define StringCxxCatWorker StringCbCatWorker
-#define StringCxxCopy StringCbCopy
-#define StringCxxCopyEx StringCbCopyEx
-#define StringCxxCopyN StringCbCopyN
-#define StringCxxCopyNEx StringCbCopyNEx
-#define StringCxxGets StringCbGets
-#define StringCxxGetsEx StringCbGetsEx
-#define StringCxxLength StringCbLength
-#define StringCxxPrintf StringCbPrintf
-#define StringCxxPrintfEx StringCbPrintfEx
-#define StringCxxVPrintf StringCbVPrintf
-#define StringCxxVPrintfEx StringCbVPrintfEx
-
-#else // !STRSAFE_CB
-
-#define STRSAFE_CXXtoCB(x) (x)*sizeof(STRSAFE_TCHAR)
-#define STRSAFE_CBtoCXX(x) (x)/sizeof(STRSAFE_TCHAR)
-#define STRSAFE_CXXtoCCH(x) (x)
-#define STRSAFE_CCHtoCXX(x) (x)
-#define StringCxxCat StringCchCat
-#define StringCxxCatEx StringCchCatEx
-#define StringCxxCatN StringCchCatN
-#define StringCxxCatNEx StringCchCatNEx
-#define StringCxxCatWorker StringCchCatWorker
-#define StringCxxCopy StringCchCopy
-#define StringCxxCopyEx StringCchCopyEx
-#define StringCxxCopyN StringCchCopyN
-#define StringCxxCopyNEx StringCchCopyNEx
-#define StringCxxGets StringCchGets
-#define StringCxxGetsEx StringCchGetsEx
-#define StringCxxLength StringCchLength
-#define StringCxxPrintf StringCchPrintf
-#define StringCxxPrintfEx StringCchPrintfEx
-#define StringCxxVPrintf StringCchVPrintf
-#define StringCxxVPrintfEx StringCchVPrintfEx
-
-#endif // !STRSAFE_CB
-
-#ifdef STRSAFE_LIB
-
-/* Normal function prototypes only */
-#define STRSAFEAPI HRESULT __stdcall
-
-STRSAFEAPI StringCxxCat(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc);
-STRSAFEAPI StringCxxCatEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags);
-STRSAFEAPI StringCxxCatN(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, size_t cbMaxAppend);
-STRSAFEAPI StringCxxCatNEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, size_t cbMaxAppend, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags);
-STRSAFEAPI StringCxxCopy(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc);
-STRSAFEAPI StringCxxCopyEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags);
-STRSAFEAPI StringCxxCopyN(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, size_t cbSrc);
-STRSAFEAPI StringCxxCopyNEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszSrc, size_t cbSrc, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags);
-STRSAFEAPI StringCxxGets(STRSAFE_LPTSTR pszDest, size_t cxDest);
-STRSAFEAPI StringCxxGetsEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags);
-STRSAFEAPI StringCxxLength(STRSAFE_LPCTSTR psz, size_t cxMax, size_t *pcb);
-STRSAFEAPI StringCxxPrintf(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszFormat, ...);
-STRSAFEAPI StringCxxPrintfEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCTSTR pszFormat, ...);
-STRSAFEAPI StringCxxVPrintf(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPCTSTR pszFormat, va_list args);
-STRSAFEAPI StringCxxVPrintfEx(STRSAFE_LPTSTR pszDest, size_t cxDest, STRSAFE_LPTSTR *ppszDestEnd, size_t *pcbRemaining, STRSAFE_DWORD dwFlags, LPCTSTR pszFormat, va_list args);
-
-#else // !STRSAFE_LIB
-
-/* Create inlined versions */
-#ifdef __GNUC__
-#define STRSAFEAPI HRESULT static __inline__
-#else
-#define STRSAFEAPI HRESULT __inline
+#define STRSAFE_E_INSUFFICIENT_BUFFER ((HRESULT)0x8007007AL)
+#define STRSAFE_E_INVALID_PARAMETER ((HRESULT)0x80070057L)
+#define STRSAFE_E_END_OF_FILE ((HRESULT)0x80070026L)
+
+typedef char *STRSAFE_LPSTR;
+typedef const char *STRSAFE_LPCSTR;
+typedef wchar_t *STRSAFE_LPWSTR;
+typedef const wchar_t *STRSAFE_LPCWSTR;
+
+typedef ULONG STRSAFE_DWORD;
+
+STRSAFEAPI StringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+STRSAFEAPI StringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy);
+STRSAFEAPI StringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy);
+STRSAFEAPI StringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+STRSAFEAPI StringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend);
+STRSAFEAPI StringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend);
+STRSAFEAPI StringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
+STRSAFEAPI StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+STRSAFEAPI StringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength);
+STRSAFEAPI StringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength);
+STRSAFE_INLINE_API StringGetsExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFE_INLINE_API StringGetsExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCchCopy __MINGW_NAME_AW(StringCchCopy)
+
+STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) {
+  return (cchDest > STRSAFE_MAX_CCH ? STRSAFE_E_INVALID_PARAMETER : StringCopyWorkerA(pszDest,cchDest,pszSrc));
+}
+
+STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyWorkerW(pszDest,cchDest,pszSrc);
+}
+#endif /* !__CRT__NO_INLINE */
+
+#define StringCbCopy __MINGW_NAME_AW(StringCbCopy)
+
+STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc);
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCopyA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc) {
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyWorkerA(pszDest,cbDest,pszSrc);
+}
+
+STRSAFEAPI StringCbCopyW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc) {
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyWorkerW(pszDest,cchDest,pszSrc);
+}
+#endif /* !__CRT__NO_INLINE */
+
+#define StringCchCopyEx __MINGW_NAME_AW(StringCchCopyEx)
+
+STRSAFEAPI StringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCopyExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyExWorkerA(pszDest,cchDest,cchDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  size_t cbDest;
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  cbDest = cchDest * sizeof(wchar_t);
+  return StringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+#endif /* !__CRT__NO_INLINE */
+
+#define StringCbCopyEx __MINGW_NAME_AW(StringCbCopyEx)
+
+STRSAFEAPI StringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCopyExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchRemaining = 0;
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  hr = StringCopyExWorkerA(pszDest,cbDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+  if(SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) {
+    if(pcbRemaining)
+      *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCbCopyExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  size_t cchRemaining = 0;
+
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  hr = StringCopyExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(pcbRemaining)
+      *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy);
+STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy);
+#define StringCchCopyN __MINGW_NAME_AW(StringCchCopyN)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCopyNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy) {
+  if(cchDest > STRSAFE_MAX_CCH || cchToCopy > STRSAFE_MAX_CCH)
+    return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNWorkerA(pszDest,cchDest,pszSrc,cchToCopy);
+}
+
+STRSAFEAPI StringCchCopyNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy) {
+  if(cchDest > STRSAFE_MAX_CCH || cchToCopy > STRSAFE_MAX_CCH)
+    return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy);
+STRSAFEAPI StringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy);
+
+#define StringCbCopyN __MINGW_NAME_AW(StringCbCopyN)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCopyNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy) {
+  if(cbDest > STRSAFE_MAX_CCH || cbToCopy > STRSAFE_MAX_CCH)
+    return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNWorkerA(pszDest,cbDest,pszSrc,cbToCopy);
+}
+
+STRSAFEAPI StringCbCopyNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy) {
+  size_t cchDest  = cbDest / sizeof(wchar_t);
+  size_t cchToCopy = cbToCopy / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH || cchToCopy > STRSAFE_MAX_CCH)
+    return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNWorkerW(pszDest,cchDest,pszSrc,cchToCopy);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCchCopyNEx __MINGW_NAME_AW(StringCchCopyNEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCopyNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNExWorkerA(pszDest,cchDest,cchDest,pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+STRSAFEAPI StringCchCopyNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCopyNExWorkerW(pszDest,cchDest,cchDest * sizeof(wchar_t),pszSrc,cchToCopy,ppszDestEnd,pcchRemaining,dwFlags);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCbCopyNEx __MINGW_NAME_AW(StringCbCopyNEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCopyNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchRemaining = 0;
+  if(cbDest > STRSAFE_MAX_CCH)
+    hr = STRSAFE_E_INVALID_PARAMETER;
+  else
+    hr = StringCopyNExWorkerA(pszDest,cbDest,cbDest,pszSrc,cbToCopy,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = cchRemaining;
+  return hr;
+}
+
+STRSAFEAPI StringCbCopyNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchToCopy;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(wchar_t);
+  cchToCopy = cbToCopy / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringCopyNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToCopy,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc);
+
+#define StringCchCat __MINGW_NAME_AW(StringCchCat)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCatA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatWorkerA(pszDest,cchDest,pszSrc);
+}
+
+STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatWorkerW(pszDest,cchDest,pszSrc);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc);
+STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc);
+
+#define StringCbCat __MINGW_NAME_AW(StringCbCat)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCatA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc) {
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatWorkerA(pszDest,cbDest,pszSrc);
+}
+
+STRSAFEAPI StringCbCatW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc) {
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatWorkerW(pszDest,cchDest,pszSrc);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCchCatEx __MINGW_NAME_AW(StringCchCatEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCatExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatExWorkerA(pszDest,cchDest,cchDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+STRSAFEAPI StringCchCatExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  size_t cbDest = cchDest*sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,pcchRemaining,dwFlags);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCbCatEx __MINGW_NAME_AW(StringCbCatEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCatExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchRemaining = 0;
+  if(cbDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringCatExWorkerA(pszDest,cbDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+  return hr;
+}
+
+STRSAFEAPI StringCbCatExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  size_t cchRemaining = 0;
+
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringCatExWorkerW(pszDest,cchDest,cbDest,pszSrc,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend);
+STRSAFEAPI StringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend);
+
+#define StringCchCatN __MINGW_NAME_AW(StringCchCatN)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCatNA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNWorkerA(pszDest,cchDest,pszSrc,cchToAppend);
+}
+
+STRSAFEAPI StringCchCatNW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend);
+STRSAFEAPI StringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend);
+
+#define StringCbCatN __MINGW_NAME_AW(StringCbCatN)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCatNA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend) {
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNWorkerA(pszDest,cbDest,pszSrc,cbToAppend);
+}
+
+STRSAFEAPI StringCbCatNW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend) {
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  size_t cchToAppend = cbToAppend / sizeof(wchar_t);
+
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNWorkerW(pszDest,cchDest,pszSrc,cchToAppend);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCchCatNEx __MINGW_NAME_AW(StringCchCatNEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchCatNExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNExWorkerA(pszDest,cchDest,cchDest,pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags);
+}
+
+STRSAFEAPI StringCchCatNExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringCatNExWorkerW(pszDest,cchDest,(cchDest*sizeof(wchar_t)),pszSrc,cchToAppend,ppszDestEnd,pcchRemaining,dwFlags);
+}
 #endif
 
 #endif
 
-#define STRSAFE_MAX_CXX STRSAFE_CCHtoCXX(STRSAFE_MAX_CCH)
+STRSAFEAPI StringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+STRSAFEAPI StringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCbCatNEx __MINGW_NAME_AW(StringCbCatNEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbCatNExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cbToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchRemaining = 0;
+  if(cbDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringCatNExWorkerA(pszDest,cbDest,cbDest,pszSrc,cbToAppend,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+  return hr;
+}
+
+STRSAFEAPI StringCbCatNExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cbToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  size_t cchToAppend = cbToAppend / sizeof(wchar_t);
+  size_t cchRemaining = 0;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringCatNExWorkerW(pszDest,cchDest,cbDest,pszSrc,cchToAppend,ppszDestEnd,&cchRemaining,dwFlags);
+  if((SUCCEEDED(hr) || hr == STRSAFE_E_INSUFFICIENT_BUFFER) && pcbRemaining)
+    *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+#define StringCchVPrintf __MINGW_NAME_AW(StringCchVPrintf)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchVPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList);
+}
+
+STRSAFEAPI StringCchVPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+#define StringCbVPrintf __MINGW_NAME_AW(StringCbVPrintf)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbVPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringVPrintfWorkerA(pszDest,cbDest,pszFormat,argList);
+}
+
+STRSAFEAPI StringCbVPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  return StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...);
+STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...);
+
+#define StringCchPrintf __MINGW_NAME_AW(StringCchPrintf)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,...) {
+  HRESULT hr;
+  va_list argList;
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfWorkerA(pszDest,cchDest,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
+
+STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,...) {
+  HRESULT hr;
+  va_list argList;
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...);
+STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...);
+
+#define StringCbPrintf __MINGW_NAME_AW(StringCbPrintf)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbPrintfA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPCSTR pszFormat,...) {
+  HRESULT hr;
+  va_list argList;
+  if(cbDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfWorkerA(pszDest,cbDest,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
+
+STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPCWSTR pszFormat,...) {
+  HRESULT hr;
+  va_list argList;
+  size_t cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfWorkerW(pszDest,cchDest,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...);
+STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...);
+
+#define StringCchPrintfEx __MINGW_NAME_AW(StringCchPrintfEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...) {
+  HRESULT hr;
+  va_list argList;
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfExWorkerA(pszDest,cchDest,cchDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
 
 
-STRSAFEAPI
-StringCxxCatWorker(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszSrc,
-    size_t cxMaxAppend,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags,
-    int UseN)
-{
-    HRESULT result;
-    STRSAFE_LPTSTR psz = pszDest;
-    size_t cch = STRSAFE_CXXtoCCH(cxDest);
+STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...) {
+  HRESULT hr;
+  size_t cbDest = cchDest * sizeof(wchar_t);
+  va_list argList;
+  if(cchDest > STRSAFE_MAX_CCH) return STRSAFE_E_INVALID_PARAMETER;
+  va_start(argList,pszFormat);
+  hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+  va_end(argList);
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...);
+STRSAFEAPI StringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...);
+
+#define StringCbPrintfEx __MINGW_NAME_AW(StringCbPrintfEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,...) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(char);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    va_list argList;
+    va_start(argList,pszFormat);
+    hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+    va_end(argList);
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(pcbRemaining) {
+      *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+    }
+  }
+  return hr;
+}
 
 
-    if (!pszDest || !pszSrc || cxDest > STRSAFE_MAX_CXX || cxDest == 0)
-    {
-        return STRSAFE_E_INVALID_PARAMETER;
+STRSAFEAPI StringCbPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,...) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    va_list argList;
+    va_start(argList,pszFormat);
+    hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+    va_end(argList);
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(pcbRemaining) {
+      *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
     }
     }
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+#define StringCchVPrintfEx __MINGW_NAME_AW(StringCchVPrintfEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchVPrintfExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(char);
+    hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+  }
+  return hr;
+}
 
 
-    for (--psz; *(++psz) != 0 && --cch > 0;);
-    if (cch == 0)
-    {
-        return STRSAFE_E_INSUFFICIENT_BUFFER;
+STRSAFEAPI StringCchVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(wchar_t);
+    hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags,pszFormat,argList);
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList);
+STRSAFEAPI StringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList);
+
+#define StringCbVPrintfEx __MINGW_NAME_AW(StringCbVPrintfEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbVPrintfExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(char);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringVPrintfExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(pcbRemaining) {
+      *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
     }
     }
+  }
+  return hr;
+}
 
 
-    if (UseN)
-    {
-        cch = STRSAFE_MIN(cxDest, STRSAFE_CXXtoCCH(cxMaxAppend));
-    }
-
-    for (--pszSrc, --psz; (*(++psz) = *(++pszSrc)) != 0 && --cch > 0;);
-    if (cch == 0)
-    {
-        result = STRSAFE_E_INSUFFICIENT_BUFFER;
+STRSAFEAPI StringCbVPrintfExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringVPrintfExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags,pszFormat,argList);
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(pcbRemaining) {
+      *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
     }
     }
-    else
-        result = S_OK;
-
-    if (ppszDestEnd)
-    {
-        *ppszDestEnd = psz;
-    }
-
-    if (pcbRemaining)
-    {
-        *pcbRemaining = STRSAFE_CCHtoCXX(cch);
-    }
-
-    if (dwFlags & STRSAFE_FILL_BEHIND_NULL)
-    {
-        for (--psz, ++cch; --cch; *(++psz) = dwFlags & 0xff);
-    }
-
-    if (!SUCCEEDED(result))
-    {
-        if (dwFlags & STRSAFE_FILL_ON_FAILURE)
-        {
-           cch = STRSAFE_CXXtoCCH(cxDest);
-           for (--pszDest, ++cch; --cch; *(++pszDest) = dwFlags & 0xff);
-        }
-
-        if (dwFlags & STRSAFE_NULL_ON_FAILURE)
-        {
-            *pszDest = 0;
-        }
-    }
-
-    return result;
-}
-
-STRSAFEAPI
-StringCxxCatEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszSrc,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags)
-{
-    return StringCxxCatWorker(pszDest, cxDest, pszSrc, 0, ppszDestEnd, pcbRemaining, dwFlags, 0);
-}
-
-STRSAFEAPI
-StringCxxCat(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszSrc)
-{
-    return StringCxxCatWorker(pszDest, cxDest, pszSrc, 0, NULL, NULL, 0, 0);
-}
-
-STRSAFEAPI
-StringCxxCatN(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszSrc,
-    size_t cbMaxAppend)
-{
-    return StringCxxCatWorker(pszDest, cxDest, pszSrc, cbMaxAppend, NULL, NULL, 0, 1);
-}
-
-STRSAFEAPI
-StringCxxCatNEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszSrc,
-    size_t cbMaxAppend,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags)
-{
-    return StringCxxCatWorker(pszDest, cxDest, pszSrc, cbMaxAppend, ppszDestEnd, pcbRemaining, dwFlags, 1);
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFE_INLINE_API StringCchGetsA(STRSAFE_LPSTR pszDest,size_t cchDest);
+STRSAFE_INLINE_API StringCchGetsW(STRSAFE_LPWSTR pszDest,size_t cchDest);
+
+#define StringCchGets __MINGW_NAME_AW(StringCchGets)
+
+#ifndef __CRT__NO_INLINE
+STRSAFE_INLINE_API StringCchGetsA(STRSAFE_LPSTR pszDest,size_t cchDest) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(char);
+    hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,NULL,NULL,0);
+  }
+  return hr;
 }
 
 }
 
-STRSAFEAPI
-StringCxxCopy(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest,
-    STRSAFE_LPCTSTR pszSrc)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxCopyEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest,
-    STRSAFE_LPCTSTR pszSrc,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxCopyN(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest,
-    STRSAFE_LPCTSTR pszSrc,
-    size_t cbSrc)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxCopyNEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest,
-    STRSAFE_LPCTSTR pszSrc,
-    size_t cbSrc,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxGets(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxGetsEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cbDest,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags)
-{
-    return 0; // FIXME
-}
-
-STRSAFEAPI
-StringCxxLength(
-    STRSAFE_LPCTSTR psz,
-    size_t cxMax,
-    size_t *pcx)
-{
-    size_t cch = STRSAFE_CXXtoCCH(cxMax);
-
-    /* Default return on error */
-    if (pcx)
-        *pcx = 0;
-
-    if (!psz || cxMax > STRSAFE_MAX_CXX || cxMax == 0)
-    {
-        return STRSAFE_E_INVALID_PARAMETER;
-    }
-
-    for (--psz; *(++psz) != 0 && --cch > 0;);
-
-    if (cch == 0)
-    {
-        return STRSAFE_E_INVALID_PARAMETER;
-    }
-
-    if (pcx)
-        *pcx = cxMax - STRSAFE_CCHtoCXX(cch);
-
-    return S_OK;
-}
-
-STRSAFEAPI
-StringCxxVPrintfEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcxRemaining,
-    STRSAFE_DWORD dwFlags,
-    STRSAFE_LPCTSTR pszFormat,
-    va_list args)
-{
-    size_t cchDest = STRSAFE_CXXtoCCH(cxDest);
-    size_t cchMax = cchDest - 1;
-    int iResult;
-    HRESULT hr;
-
-    if (dwFlags & STRSAFE_IGNORE_NULLS)
-    {
-        if (!pszDest) pszDest = (STRSAFE_LPTSTR)L"";
-        if (!pszFormat) pszFormat = (STRSAFE_LPTSTR)L"";
-    }
-
-    if (!pszDest || !pszFormat || cxDest > STRSAFE_MAX_CXX || cxDest == 0)
-    {
-        return STRSAFE_E_INVALID_PARAMETER;
-    }
+STRSAFE_INLINE_API StringCchGetsW(STRSAFE_LPWSTR pszDest,size_t cchDest) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(wchar_t);
+    hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,NULL,NULL,0);
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
 
 
-#if (STRSAFE_USE_SECURE_CRT == 1)
-    iResult = _vsnprintf_sAW(pszDest, cchDest, cchMax, pszFormat, args);
-#else
-    iResult = _vsnprintfAW(pszDest, cchMax, pszFormat, args);
+STRSAFE_INLINE_API StringCbGetsA(STRSAFE_LPSTR pszDest,size_t cbDest);
+STRSAFE_INLINE_API StringCbGetsW(STRSAFE_LPWSTR pszDest,size_t cbDest);
+
+#define StringCbGets __MINGW_NAME_AW(StringCbGets)
+
+#ifndef __CRT__NO_INLINE
+STRSAFE_INLINE_API StringCbGetsA(STRSAFE_LPSTR pszDest,size_t cbDest) {
+  HRESULT hr;
+  size_t cchDest;
+  cchDest = cbDest / sizeof(char);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,NULL,NULL,0);
+  return hr;
+}
+
+STRSAFE_INLINE_API StringCbGetsW(STRSAFE_LPWSTR pszDest,size_t cbDest) {
+  HRESULT hr;
+  size_t cchDest;
+  cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,NULL,NULL,0);
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFE_INLINE_API StringCchGetsExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+STRSAFE_INLINE_API StringCchGetsExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCchGetsEx __MINGW_NAME_AW(StringCchGetsEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFE_INLINE_API StringCchGetsExA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(char);
+    hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags);
+  }
+  return hr;
+}
+
+STRSAFE_INLINE_API StringCchGetsExW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cbDest;
+    cbDest = cchDest*sizeof(wchar_t);
+    hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,pcchRemaining,dwFlags);
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFE_INLINE_API StringCbGetsExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+STRSAFE_INLINE_API StringCbGetsExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags);
+
+#define StringCbGetsEx __MINGW_NAME_AW(StringCbGetsEx)
+
+#ifndef __CRT__NO_INLINE
+STRSAFE_INLINE_API StringCbGetsExA(STRSAFE_LPSTR pszDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(char);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringGetsExWorkerA(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags);
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) {
+    if(pcbRemaining) *pcbRemaining = (cchRemaining*sizeof(char)) + (cbDest % sizeof(char));
+  }
+  return hr;
+}
+
+STRSAFE_INLINE_API StringCbGetsExW(STRSAFE_LPWSTR pszDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcbRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr;
+  size_t cchDest;
+  size_t cchRemaining = 0;
+  cchDest = cbDest / sizeof(wchar_t);
+  if(cchDest > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringGetsExWorkerW(pszDest,cchDest,cbDest,ppszDestEnd,&cchRemaining,dwFlags);
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) {
+    if(pcbRemaining) *pcbRemaining = (cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t));
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength);
+STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength);
+
+#define StringCchLength __MINGW_NAME_AW(StringCchLength)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCchLengthA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength) {
+  HRESULT hr;
+  if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringLengthWorkerA(psz,cchMax,pcchLength);
+  if(FAILED(hr) && pcchLength) {
+    *pcchLength = 0;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCchLengthW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength) {
+  HRESULT hr;
+  if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringLengthWorkerW(psz,cchMax,pcchLength);
+  if(FAILED(hr) && pcchLength) {
+    *pcchLength = 0;
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+STRSAFEAPI StringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength);
+STRSAFEAPI StringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength);
+
+#define StringCbLength __MINGW_NAME_AW(StringCbLength)
+
+#ifndef __CRT__NO_INLINE
+STRSAFEAPI StringCbLengthA(STRSAFE_LPCSTR psz,size_t cbMax,size_t *pcbLength) {
+  HRESULT hr;
+  size_t cchMax;
+  size_t cchLength = 0;
+  cchMax = cbMax / sizeof(char);
+  if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringLengthWorkerA(psz,cchMax,&cchLength);
+  if(pcbLength) {
+    if(SUCCEEDED(hr)) {
+      *pcbLength = cchLength*sizeof(char);
+    } else {
+      *pcbLength = 0;
+    }
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCbLengthW(STRSAFE_LPCWSTR psz,size_t cbMax,size_t *pcbLength) {
+  HRESULT hr;
+  size_t cchMax;
+  size_t cchLength = 0;
+  cchMax = cbMax / sizeof(wchar_t);
+  if(!psz || (cchMax > STRSAFE_MAX_CCH)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else hr = StringLengthWorkerW(psz,cchMax,&cchLength);
+  if(pcbLength) {
+    if(SUCCEEDED(hr)) {
+      *pcbLength = cchLength*sizeof(wchar_t);
+    } else {
+      *pcbLength = 0;
+    }
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    while(cchDest && (*pszSrc!='\0')) {
+      *pszDest++ = *pszSrc++;
+      cchDest--;
+    }
+    if(cchDest==0) {
+      pszDest--;
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    }
+    *pszDest= '\0';
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    while(cchDest && (*pszSrc!=L'\0')) {
+      *pszDest++ = *pszSrc++;
+      cchDest--;
+    }
+    if(cchDest==0) {
+      pszDest--;
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    }
+    *pszDest= L'\0';
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszSrc) pszSrc = "";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if(*pszSrc!='\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining && (*pszSrc!='\0')) {
+         *pszDestEnd++ = *pszSrc++;
+         cchRemaining--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+         }
+       } else {
+         pszDestEnd--;
+         cchRemaining++;
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+       *pszDestEnd = '\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszSrc) pszSrc = L"";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if(*pszSrc!=L'\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining && (*pszSrc!=L'\0')) {
+         *pszDestEnd++ = *pszSrc++;
+         cchRemaining--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+         }
+       } else {
+         pszDestEnd--;
+         cchRemaining++;
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+       *pszDestEnd = L'\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchSrc) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    while(cchDest && cchSrc && (*pszSrc!='\0')) {
+      *pszDest++ = *pszSrc++;
+      cchDest--;
+      cchSrc--;
+    }
+    if(cchDest==0) {
+      pszDest--;
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    }
+    *pszDest= '\0';
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    while(cchDest && cchToCopy && (*pszSrc!=L'\0')) {
+      *pszDest++ = *pszSrc++;
+      cchDest--;
+      cchToCopy--;
+    }
+    if(cchDest==0) {
+      pszDest--;
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    }
+    *pszDest= L'\0';
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToCopy,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else if(cchToCopy > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszSrc) pszSrc = "";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if((cchToCopy!=0) && (*pszSrc!='\0')) {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining && cchToCopy && (*pszSrc!='\0')) {
+         *pszDestEnd++ = *pszSrc++;
+         cchRemaining--;
+         cchToCopy--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+         }
+       } else {
+         pszDestEnd--;
+         cchRemaining++;
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+       *pszDestEnd = '\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCopyNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToCopy,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else if(cchToCopy > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszSrc) pszSrc = L"";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if((cchToCopy!=0) && (*pszSrc!=L'\0')) {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining && cchToCopy && (*pszSrc!=L'\0')) {
+         *pszDestEnd++ = *pszSrc++;
+         cchRemaining--;
+         cchToCopy--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+         }
+       } else {
+         pszDestEnd--;
+         cchRemaining++;
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+       *pszDestEnd = L'\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCatWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc) {
+  HRESULT hr;
+  size_t cchDestLength;
+  hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+  if(SUCCEEDED(hr)) hr = StringCopyWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc);
+  return hr;
+}
+
+STRSAFEAPI StringCatWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc) {
+  HRESULT hr;
+  size_t cchDestLength;
+  hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+  if(SUCCEEDED(hr)) hr = StringCopyWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc);
+  return hr;
+}
+
+STRSAFEAPI StringCatExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cchDestLength;
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest==0) && (cbDest==0)) cchDestLength = 0;
+       else hr = STRSAFE_E_INVALID_PARAMETER;
+      } else {
+       hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+       if(SUCCEEDED(hr)) {
+         pszDestEnd = pszDest + cchDestLength;
+         cchRemaining = cchDest - cchDestLength;
+       }
+      }
+      if(!pszSrc) pszSrc = "";
+    } else {
+      hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+      if(SUCCEEDED(hr)) {
+       pszDestEnd = pszDest + cchDestLength;
+       cchRemaining = cchDest - cchDestLength;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       if(*pszSrc!='\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else hr = StringCopyExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & STRSAFE_NULL_ON_FAILURE) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCatExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    size_t cchDestLength;
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest==0) && (cbDest==0)) cchDestLength = 0;
+       else hr = STRSAFE_E_INVALID_PARAMETER;
+      } else {
+       hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+       if(SUCCEEDED(hr)) {
+         pszDestEnd = pszDest + cchDestLength;
+         cchRemaining = cchDest - cchDestLength;
+       }
+      }
+      if(!pszSrc) pszSrc = L"";
+    } else {
+      hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+      if(SUCCEEDED(hr)) {
+       pszDestEnd = pszDest + cchDestLength;
+       cchRemaining = cchDest - cchDestLength;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       if(*pszSrc!=L'\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else hr = StringCopyExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & STRSAFE_NULL_ON_FAILURE) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCatNWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend) {
+  HRESULT hr;
+  size_t cchDestLength;
+  hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+  if(SUCCEEDED(hr)) hr = StringCopyNWorkerA(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend);
+  return hr;
+}
+
+STRSAFEAPI StringCatNWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend) {
+  HRESULT hr;
+  size_t cchDestLength;
+  hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+  if(SUCCEEDED(hr)) hr = StringCopyNWorkerW(pszDest + cchDestLength,cchDest - cchDestLength,pszSrc,cchToAppend);
+  return hr;
+}
+
+STRSAFEAPI StringCatNExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCSTR pszSrc,size_t cchToAppend,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  size_t cchDestLength = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else if(cchToAppend > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest==0) && (cbDest==0)) cchDestLength = 0;
+       else hr = STRSAFE_E_INVALID_PARAMETER;
+      } else {
+       hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+       if(SUCCEEDED(hr)) {
+         pszDestEnd = pszDest + cchDestLength;
+         cchRemaining = cchDest - cchDestLength;
+       }
+      }
+      if(!pszSrc) pszSrc = "";
+    } else {
+      hr = StringLengthWorkerA(pszDest,cchDest,&cchDestLength);
+      if(SUCCEEDED(hr)) {
+       pszDestEnd = pszDest + cchDestLength;
+       cchRemaining = cchDest - cchDestLength;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       if((cchToAppend!=0) && (*pszSrc!='\0')) {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else hr = StringCopyNExWorkerA(pszDestEnd,cchRemaining,(cchRemaining*sizeof(char)) + (cbDest % sizeof(char)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringCatNExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPCWSTR pszSrc,size_t cchToAppend,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  size_t cchDestLength = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else if(cchToAppend > STRSAFE_MAX_CCH) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest==0) && (cbDest==0)) cchDestLength = 0;
+       else hr = STRSAFE_E_INVALID_PARAMETER;
+      } else {
+       hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+       if(SUCCEEDED(hr)) {
+         pszDestEnd = pszDest + cchDestLength;
+         cchRemaining = cchDest - cchDestLength;
+       }
+      }
+      if(!pszSrc) pszSrc = L"";
+    } else {
+      hr = StringLengthWorkerW(pszDest,cchDest,&cchDestLength);
+      if(SUCCEEDED(hr)) {
+       pszDestEnd = pszDest + cchDestLength;
+       cchRemaining = cchDest - cchDestLength;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       if((cchToAppend!=0) && (*pszSrc!=L'\0')) {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else hr = StringCopyNExWorkerW(pszDestEnd,cchRemaining,(cchRemaining*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)),pszSrc,cchToAppend,&pszDestEnd,&cchRemaining,dwFlags & (~(STRSAFE_FILL_ON_FAILURE | STRSAFE_NULL_ON_FAILURE)));
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringVPrintfWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    int iRet;
+    size_t cchMax;
+    cchMax = cchDest - 1;
+    iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList);
+    if((iRet < 0) || (((size_t)iRet) > cchMax)) {
+      pszDest += cchMax;
+      *pszDest = '\0';
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    } else if(((size_t)iRet)==cchMax) {
+      pszDest += cchMax;
+      *pszDest = '\0';
+    }
+  }
+  return hr;
+}
+
+STRSAFEAPI StringVPrintfWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  HRESULT hr = S_OK;
+  if(cchDest==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    int iRet;
+    size_t cchMax;
+    cchMax = cchDest - 1;
+    iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList);
+    if((iRet < 0) || (((size_t)iRet) > cchMax)) {
+      pszDest += cchMax;
+      *pszDest = L'\0';
+      hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+    } else if(((size_t)iRet)==cchMax) {
+      pszDest += cchMax;
+      *pszDest = L'\0';
+    }
+  }
+  return hr;
+}
+
+STRSAFEAPI StringVPrintfExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCSTR pszFormat,va_list argList) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszFormat) pszFormat = "";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if(*pszFormat!='\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       int iRet;
+       size_t cchMax;
+       cchMax = cchDest - 1;
+       iRet = _vsnprintf(pszDest,cchMax,pszFormat,argList);
+       if((iRet < 0) || (((size_t)iRet) > cchMax)) {
+         pszDestEnd = pszDest + cchMax;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       } else if(((size_t)iRet)==cchMax) {
+         pszDestEnd = pszDest + cchMax;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       } else if(((size_t)iRet) < cchMax) {
+         pszDestEnd = pszDest + iRet;
+         cchRemaining = cchDest - iRet;
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+         }
+       }
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringVPrintfExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags,STRSAFE_LPCWSTR pszFormat,va_list argList) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+      if(!pszFormat) pszFormat = L"";
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest==0) {
+       pszDestEnd = pszDest;
+       cchRemaining = 0;
+       if(*pszFormat!=L'\0') {
+         if(!pszDest) hr = STRSAFE_E_INVALID_PARAMETER;
+         else hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       }
+      } else {
+       int iRet;
+       size_t cchMax;
+       cchMax = cchDest - 1;
+       iRet = _vsnwprintf(pszDest,cchMax,pszFormat,argList);
+       if((iRet < 0) || (((size_t)iRet) > cchMax)) {
+         pszDestEnd = pszDest + cchMax;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+         hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+       } else if(((size_t)iRet)==cchMax) {
+         pszDestEnd = pszDest + cchMax;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       } else if(((size_t)iRet) < cchMax) {
+         pszDestEnd = pszDest + iRet;
+         cchRemaining = cchDest - iRet;
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+         }
+       }
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringLengthWorkerA(STRSAFE_LPCSTR psz,size_t cchMax,size_t *pcchLength) {
+  HRESULT hr = S_OK;
+  size_t cchMaxPrev = cchMax;
+  while(cchMax && (*psz!='\0')) {
+    psz++;
+    cchMax--;
+  }
+  if(cchMax==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  if(pcchLength) {
+    if(SUCCEEDED(hr)) *pcchLength = cchMaxPrev - cchMax;
+    else *pcchLength = 0;
+  }
+  return hr;
+}
+
+STRSAFEAPI StringLengthWorkerW(STRSAFE_LPCWSTR psz,size_t cchMax,size_t *pcchLength) {
+  HRESULT hr = S_OK;
+  size_t cchMaxPrev = cchMax;
+  while(cchMax && (*psz!=L'\0')) {
+    psz++;
+    cchMax--;
+  }
+  if(cchMax==0) hr = STRSAFE_E_INVALID_PARAMETER;
+  if(pcchLength) {
+    if(SUCCEEDED(hr)) *pcchLength = cchMaxPrev - cchMax;
+    else *pcchLength = 0;
+  }
+  return hr;
+}
+
+STRSAFE_INLINE_API StringGetsExWorkerA(STRSAFE_LPSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) hr = STRSAFE_E_INVALID_PARAMETER;
+  else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest <= 1) {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       if(cchDest==1) *pszDestEnd = '\0';
+       hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining > 1) {
+         char ch;
+         int i = getc(stdin);
+         if(i==EOF) {
+           if(pszDestEnd==pszDest) hr = STRSAFE_E_END_OF_FILE;
+           break;
+         }
+         ch = (char)i;
+         if(ch=='\n') break;
+         *pszDestEnd = ch;
+         pszDestEnd++;
+         cchRemaining--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(char)) + (cbDest % sizeof(char)));
+         }
+       }
+       *pszDestEnd = '\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = '\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = '\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+
+STRSAFE_INLINE_API StringGetsExWorkerW(STRSAFE_LPWSTR pszDest,size_t cchDest,size_t cbDest,STRSAFE_LPWSTR *ppszDestEnd,size_t *pcchRemaining,STRSAFE_DWORD dwFlags) {
+  HRESULT hr = S_OK;
+  STRSAFE_LPWSTR pszDestEnd = pszDest;
+  size_t cchRemaining = 0;
+  if(dwFlags & (~STRSAFE_VALID_FLAGS)) {
+    hr = STRSAFE_E_INVALID_PARAMETER;
+  } else {
+    if(dwFlags & STRSAFE_IGNORE_NULLS) {
+      if(!pszDest) {
+       if((cchDest!=0) || (cbDest!=0)) hr = STRSAFE_E_INVALID_PARAMETER;
+      }
+    }
+    if(SUCCEEDED(hr)) {
+      if(cchDest <= 1) {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       if(cchDest==1) *pszDestEnd = L'\0';
+       hr = STRSAFE_E_INSUFFICIENT_BUFFER;
+      } else {
+       pszDestEnd = pszDest;
+       cchRemaining = cchDest;
+       while(cchRemaining > 1) {
+         wchar_t ch = getwc(stdin);
+         if(ch==WEOF) {
+           if(pszDestEnd==pszDest) hr = STRSAFE_E_END_OF_FILE;
+           break;
+         }
+         if(ch==L'\n') break;
+         *pszDestEnd = ch;
+         pszDestEnd++;
+         cchRemaining--;
+       }
+       if(cchRemaining > 0) {
+         if(dwFlags & STRSAFE_FILL_BEHIND_NULL) {
+           memset(pszDestEnd + 1,STRSAFE_GET_FILL_PATTERN(dwFlags),((cchRemaining - 1)*sizeof(wchar_t)) + (cbDest % sizeof(wchar_t)));
+         }
+       }
+       *pszDestEnd = L'\0';
+      }
+    }
+  }
+  if(FAILED(hr)) {
+    if(pszDest) {
+      if(dwFlags & STRSAFE_FILL_ON_FAILURE) {
+       memset(pszDest,STRSAFE_GET_FILL_PATTERN(dwFlags),cbDest);
+       if(STRSAFE_GET_FILL_PATTERN(dwFlags)==0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+       } else if(cchDest > 0) {
+         pszDestEnd = pszDest + cchDest - 1;
+         cchRemaining = 1;
+         *pszDestEnd = L'\0';
+       }
+      }
+      if(dwFlags & (STRSAFE_NULL_ON_FAILURE | STRSAFE_NO_TRUNCATION)) {
+       if(cchDest > 0) {
+         pszDestEnd = pszDest;
+         cchRemaining = cchDest;
+         *pszDestEnd = L'\0';
+       }
+      }
+    }
+  }
+  if(SUCCEEDED(hr) || (hr==STRSAFE_E_INSUFFICIENT_BUFFER) || (hr==STRSAFE_E_END_OF_FILE)) {
+    if(ppszDestEnd) *ppszDestEnd = pszDestEnd;
+    if(pcchRemaining) *pcchRemaining = cchRemaining;
+  }
+  return hr;
+}
+#endif /* !__CRT__NO_INLINE */
+
+#define StringCopyWorkerA StringCopyWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define StringCopyWorkerW StringCopyWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define StringCopyExWorkerA StringCopyExWorkerA_instead_use_StringCchCopyA_or_StringCchCopyExA;
+#define StringCopyExWorkerW StringCopyExWorkerW_instead_use_StringCchCopyW_or_StringCchCopyExW;
+#define StringCatWorkerA StringCatWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define StringCatWorkerW StringCatWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define StringCatExWorkerA StringCatExWorkerA_instead_use_StringCchCatA_or_StringCchCatExA;
+#define StringCatExWorkerW StringCatExWorkerW_instead_use_StringCchCatW_or_StringCchCatExW;
+#define StringCatNWorkerA StringCatNWorkerA_instead_use_StringCchCatNA_or_StrincCbCatNA;
+#define StringCatNWorkerW StringCatNWorkerW_instead_use_StringCchCatNW_or_StringCbCatNW;
+#define StringCatNExWorkerA StringCatNExWorkerA_instead_use_StringCchCatNExA_or_StringCbCatNExA;
+#define StringCatNExWorkerW StringCatNExWorkerW_instead_use_StringCchCatNExW_or_StringCbCatNExW;
+#define StringVPrintfWorkerA StringVPrintfWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define StringVPrintfWorkerW StringVPrintfWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define StringVPrintfExWorkerA StringVPrintfExWorkerA_instead_use_StringCchVPrintfA_or_StringCchVPrintfExA;
+#define StringVPrintfExWorkerW StringVPrintfExWorkerW_instead_use_StringCchVPrintfW_or_StringCchVPrintfExW;
+#define StringLengthWorkerA StringLengthWorkerA_instead_use_StringCchLengthA_or_StringCbLengthA;
+#define StringLengthWorkerW StringLengthWorkerW_instead_use_StringCchLengthW_or_StringCbLengthW;
+#define StringGetsExWorkerA StringGetsExWorkerA_instead_use_StringCchGetsA_or_StringCbGetsA
+#define StringGetsExWorkerW StringGetsExWorkerW_instead_use_StringCchGetsW_or_StringCbGetsW
+
+/* Some Wine modules include us, don't specify STRSAFE_NO_DEPRECATE, and use deprecated functions */
+#ifndef STRSAFE_NO_DEPRECATE
+#define STRSAFE_NO_DEPRECATE
 #endif
 
 #endif
 
-    hr = (iResult == -1) ? STRSAFE_E_INSUFFICIENT_BUFFER : S_OK;
-
-    if ((size_t)iResult >= cchMax)
-    {
-        pszDest[cchMax] = 0;
-        iResult = cchMax;
-    }
-
-    if (ppszDestEnd) *ppszDestEnd = pszDest + iResult;
-
-    if (pcxRemaining) *pcxRemaining = STRSAFE_CCHtoCXX(cchMax - iResult);
-
-    if (SUCCEEDED(hr))
-    {
-        if ((dwFlags & STRSAFE_FILL_BEHIND_NULL) && ((size_t)iResult + 1 < cchMax))
-        {
-            memset(pszDest + iResult + 1,
-                   dwFlags & 0xff,
-                   (cchMax - iResult - 1) * sizeof(STRSAFE_TCHAR));
-        }
-    }
-    else
-    {
-        if (dwFlags & STRSAFE_FILL_ON_FAILURE)
-        {
-            memset(pszDest, dwFlags & 0xff, cchMax * sizeof(STRSAFE_TCHAR));
-        }
-        else if (dwFlags & STRSAFE_NULL_ON_FAILURE)
-        {
-            *pszDest = 0;
-        }
-    }
-
-    return hr;
-}
-
-STRSAFEAPI
-StringCxxVPrintf(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszFormat,
-    va_list args)
-{
-    return StringCxxVPrintfEx(pszDest, cxDest, NULL, NULL, 0, pszFormat, args);
-}
-
-STRSAFEAPI
-StringCxxPrintf(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPCTSTR pszFormat, ...)
-{
-    HRESULT result;
-    va_list args;
-    va_start(args, pszFormat);
-    result = StringCxxVPrintf(pszDest, cxDest, pszFormat, args);
-    va_end(args);
-    return result;
-}
-
-STRSAFEAPI
-StringCxxPrintfEx(
-    STRSAFE_LPTSTR pszDest,
-    size_t cxDest,
-    STRSAFE_LPTSTR *ppszDestEnd,
-    size_t *pcbRemaining,
-    STRSAFE_DWORD dwFlags,
-    STRSAFE_LPCTSTR pszFormat, ...)
-{
-    HRESULT result;
-    va_list args;
-    va_start(args, pszFormat);
-    result = StringCxxVPrintfEx(pszDest, cxDest, ppszDestEnd, pcbRemaining, dwFlags, pszFormat, args);
-    va_end(args);
-    return result;
-}
-
-#endif // !STRSAFE_LIB
-
-/* Functions are implemented or defined, clear #defines for next pass */
-#undef StringCxxCat
-#undef StringCxxCatEx
-#undef StringCxxCatN
-#undef StringCxxCatNEx
-#undef StringCxxCatWorker
-#undef StringCxxCopy
-#undef StringCxxCopyEx
-#undef StringCxxCopyN
-#undef StringCxxCopyNEx
-#undef StringCxxGets
-#undef StringCxxGetsEx
-#undef StringCxxLength
-#undef StringCxxPrintf
-#undef StringCxxPrintfEx
-#undef StringCxxVPrintf
-#undef StringCxxVPrintfEx
-
-#undef StringCbCat
-#undef StringCbCatEx
-#undef StringCbCatN
-#undef StringCbCatNEx
-#undef StringCbCatWorker
-#undef StringCbCopy
-#undef StringCbCopyEx
-#undef StringCbCopyN
-#undef StringCbCopyNEx
-#undef StringCbGets
-#undef StringCbGetsEx
-#undef StringCbLength
-#undef StringCbPrintf
-#undef StringCbPrintfEx
-#undef StringCbVPrintf
-#undef StringCbVPrintfEx
-#undef StringCchCat
-#undef StringCchCatEx
-#undef StringCchCatN
-#undef StringCchCatNEx
-#undef StringCchCatWorker
-#undef StringCchCopy
-#undef StringCchCopyEx
-#undef StringCchCopyN
-#undef StringCchCopyNEx
-#undef StringCchGets
-#undef StringCchGetsEx
-#undef StringCchLength
-#undef StringCchPrintf
-#undef StringCchPrintfEx
-#undef StringCchVPrintf
-#undef StringCchVPrintfEx
-#undef _vsnprintfAW
-
-#undef STRSAFE_LPTSTR
-#undef STRSAFE_LPCTSTR
-#undef STRSAFE_TCHAR
-
-#undef STRSAFE_CXXtoCB
-#undef STRSAFE_CBtoCXX
-#undef STRSAFE_CXXtoCCH
-#undef STRSAFE_CCHtoCXX
-
-#endif // defined (STRSAFE_PASS2)
+#ifndef STRSAFE_NO_DEPRECATE
+
+#undef strcpy
+#define strcpy strcpy_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef wcscpy
+#define wcscpy wcscpy_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef strcat
+#define strcat strcat_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef wcscat
+#define wcscat wcscat_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef sprintf
+#define sprintf sprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef swprintf
+#define swprintf swprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW;
+
+#undef vsprintf
+#define vsprintf vsprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef vswprintf
+#define vswprintf vswprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef _snprintf
+#define _snprintf _snprintf_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef _snwprintf
+#define _snwprintf _snwprintf_instead_use_StringCbPrintfW_or_StringCchPrintfW;
 
 
+#undef _vsnprintf
+#define _vsnprintf _vsnprintf_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef _vsnwprintf
+#define _vsnwprintf _vsnwprintf_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef strcpyA
+#define strcpyA strcpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef strcpyW
+#define strcpyW strcpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef lstrcpy
+#define lstrcpy lstrcpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef lstrcpyA
+#define lstrcpyA lstrcpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef lstrcpyW
+#define lstrcpyW lstrcpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef StrCpy
+#define StrCpy StrCpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef StrCpyA
+#define StrCpyA StrCpyA_instead_use_StringCbCopyA_or_StringCchCopyA;
+
+#undef StrCpyW
+#define StrCpyW StrCpyW_instead_use_StringCbCopyW_or_StringCchCopyW;
+
+#undef _tcscpy
+#define _tcscpy _tcscpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef _ftcscpy
+#define _ftcscpy _ftcscpy_instead_use_StringCbCopy_or_StringCchCopy;
+
+#undef lstrcat
+#define lstrcat lstrcat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef lstrcatA
+#define lstrcatA lstrcatA_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef lstrcatW
+#define lstrcatW lstrcatW_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef StrCat
+#define StrCat StrCat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef StrCatA
+#define StrCatA StrCatA_instead_use_StringCbCatA_or_StringCchCatA;
+
+#undef StrCatW
+#define StrCatW StrCatW_instead_use_StringCbCatW_or_StringCchCatW;
+
+#undef StrNCat
+#define StrNCat StrNCat_instead_use_StringCbCatN_or_StringCchCatN;
+
+#undef StrNCatA
+#define StrNCatA StrNCatA_instead_use_StringCbCatNA_or_StringCchCatNA;
+
+#undef StrNCatW
+#define StrNCatW StrNCatW_instead_use_StringCbCatNW_or_StringCchCatNW;
+
+#undef StrCatN
+#define StrCatN StrCatN_instead_use_StringCbCatN_or_StringCchCatN;
+
+#undef StrCatNA
+#define StrCatNA StrCatNA_instead_use_StringCbCatNA_or_StringCchCatNA;
+
+#undef StrCatNW
+#define StrCatNW StrCatNW_instead_use_StringCbCatNW_or_StringCchCatNW;
+
+#undef _tcscat
+#define _tcscat _tcscat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef _ftcscat
+#define _ftcscat _ftcscat_instead_use_StringCbCat_or_StringCchCat;
+
+#undef wsprintf
+#define wsprintf wsprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef wsprintfA
+#define wsprintfA wsprintfA_instead_use_StringCbPrintfA_or_StringCchPrintfA;
+
+#undef wsprintfW
+#define wsprintfW wsprintfW_instead_use_StringCbPrintfW_or_StringCchPrintfW;
+
+#undef wvsprintf
+#define wvsprintf wvsprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef wvsprintfA
+#define wvsprintfA wvsprintfA_instead_use_StringCbVPrintfA_or_StringCchVPrintfA;
+
+#undef wvsprintfW
+#define wvsprintfW wvsprintfW_instead_use_StringCbVPrintfW_or_StringCchVPrintfW;
+
+#undef _vstprintf
+#define _vstprintf _vstprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef _vsntprintf
+#define _vsntprintf _vsntprintf_instead_use_StringCbVPrintf_or_StringCchVPrintf;
+
+#undef _stprintf
+#define _stprintf _stprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef _sntprintf
+#define _sntprintf _sntprintf_instead_use_StringCbPrintf_or_StringCchPrintf;
+
+#undef _getts
+#define _getts _getts_instead_use_StringCbGets_or_StringCchGets;
+
+#undef gets
+#define gets _gets_instead_use_StringCbGetsA_or_StringCchGetsA;
+
+#undef _getws
+#define _getws _getws_instead_use_StringCbGetsW_or_StringCchGetsW;
+#endif
+#endif
index 3e2066d..f614cf6 100644 (file)
@@ -12,7 +12,6 @@
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <debug.h>
-#include "ntstrsafe.h"
 
 /* Temporary hack */
 BOOLEAN
 
 /* Temporary hack */
 BOOLEAN
@@ -44,7 +43,7 @@ ULONG NtBuildNumber = VER_PRODUCTBUILD;
 #endif
 
 /* NT System Info */
 #endif
 
 /* NT System Info */
-ULONG NtGlobalFlag;
+ULONG NtGlobalFlag = 0;
 ULONG ExSuiteMask;
 
 /* Cm Version Info */
 ULONG ExSuiteMask;
 
 /* Cm Version Info */
@@ -894,7 +893,7 @@ ExpInitializeExecutive(IN ULONG Cpu,
     PLDR_DATA_TABLE_ENTRY NtosEntry;
     PMESSAGE_RESOURCE_ENTRY MsgEntry;
     ANSI_STRING CsdString;
     PLDR_DATA_TABLE_ENTRY NtosEntry;
     PMESSAGE_RESOURCE_ENTRY MsgEntry;
     ANSI_STRING CsdString;
-    SIZE_T Remaining = 0;
+    size_t Remaining = 0;
     PCHAR RcEnd = NULL;
     CHAR VersionBuffer [65];
 
     PCHAR RcEnd = NULL;
     CHAR VersionBuffer [65];
 
@@ -1311,6 +1310,7 @@ Phase1InitializationDiscard(IN PVOID Context)
     ANSI_STRING TempString;
     ULONG LastTzBias, Length, YearHack = 0, Disposition, MessageCode = 0;
     SIZE_T Size;
     ANSI_STRING TempString;
     ULONG LastTzBias, Length, YearHack = 0, Disposition, MessageCode = 0;
     SIZE_T Size;
+    size_t Remaining;
     PRTL_USER_PROCESS_INFORMATION ProcessInfo;
     KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo;
     UNICODE_STRING KeyName, DebugString;
     PRTL_USER_PROCESS_INFORMATION ProcessInfo;
     KEY_VALUE_PARTIAL_INFORMATION KeyPartialInfo;
     UNICODE_STRING KeyName, DebugString;
@@ -1390,14 +1390,14 @@ Phase1InitializationDiscard(IN PVOID Context)
     StringBuffer = InitBuffer->VersionBuffer;
     BeginBuffer = StringBuffer;
     EndBuffer = StringBuffer;
     StringBuffer = InitBuffer->VersionBuffer;
     BeginBuffer = StringBuffer;
     EndBuffer = StringBuffer;
-    Size = 256;
+    Remaining = sizeof(InitBuffer->VersionBuffer);
     if (CmCSDVersionString.Length)
     {
         /* Print the version string */
         Status = RtlStringCbPrintfExA(StringBuffer,
     if (CmCSDVersionString.Length)
     {
         /* Print the version string */
         Status = RtlStringCbPrintfExA(StringBuffer,
-                                      255,
+                                      Remaining,
                                       &EndBuffer,
                                       &EndBuffer,
-                                      &Size,
+                                      &Remaining,
                                       0,
                                       ": %wZ",
                                       &CmCSDVersionString);
                                       0,
                                       ": %wZ",
                                       &CmCSDVersionString);
@@ -1410,16 +1410,14 @@ Phase1InitializationDiscard(IN PVOID Context)
     else
     {
         /* No version */
     else
     {
         /* No version */
-        Size = 255;
+        *EndBuffer++ = ANSI_NULL; /* Null-terminate the string */
+        --Remaining;
     }
 
     }
 
-    /* Null-terminate the string */
-    *EndBuffer++ = ANSI_NULL;
-
     /* Build the version number */
     StringBuffer = InitBuffer->VersionNumber;
     Status = RtlStringCbPrintfA(StringBuffer,
     /* Build the version number */
     StringBuffer = InitBuffer->VersionNumber;
     Status = RtlStringCbPrintfA(StringBuffer,
-                                24,
+                                sizeof(InitBuffer->VersionNumber),
                                 "%u.%u",
                                 VER_PRODUCTMAJORVERSION,
                                 VER_PRODUCTMINORVERSION);
                                 "%u.%u",
                                 VER_PRODUCTMAJORVERSION,
                                 VER_PRODUCTMINORVERSION);
@@ -1434,7 +1432,7 @@ Phase1InitializationDiscard(IN PVOID Context)
     {
         /* Create the banner message */
         Status = RtlStringCbPrintfA(EndBuffer,
     {
         /* Create the banner message */
         Status = RtlStringCbPrintfA(EndBuffer,
-                                    Size,
+                                    Remaining,
                                     (PCHAR)MsgEntry->Text,
                                     StringBuffer,
                                     NtBuildNumber & 0xFFFF,
                                     (PCHAR)MsgEntry->Text,
                                     StringBuffer,
                                     NtBuildNumber & 0xFFFF,
@@ -1448,7 +1446,7 @@ Phase1InitializationDiscard(IN PVOID Context)
     else
     {
         /* Use hard-coded banner message */
     else
     {
         /* Use hard-coded banner message */
-        Status = RtlStringCbCopyA(EndBuffer, Size, "REACTOS (R)\n");
+        Status = RtlStringCbCopyA(EndBuffer, Remaining, "REACTOS (R)\n");
         if (!NT_SUCCESS(Status))
         {
             /* Bugcheck */
         if (!NT_SUCCESS(Status))
         {
             /* Bugcheck */
@@ -1548,7 +1546,7 @@ Phase1InitializationDiscard(IN PVOID Context)
     /* Create the string */
     StringBuffer = InitBuffer->VersionBuffer;
     Status = RtlStringCbPrintfA(StringBuffer,
     /* Create the string */
     StringBuffer = InitBuffer->VersionBuffer;
     Status = RtlStringCbPrintfA(StringBuffer,
-                                256,
+                                sizeof(InitBuffer->VersionBuffer),
                                 NT_SUCCESS(MsgStatus) ?
                                 (PCHAR)MsgEntry->Text :
                                 "%u System Processor [%u MB Memory] %Z\n",
                                 NT_SUCCESS(MsgStatus) ?
                                 (PCHAR)MsgEntry->Text :
                                 "%u System Processor [%u MB Memory] %Z\n",