#include "util.h"
#include "dbg_print.h"
#include "assert.h"
-#include "link.h"
+#include "string.h"
#define MAXNAMELEN 128
PXENNET_RECEIVER Receiver;
PXENNET_TRANSMITTER Transmitter;
BOOLEAN Enabled;
-
- NTSTATUS (*_snprintf_s)(char *,
- size_t,
- size_t,
- const char *,
- ...);
};
static LONG AdapterCount;
ULONG Index;
CHAR Distribution[MAXNAMELEN];
CHAR Vendor[MAXNAMELEN];
+ STRING String;
const CHAR *Product;
NTSTATUS status;
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,
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]))
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);
return NDIS_STATUS_SUCCESS;
-fail5:
- AdapterClearDistribution(Adapter);
-
fail4:
- Adapter->_snprintf_s = NULL;
+ AdapterClearDistribution(Adapter);
fail3:
XENBUS_SUSPEND(Release, &Adapter->SuspendInterface);
AdapterClearDistribution(Adapter);
- Adapter->_snprintf_s = NULL;
-
XENBUS_SUSPEND(Release, &Adapter->SuspendInterface);
XENBUS_STORE(Release, &Adapter->StoreInterface);
}
+++ /dev/null
-/* 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
-}
+++ /dev/null
-/* 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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
<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>
<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>