[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Use a locally defined StringPrintf



Use of the _snprintf_s symbol fails on Windows 10, where it appears not to
be exported from ntdll. So, for portability's sake it is more robust to
implement a StringPrintf function locally.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xennet/adapter.c         |  52 ++---
 src/xennet/link.c            | 250 -----------------------
 src/xennet/link.h            |  42 ----
 src/xennet/string.c          | 464 +++++++++++++++++++++++++++++++++++++++++++
 src/xennet/string.h          |  51 +++++
 vs2012/xennet/xennet.vcxproj |   2 +-
 vs2013/xennet/xennet.vcxproj |   2 +-
 7 files changed, 538 insertions(+), 325 deletions(-)
 delete mode 100644 src/xennet/link.c
 delete mode 100644 src/xennet/link.h
 create mode 100644 src/xennet/string.c
 create mode 100644 src/xennet/string.h

diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index dc69a7f..ea54871 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -45,7 +45,7 @@
 #include "util.h"
 #include "dbg_print.h"
 #include "assert.h"
-#include "link.h"
+#include "string.h"
 
 #define MAXNAMELEN  128
 
@@ -81,12 +81,6 @@ struct _XENNET_ADAPTER {
     PXENNET_RECEIVER            Receiver;
     PXENNET_TRANSMITTER         Transmitter;
     BOOLEAN                     Enabled;
-
-    NTSTATUS                    (*_snprintf_s)(char *,
-                                               size_t,
-                                               size_t,
-                                               const char *,
-                                               ...);
 };
 
 static LONG AdapterCount;
@@ -1308,6 +1302,7 @@ __AdapterSetDistribution(
     ULONG               Index;
     CHAR                Distribution[MAXNAMELEN];
     CHAR                Vendor[MAXNAMELEN];
+    STRING              String;
     const CHAR          *Product;
     NTSTATUS            status;
 
@@ -1317,11 +1312,14 @@ __AdapterSetDistribution(
     while (Index <= MAXIMUM_INDEX) {
         PCHAR   Buffer;
 
-        (VOID) Adapter->_snprintf_s(Distribution,
-                                    MAXNAMELEN,
-                                    _TRUNCATE,
-                                    "%u",
-                                    Index);
+        String.Buffer = Distribution;
+        String.MaximumLength = sizeof (Distribution);
+        String.Length = 0;
+
+        status = StringPrintf(&String,
+                              "%u",
+                              Index);
+        ASSERT(NT_SUCCESS(status));
 
         status = XENBUS_STORE(Read,
                               &Adapter->StoreInterface,
@@ -1347,11 +1345,14 @@ __AdapterSetDistribution(
     goto fail2;
 
 update:
-    (VOID) Adapter->_snprintf_s(Vendor,
-                                MAXNAMELEN,
-                                _TRUNCATE,
-                                "%s",
-                                VENDOR_NAME_STR);
+    String.Buffer = Vendor;
+    String.MaximumLength = sizeof (Vendor);
+    String.Length = 0;
+
+    status = StringPrintf(&String,
+                          "%s",
+                          VENDOR_NAME_STR);
+    ASSERT(NT_SUCCESS(status));
 
     for (Index  = 0; Vendor[Index] != '\0'; Index++)
         if (!isalnum((UCHAR)Vendor[Index]))
@@ -1490,22 +1491,16 @@ AdapterEnable(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = LinkGetRoutineAddress("ntdll.dll",
-                                   "_snprintf_s",
-                                   (PVOID *)&Adapter->_snprintf_s);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
     status = AdapterSetDistribution(Adapter);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail3;
 
     status = XENVIF_VIF(Enable,
                         &Adapter->VifInterface,
                         AdapterVifCallback,
                         Adapter);
     if (!NT_SUCCESS(status))
-        goto fail5;
+        goto fail4;
 
     AdapterMediaStateChange(Adapter);
 
@@ -1513,11 +1508,8 @@ AdapterEnable(
 
     return NDIS_STATUS_SUCCESS;
 
-fail5:
-    AdapterClearDistribution(Adapter);
-
 fail4:
-    Adapter->_snprintf_s = NULL;
+    AdapterClearDistribution(Adapter);
 
 fail3:
     XENBUS_SUSPEND(Release, &Adapter->SuspendInterface);
@@ -1544,8 +1536,6 @@ AdapterDisable(
 
     AdapterClearDistribution(Adapter);
 
-    Adapter->_snprintf_s = NULL;
-
     XENBUS_SUSPEND(Release, &Adapter->SuspendInterface);
     XENBUS_STORE(Release, &Adapter->StoreInterface);
 }
diff --git a/src/xennet/link.c b/src/xennet/link.c
deleted file mode 100644
index e2a41bc..0000000
--- a/src/xennet/link.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * *   Redistributions of source code must retain the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer in the documentation and/or other
- *     materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ntddk.h>
-#include <aux_klib.h>
-
-#include "link.h"
-#include "dbg_print.h"
-#include "assert.h"
-#include "util.h"
-
-#define LINK_TAG    'KNIL'
-
-static FORCEINLINE PVOID
-__LinkAllocate(
-    IN  ULONG   Length
-    )
-{
-    return __AllocatePoolWithTag(NonPagedPool, Length, LINK_TAG);
-}
-
-static FORCEINLINE VOID
-__LinkFree(
-    IN  PVOID   Buffer
-    )
-{
-    __FreePoolWithTag(Buffer, LINK_TAG);
-}
-
-static FORCEINLINE NTSTATUS
-__LinkGetImageBase(
-    IN  const CHAR              *ModuleName,
-    OUT PVOID                   *ImageBase
-    )
-{
-    ULONG                       BufferSize;
-    ULONG                       Count;
-    PAUX_MODULE_EXTENDED_INFO   QueryInfo;
-    ULONG                       Index;
-    NTSTATUS                    status;
-
-    Trace("====>\n");
-
-    status = AuxKlibInitialize();
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = AuxKlibQueryModuleInformation(&BufferSize,
-                                           sizeof (AUX_MODULE_EXTENDED_INFO),
-                                           NULL);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = STATUS_UNSUCCESSFUL;
-    if (BufferSize == 0)
-        goto fail3;
-
-again:
-    Count = BufferSize / sizeof (AUX_MODULE_EXTENDED_INFO);
-    QueryInfo = __LinkAllocate(sizeof (AUX_MODULE_EXTENDED_INFO) * Count);
-
-    status = STATUS_NO_MEMORY;
-    if (QueryInfo == NULL)
-        goto fail4;
-
-    status = AuxKlibQueryModuleInformation(&BufferSize,
-                                           sizeof (AUX_MODULE_EXTENDED_INFO),
-                                           QueryInfo);
-    if (!NT_SUCCESS(status)) {
-        if (status != STATUS_BUFFER_TOO_SMALL)
-            goto fail5;
-
-        __LinkFree(QueryInfo);
-        goto again;
-    }
-
-    for (Index = 0; Index < Count; Index++) {
-        PCHAR   Name;
-
-        Name = strrchr((const CHAR *)QueryInfo[Index].FullPathName, '\\');
-        Name = (Name == NULL) ? (PCHAR)QueryInfo[Index].FullPathName : (Name + 
1);
-
-        if (_stricmp(Name, ModuleName) == 0)
-            goto found;
-    }
-
-    status = STATUS_UNSUCCESSFUL;
-    goto fail6;
-
-found:
-    *ImageBase = QueryInfo[Index].BasicInfo.ImageBase;
-
-    __LinkFree(QueryInfo);
-
-    Trace("<====\n");
-
-    return STATUS_SUCCESS;
-
-fail6:
-    Error("fail6\n");
-
-fail5:
-    Error("fail5\n");
-
-    __LinkFree(QueryInfo);
-
-fail4:
-    Error("fail4\n");
-
-fail3:
-    Error("fail3\n");
-
-fail2:
-    Error("fail2\n");
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
-NTSTATUS
-LinkGetRoutineAddress(
-    IN  const CHAR  *ModuleName,
-    IN  const CHAR  *FunctionName,
-    OUT PVOID       *Address
-    )
-{
-#define MK_PTR(_ImageBase, _Type, _RVA) \
-    (_Type)((ULONG_PTR)(_ImageBase) + (_RVA))
-
-    PVOID                       ImageBase;
-    PIMAGE_DOS_HEADER           DosHeader;
-    PIMAGE_NT_HEADERS           NtHeaders;
-    PIMAGE_OPTIONAL_HEADER      OptionalHeader;
-    PIMAGE_DATA_DIRECTORY       Entry;
-    PIMAGE_EXPORT_DIRECTORY     Exports;
-    PULONG                      AddressOfFunctions;
-    PULONG                      AddressOfNames;
-    PUSHORT                     AddressOfNameOrdinals;
-    ULONG                       Index;
-    USHORT                      Ordinal;
-    PVOID                       Function;
-    NTSTATUS                    status;
-
-    Trace("====>\n");
-
-    status = __LinkGetImageBase(ModuleName, &ImageBase);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    DosHeader = MK_PTR(ImageBase, PIMAGE_DOS_HEADER, 0);
-    ASSERT3U(DosHeader->e_magic, ==, IMAGE_DOS_SIGNATURE);
-
-    NtHeaders = MK_PTR(ImageBase, PIMAGE_NT_HEADERS, DosHeader->e_lfanew);
-    ASSERT3U(NtHeaders->Signature, ==, IMAGE_NT_SIGNATURE);
-
-    OptionalHeader = &NtHeaders->OptionalHeader;
-    ASSERT3U(OptionalHeader->Magic, ==, IMAGE_NT_OPTIONAL_HDR_MAGIC);
-
-    Entry = &OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
-
-    status = STATUS_UNSUCCESSFUL;
-    if (Entry->Size == 0)
-        goto fail2;
-
-    Exports = MK_PTR(ImageBase, PIMAGE_EXPORT_DIRECTORY,
-                     Entry->VirtualAddress);
-
-    status = STATUS_UNSUCCESSFUL;
-    if (Exports->NumberOfNames == 0)
-        goto fail3;
-
-    AddressOfFunctions = MK_PTR(ImageBase, PULONG,
-                                Exports->AddressOfFunctions);
-    AddressOfNames = MK_PTR(ImageBase, PULONG,
-                            Exports->AddressOfNames);
-    AddressOfNameOrdinals = MK_PTR(ImageBase, PUSHORT,
-                                   Exports->AddressOfNameOrdinals);
-
-    for (Index = 0; Index < Exports->NumberOfNames; Index++) {
-        PCHAR   Name = MK_PTR(ImageBase, PCHAR, AddressOfNames[Index]);
-
-        Ordinal = AddressOfNameOrdinals[Index];
-        Function = MK_PTR(ImageBase, PVOID, AddressOfFunctions[Ordinal]);
-
-        if (strcmp(Name, FunctionName) == 0)
-            goto found;
-    }
-
-    status = STATUS_UNSUCCESSFUL;
-    goto fail4;
-
-found:
-    *Address = Function;
-
-    Trace("%s:%s (%04X) @ %p\n",
-          ModuleName,
-          FunctionName,
-          Ordinal,
-          Function);
-
-    Trace("<====\n");
-
-    return STATUS_SUCCESS;
-
-fail4:
-    Error("fail4\n");
-
-fail3:
-    Error("fail3\n");
-
-fail2:
-    Error("fail2\n");
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-
-#undef  MK_PTR
-}
diff --git a/src/xennet/link.h b/src/xennet/link.h
deleted file mode 100644
index 9e4b564..0000000
--- a/src/xennet/link.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (c) Citrix Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms,
- * with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * *   Redistributions of source code must retain the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer.
- * *   Redistributions in binary form must reproduce the above
- *     copyright notice, this list of conditions and the
- *     following disclaimer in the documentation and/or other
- *     materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _XENNET_LINK_H
-#define _XENNET_LINK_H
-
-extern NTSTATUS
-LinkGetRoutineAddress(
-    IN  const CHAR  *ModuleName,
-    IN  const CHAR  *FunctionName,
-    OUT PVOID       *Address
-     );
-
-#endif  // _XENVIF_LINK_H
diff --git a/src/xennet/string.c b/src/xennet/string.c
new file mode 100644
index 0000000..ff0d003
--- /dev/null
+++ b/src/xennet/string.c
@@ -0,0 +1,464 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma warning(disable:4152)   // nonstandard extension, function/data 
pointer conversion in expression
+
+#include <ntddk.h>
+
+#include "string.h"
+#include "dbg_print.h"
+#include "assert.h"
+
+static FORCEINLINE NTSTATUS
+__StringPut(
+    IN  PSTRING String,
+    IN  CHAR    Character
+    )
+{
+    if (String->Length >= String->MaximumLength - 1)
+        return STATUS_BUFFER_OVERFLOW;
+
+    String->Buffer[String->Length++] = Character;
+    return STATUS_SUCCESS;
+}
+
+static PCHAR
+FormatNumber(
+    IN  PCHAR       Buffer,
+    IN  ULONGLONG   Value,
+    IN  UCHAR       Base,
+    IN  BOOLEAN     UpperCase
+    )
+{
+    ULONGLONG       Next = Value / Base;
+
+    if (Next != 0)
+        Buffer = FormatNumber(Buffer, Next, Base, UpperCase);
+
+    Value %= Base;
+
+    if (Value < 10)
+        *Buffer++ = '0' + (CHAR)Value;
+    else
+        *Buffer++ = ((UpperCase) ? 'A' : 'a') + (CHAR)(Value - 10);
+
+    *Buffer = '\0';
+
+    return Buffer;
+}
+
+#define FORMAT_NUMBER(_Arguments, _Type, _Character, _Buffer)                  
             \
+        do {                                                                   
             \
+            U ## _Type  _Value = va_arg((_Arguments), U ## _Type);             
             \
+            BOOLEAN     _UpperCase = FALSE;                                    
             \
+            UCHAR       _Base = 0;                                             
             \
+            ULONG       _Index = 0;                                            
             \
+                                                                               
             \
+            if ((_Character) == 'd' && (_Type)_Value < 0) {                    
             \
+                _Value = -((_Type)_Value);                                     
             \
+                (_Buffer)[_Index++] = '-';                                     
             \
+            }                                                                  
             \
+                                                                               
             \
+            switch (_Character) {                                              
             \
+            case 'o':                                                          
             \
+                _Base = 8;                                                     
             \
+                break;                                                         
             \
+                                                                               
             \
+            case 'd':                                                          
             \
+            case 'u':                                                          
             \
+                _Base = 10;                                                    
             \
+                break;                                                         
             \
+                                                                               
             \
+            case 'p':                                                          
             \
+            case 'X':                                                          
             \
+                _UpperCase = TRUE;                                             
             \
+                /* FALLTHRU */                                                 
             \
+                                                                               
             \
+            case 'x':                                                          
             \
+                _Base = 16;                                                    
             \
+                break;                                                         
             \
+            }                                                                  
             \
+                                                                               
             \
+            (VOID) FormatNumber(&(_Buffer)[_Index], (ULONGLONG)_Value, _Base, 
_UpperCase);  \
+        } while (FALSE)
+
+static NTSTATUS
+StringWriteBuffer(
+    IN  PSTRING         String,
+    IN  const CHAR      *Format,
+    IN  va_list         Arguments
+    )
+{
+    CHAR                Character;
+    NTSTATUS            status;
+
+    status = STATUS_SUCCESS;
+
+    while ((Character = *Format++) != '\0') {
+        UCHAR   Pad = 0;
+        UCHAR   Long = 0;
+        BOOLEAN Wide = FALSE;
+        BOOLEAN ZeroPrefix = FALSE;
+        BOOLEAN OppositeJustification = FALSE;
+
+        if (Character != '%') {
+            status = __StringPut(String, Character);
+            if (!NT_SUCCESS(status))
+                goto done;
+
+            continue;
+        }
+
+        Character = *Format++;
+        ASSERT(Character != '\0');
+
+        if (Character == '-') {
+            OppositeJustification = TRUE;
+            Character = *Format++;
+            ASSERT(Character != '\0');
+        }
+
+        if (isdigit((unsigned char)Character)) {
+            ZeroPrefix = (Character == '0') ? TRUE : FALSE;
+
+            while (isdigit((unsigned char)Character)) {
+                Pad = (Pad * 10) + (Character - '0');
+                Character = *Format++;
+                ASSERT(Character != '\0');
+            }
+        }
+
+        while (Character == 'l') {
+            Long++;
+            Character = *Format++;
+            ASSERT(Character == 'd' ||
+                   Character == 'u' ||
+                   Character == 'o' ||
+                   Character == 'x' ||
+                   Character == 'X' ||
+                   Character == 'l');
+        }
+        ASSERT3U(Long, <=, 2);
+
+        while (Character == 'w') {
+            Wide = TRUE;
+            Character = *Format++;
+            ASSERT(Character == 'c' ||
+                   Character == 's' ||
+                   Character == 'Z');
+        }
+
+        switch (Character) {
+        case 'c': {
+            if (Wide) {
+                WCHAR   Value;
+                Value = va_arg(Arguments, WCHAR);
+
+                status = __StringPut(String, (CHAR)Value);
+                if (!NT_SUCCESS(status))
+                    goto done;
+            } else {
+                CHAR    Value;
+
+                Value = va_arg(Arguments, CHAR);
+
+                status = __StringPut(String, Value);
+                if (!NT_SUCCESS(status))
+                    goto done;
+            }
+            break;
+        }
+        case 'p':
+            ZeroPrefix = TRUE;
+            Pad = sizeof (ULONG_PTR) * 2;
+            Long = sizeof (ULONG_PTR) / sizeof (ULONG);
+            /* FALLTHRU */
+
+        case 'd':
+        case 'u':
+        case 'o':
+        case 'x':
+        case 'X': {
+            CHAR    Buffer[23]; // Enough for 8 bytes in octal plus the NUL 
terminator
+            ULONG   Length;
+            ULONG   Index;
+
+            if (Long == 2)
+                FORMAT_NUMBER(Arguments, LONGLONG, Character, Buffer);
+            else
+                FORMAT_NUMBER(Arguments, LONG, Character, Buffer);
+
+            Length = (ULONG)strlen(Buffer);
+            if (!OppositeJustification) {
+                while (Pad > Length) {
+                    status = __StringPut(String, (ZeroPrefix) ? '0' : ' ');
+                    if (!NT_SUCCESS(status))
+                        goto done;
+
+                    --Pad;
+                }
+            }
+
+            for (Index = 0; Index < Length; Index++) {
+                status = __StringPut(String, Buffer[Index]);
+                if (!NT_SUCCESS(status))
+                    goto done;
+            }
+
+            if (OppositeJustification) {
+                while (Pad > Length) {
+                    status = __StringPut(String, ' ');
+                    if (!NT_SUCCESS(status))
+                        goto done;
+
+                    --Pad;
+                }
+            }
+
+            break;
+        }
+        case 's': {
+            if (Wide) {
+                PWCHAR  Value = va_arg(Arguments, PWCHAR);
+                ULONG   Length;
+                ULONG   Index;
+
+                if (Value == NULL)
+                    Value = L"(null)";
+
+                Length = (ULONG)wcslen(Value);
+
+                if (OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+
+                for (Index = 0; Index < Length; Index++) {
+                    status = __StringPut(String, (CHAR)Value[Index]);
+                    if (!NT_SUCCESS(status))
+                        goto done;
+                }
+
+                if (!OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+            } else {
+                PCHAR   Value = va_arg(Arguments, PCHAR);
+                ULONG   Length;
+                ULONG   Index;
+
+                if (Value == NULL)
+                    Value = "(null)";
+
+                Length = (ULONG)strlen(Value);
+
+                if (OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+
+                for (Index = 0; Index < Length; Index++) {
+                    status = __StringPut(String, Value[Index]);
+                    if (!NT_SUCCESS(status))
+                        goto done;
+                }
+
+                if (!OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+            }
+
+            break;
+        }
+        case 'Z': {
+            if (Wide) {
+                PUNICODE_STRING Value = va_arg(Arguments, PUNICODE_STRING);
+                PWCHAR          Buffer;
+                ULONG           Length;
+                ULONG           Index;
+
+                if (Value == NULL) {
+                    Buffer = L"(null)";
+                    Length = sizeof ("(null)") - 1;
+                } else {
+                    Buffer = Value->Buffer;
+                    Length = Value->Length / sizeof (WCHAR);
+                }
+
+                if (OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+
+                for (Index = 0; Index < Length; Index++) {
+                    status = __StringPut(String, (CHAR)Buffer[Index]);
+                    if (!NT_SUCCESS(status))
+                        goto done;
+                }
+
+                if (!OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+            } else {
+                PANSI_STRING Value = va_arg(Arguments, PANSI_STRING);
+                PCHAR        Buffer;
+                ULONG        Length;
+                ULONG        Index;
+
+                if (Value == NULL) {
+                    Buffer = "(null)";
+                    Length = sizeof ("(null)") - 1;
+                } else {
+                    Buffer = Value->Buffer;
+                    Length = Value->Length / sizeof (CHAR);
+                }
+
+                if (OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+
+                for (Index = 0; Index < Length; Index++) {
+                    status = __StringPut(String, Buffer[Index]);
+                    if (!NT_SUCCESS(status))
+                        goto done;
+                }
+
+                if (!OppositeJustification) {
+                    while (Pad > Length) {
+                        status = __StringPut(String, ' ');
+                        if (!NT_SUCCESS(status))
+                            goto done;
+
+                        --Pad;
+                    }
+                }
+            }
+
+            break;
+        }
+        default:
+            status = __StringPut(String, Character);
+            if (!NT_SUCCESS(status))
+                goto done;
+
+            break;
+        }
+    }
+
+done:
+    return status;
+}
+
+NTSTATUS
+StringVPrintf(
+    IN  PSTRING     String,
+    IN  const CHAR  *Format,
+    IN  va_list     Arguments
+    )
+{
+    NTSTATUS        status;
+
+    status = StringWriteBuffer(String,
+                               Format,
+                               Arguments);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = __StringPut(String, '\0');
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+StringPrintf(
+    IN  PSTRING     String,
+    IN  const CHAR  *Format,
+    ...
+    )
+{
+    va_list         Arguments;
+    NTSTATUS        status;
+
+    va_start(Arguments, Format);
+    status = StringVPrintf(String, Format, Arguments);
+    va_end(Arguments);
+
+    return status;
+}
diff --git a/src/xennet/string.h b/src/xennet/string.h
new file mode 100644
index 0000000..cc3b8d5
--- /dev/null
+++ b/src/xennet/string.h
@@ -0,0 +1,51 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENNET_STRING_H
+#define _XENNET_STRING_H
+
+#include <ntddk.h>
+
+extern NTSTATUS
+StringVPrintf(
+    IN  PSTRING     String,
+    IN  const CHAR  *Format,
+    IN  va_list     Arguments
+    );
+
+extern NTSTATUS
+StringPrintf(
+    IN  PSTRING     String,
+    IN  const CHAR  *Format,
+    ...
+    );
+
+#endif  // _XENNET_STRING_H
diff --git a/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index e80bcb1..054b4a6 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -75,9 +75,9 @@
        <ItemGroup>
                <ClCompile Include="../../src/xennet/adapter.c" />
                <ClCompile Include="../../src/xennet/driver.c" />
-               <ClCompile Include="../../src/xennet/link.c" />
                <ClCompile Include="../../src/xennet/miniport.c" />
                <ClCompile Include="../../src/xennet/receiver.c" />
+               <ClCompile Include="../../src/xennet/string.c" />
                <ClCompile Include="../../src/xennet/transmitter.c" />
        </ItemGroup>
        <ItemGroup>
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index bcc6025..58f4032 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -70,9 +70,9 @@
   <ItemGroup>
     <ClCompile Include="../../src/xennet/adapter.c" />
     <ClCompile Include="../../src/xennet/driver.c" />
-    <ClCompile Include="../../src/xennet/link.c" />
     <ClCompile Include="../../src/xennet/miniport.c" />
     <ClCompile Include="../../src/xennet/receiver.c" />
+    <ClCompile Include="../../src/xennet/string.c" />
     <ClCompile Include="../../src/xennet/transmitter.c" />
   </ItemGroup>
   <ItemGroup>
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.