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

[win-pv-devel] [PATCH] Stop using RtlStringCbPrintfA()



It appears that linking an NDIS driver with any ntstrsafe function (when
building with VS2012 and the 8.0 WDK at least) has the side effect of
requiring use of DbgPrint(). Whilst this may not sound like a problem, it
is. This is because the NDISTest 6.0 1c_KernelCalls test insists that any
use of DbgPrint is illegal and so it's impossible to logo an NDIS driver
using ntstrsafe functions.

This patch works around the issue by dynamically linking (at run-time) to
the ntdll _snprintf_s function as a replacement for calls to
RtlStringCbPrintfA(). This entails importing the dynamic linking code from
XENVIF since MmGetSystemRoutineAddress() doesn't seem to work for that
symbol.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xennet/adapter.c         |  40 ++++---
 src/xennet/link.c            | 250 +++++++++++++++++++++++++++++++++++++++++++
 src/xennet/link.h            |  42 ++++++++
 vs2012/xennet/xennet.vcxproj |   3 +-
 vs2013/xennet/xennet.vcxproj |   3 +-
 5 files changed, 323 insertions(+), 15 deletions(-)
 create mode 100644 src/xennet/link.c
 create mode 100644 src/xennet/link.h

diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
index dca9b7b..d85f4d1 100644
--- a/src/xennet/adapter.c
+++ b/src/xennet/adapter.c
@@ -32,7 +32,6 @@
 #define INITGUID 1
 
 #include <ndis.h>
-#include <ntstrsafe.h>
 #include <stdlib.h>
 #include <version.h>
 
@@ -46,6 +45,7 @@
 #include "util.h"
 #include "dbg_print.h"
 #include "assert.h"
+#include "link.h"
 
 #define MAXNAMELEN  128
 
@@ -1300,6 +1300,11 @@ __AdapterSetDistribution(
     )
 {
     ULONG               Index;
+    NTSTATUS            (*___snprintf_s)(char *,
+                                         size_t,
+                                         size_t,
+                                         const char *,
+                                         ...);
     CHAR                Distribution[MAXNAMELEN];
     CHAR                Vendor[MAXNAMELEN];
     const CHAR          *Product;
@@ -1307,15 +1312,21 @@ __AdapterSetDistribution(
 
     Trace("====>\n");
 
+    status = LinkGetRoutineAddress("ntdll.dll",
+                                   "_snprintf_s",
+                                   (PVOID *)&___snprintf_s);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
     Index = 0;
     while (Index <= MAXIMUM_INDEX) {
         PCHAR   Buffer;
 
-        status = RtlStringCbPrintfA(Distribution,
-                                    MAXNAMELEN,
-                                    "%u",
-                                    Index);
-        ASSERT(NT_SUCCESS(status));
+        (VOID) ___snprintf_s(Distribution,
+                             MAXNAMELEN,
+                             _TRUNCATE,
+                             "%u",
+                             Index);
 
         status = XENBUS_STORE(Read,
                               &Adapter->StoreInterface,
@@ -1327,7 +1338,7 @@ __AdapterSetDistribution(
             if (status == STATUS_OBJECT_NAME_NOT_FOUND)
                 goto update;
 
-            goto fail1;
+            goto fail2;
         }
 
         XENBUS_STORE(Free,
@@ -1338,14 +1349,14 @@ __AdapterSetDistribution(
     }
 
     status = STATUS_UNSUCCESSFUL;
-    goto fail2;
+    goto fail3;
 
 update:
-    status = RtlStringCbPrintfA(Vendor,
-                                MAXNAMELEN,
-                                "%s",
-                                VENDOR_NAME_STR);
-    ASSERT(NT_SUCCESS(status));
+    (VOID) ___snprintf_s(Vendor,
+                         MAXNAMELEN,
+                         _TRUNCATE,
+                         "%s",
+                         VENDOR_NAME_STR);
 
     for (Index  = 0; Vendor[Index] != '\0'; Index++)
         if (!isalnum((UCHAR)Vendor[Index]))
@@ -1378,6 +1389,9 @@ update:
     Trace("<====\n");
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
 fail2:
     Error("fail2\n");
 
diff --git a/src/xennet/link.c b/src/xennet/link.c
new file mode 100644
index 0000000..e2a41bc
--- /dev/null
+++ b/src/xennet/link.c
@@ -0,0 +1,250 @@
+/* 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
new file mode 100644
index 0000000..9e4b564
--- /dev/null
+++ b/src/xennet/link.h
@@ -0,0 +1,42 @@
+/* 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/vs2012/xennet/xennet.vcxproj b/vs2012/xennet/xennet.vcxproj
index 3ca7407..e80bcb1 100644
--- a/vs2012/xennet/xennet.vcxproj
+++ b/vs2012/xennet/xennet.vcxproj
@@ -40,7 +40,7 @@
                </ClCompile>
                <Link>
                        
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
-                       
<AdditionalDependencies>$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDependencies)</AdditionalDependencies>
+                       
<AdditionalDependencies>$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
                        <EnableCOMDATFolding>false</EnableCOMDATFolding>
                </Link>
                <Inf>
@@ -75,6 +75,7 @@
        <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/transmitter.c" />
diff --git a/vs2013/xennet/xennet.vcxproj b/vs2013/xennet/xennet.vcxproj
index 0064a92..bcc6025 100644
--- a/vs2013/xennet/xennet.vcxproj
+++ b/vs2013/xennet/xennet.vcxproj
@@ -36,7 +36,7 @@
     </ClCompile>
     <Link>
       <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
-      
<AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      
<AdditionalDependencies>$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)/libcntpr.lib;$(DDK_LIB_PATH)/aux_klib.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <EnableCOMDATFolding>false</EnableCOMDATFolding>
     </Link>
     <Inf>
@@ -70,6 +70,7 @@
   <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/transmitter.c" />
-- 
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®.