summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/wrapper/cxport.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/tdi/wrapper/cxport.c723
1 files changed, 723 insertions, 0 deletions
diff --git a/private/ntos/tdi/wrapper/cxport.c b/private/ntos/tdi/wrapper/cxport.c
new file mode 100644
index 000000000..db444df32
--- /dev/null
+++ b/private/ntos/tdi/wrapper/cxport.c
@@ -0,0 +1,723 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ cxport.c
+
+Abstract:
+
+ Common Transport Environment utility functions for the NT environment
+
+Author:
+
+ Mike Massa (mikemas) Aug 11, 1993
+
+Revision History:
+
+ Who When What
+ -------- -------- ----------------------------------------------
+ mikemas 08-11-93 created
+
+Notes:
+
+--*/
+
+#include <ntddk.h>
+#include <ndis.h>
+#include <cxport.h>
+#include <tdistat.h>
+
+
+//
+// Mark pageable code
+//
+#ifdef ALLOC_PRAGMA
+
+#pragma alloc_text(PAGE, CTELogEvent)
+
+#endif // ALLOC_PRAGMA
+
+
+//
+// Local variables
+//
+ULONG CTEpTimeIncrement = 0; // used to convert kernel clock ticks to 100ns.
+
+ // Used in the conversion of 100ns times to milliseconds.
+static LARGE_INTEGER Magic10000 = {0xe219652c, 0xd1b71758};
+
+
+//
+// Macros
+//
+//++
+//
+// LARGE_INTEGER
+// CTEConvertMillisecondsTo100ns(
+// IN LARGE_INTEGER MsTime
+// );
+//
+// Routine Description:
+//
+// Converts time expressed in hundreds of nanoseconds to milliseconds.
+//
+// Arguments:
+//
+// MsTime - Time in milliseconds.
+//
+// Return Value:
+//
+// Time in hundreds of nanoseconds.
+//
+//--
+
+#define CTEConvertMillisecondsTo100ns(MsTime) \
+ RtlExtendedIntegerMultiply(MsTime, 10000)
+
+
+//++
+//
+// LARGE_INTEGER
+// CTEConvert100nsToMilliseconds(
+// IN LARGE_INTEGER HnsTime
+// );
+//
+// Routine Description:
+//
+// Converts time expressed in hundreds of nanoseconds to milliseconds.
+//
+// Arguments:
+//
+// HnsTime - Time in hundreds of nanoseconds.
+//
+// Return Value:
+//
+// Time in milliseconds.
+//
+//--
+
+#define SHIFT10000 13
+extern LARGE_INTEGER Magic10000;
+
+#define CTEConvert100nsToMilliseconds(HnsTime) \
+ RtlExtendedMagicDivide((HnsTime), Magic10000, SHIFT10000)
+
+
+//
+// Local functions
+//
+VOID
+CTEpEventHandler(
+ IN PVOID Context
+ )
+/*++
+
+Routine Description:
+
+ Internal handler for scheduled CTE Events. Conforms to calling convention
+ for ExWorkerThread handlers. Calls the CTE handler registered for this
+ event.
+
+Arguments:
+
+ Context - Work item to process.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CTEEvent *Event;
+ CTELockHandle Handle;
+
+#if DBG
+ KIRQL StartingIrql;
+
+ StartingIrql = KeGetCurrentIrql();
+#endif
+
+ Event = (CTEEvent *) Context;
+
+ CTEGetLock(&(Event->ce_lock), &Handle);
+ ASSERT(Event->ce_scheduled);
+ Event->ce_scheduled = 0;
+ CTEFreeLock(&(Event->ce_lock), Handle);
+
+ (*Event->ce_handler)(Event, Event->ce_arg);
+
+#if DBG
+ if (KeGetCurrentIrql() != StartingIrql) {
+ DbgPrint(
+ "CTEpEventHandler: routine %lx , event %lx returned at raised IRQL\n",
+ Event->ce_handler, Event
+ );
+ DbgBreakPoint();
+ }
+#endif
+}
+
+
+VOID
+CTEpTimerHandler(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+ )
+/*++
+
+Routine Description:
+
+ Internal handler for scheduled CTE Timers. Conforms to calling convention
+ for NT DPC handlers. Calls the CTE handler registered for this timer.
+
+Arguments:
+
+ Dpc - Pointer to the DPC routine being run.
+ DeferredContext - Private context for this instance of the DPC.
+ SystemArgument1 - Additional argument.
+ SystemArgument2 - Additional argument.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ CTETimer *Timer;
+
+ UNREFERENCED_PARAMETER(Dpc);
+ UNREFERENCED_PARAMETER(SystemArgument1);
+ UNREFERENCED_PARAMETER(SystemArgument2);
+
+ Timer = (CTETimer *) DeferredContext;
+ (*Timer->t_handler)((CTEEvent *)Timer, Timer->t_arg);
+}
+
+
+//
+// Exported functions.
+//
+int
+CTEInitialize(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Initializes the Common Tranport Environment (CTE).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ 0 if initialization fails. Nonzero otherwise.
+
+--*/
+
+{
+ CTEpTimeIncrement = KeQueryTimeIncrement();
+
+ return(1);
+}
+
+
+void
+CTEInitEvent(
+ CTEEvent *Event,
+ CTEEventRtn Handler
+ )
+/*++
+
+Routine Description:
+
+ Initializes a CTE Event variable.
+
+Arguments:
+
+ Event - Event variable to initialize.
+ Handler - Handler routine for this event variable.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ASSERT(Handler != NULL);
+
+ Event->ce_handler = Handler;
+ Event->ce_scheduled = 0;
+ CTEInitLock(&(Event->ce_lock));
+ ExInitializeWorkItem(&(Event->ce_workitem), CTEpEventHandler, Event);
+}
+
+
+int
+CTEScheduleEvent(
+ IN CTEEvent *Event,
+ IN void *Argument OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ Schedules a routine to be executed later in a different context. In the
+ NT environment, the event is implemented using Executive worker threads.
+
+Arguments:
+
+ Event - Pointer to a CTE Event variable
+ Argument - An argument to pass to the event handler when it is called
+
+Return Value:
+
+ 0 if the event could not be scheduled. Nonzero otherwise.
+
+--*/
+
+{
+ CTELockHandle Handle;
+
+ CTEGetLock(&(Event->ce_lock), &Handle);
+
+ if (!(Event->ce_scheduled)) {
+ Event->ce_scheduled = 1;
+ Event->ce_arg = Argument;
+
+ ExQueueWorkItem(
+ &(Event->ce_workitem),
+ CriticalWorkQueue
+ );
+ }
+
+ CTEFreeLock(&(Event->ce_lock), Handle);
+
+ return(1);
+}
+
+
+void
+CTEInitTimer(
+ CTETimer *Timer
+ )
+/*++
+
+Routine Description:
+
+ Initializes a CTE Timer variable.
+
+Arguments:
+
+ Timer - Timer variable to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ Timer->t_handler = NULL;
+ Timer->t_arg = NULL;
+ KeInitializeDpc(&(Timer->t_dpc), CTEpTimerHandler, Timer);
+ KeInitializeTimer(&(Timer->t_timer));
+}
+
+
+void *
+CTEStartTimer(
+ CTETimer *Timer,
+ unsigned long DueTime,
+ CTEEventRtn Handler,
+ void *Context
+ )
+
+/*++
+
+Routine Description:
+
+ Sets a CTE Timer for expiration.
+
+Arguments:
+
+ Timer - Pointer to a CTE Timer variable.
+ DueTime - Time in milliseconds after which the timer should expire.
+ Handler - Timer expiration handler routine.
+ Context - Argument to pass to the handler.
+
+Return Value:
+
+ 0 if the timer could not be set. Nonzero otherwise.
+
+--*/
+
+{
+ LARGE_INTEGER LargeDueTime;
+
+ ASSERT(Handler != NULL);
+
+ //
+ // Convert milliseconds to hundreds of nanoseconds and negate to make
+ // an NT relative timeout.
+ //
+ LargeDueTime.HighPart = 0;
+ LargeDueTime.LowPart = DueTime;
+ LargeDueTime = CTEConvertMillisecondsTo100ns(LargeDueTime);
+ LargeDueTime.QuadPart = -LargeDueTime.QuadPart;
+
+ Timer->t_handler = Handler;
+ Timer->t_arg = Context;
+
+ KeSetTimer(
+ &(Timer->t_timer),
+ LargeDueTime,
+ &(Timer->t_dpc)
+ );
+
+ return((void *) 1);
+}
+
+
+unsigned long
+CTESystemUpTime(
+ void
+ )
+
+/*++
+
+Routine Description:
+
+ Provides the time since system boot in milliseconds.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The time since boot in milliseconds.
+
+--*/
+
+{
+ LARGE_INTEGER TickCount;
+
+ //
+ // Get tick count and convert to hundreds of nanoseconds.
+ //
+ KeQueryTickCount(&TickCount);
+
+ TickCount = RtlExtendedIntegerMultiply(
+ TickCount,
+ (LONG) CTEpTimeIncrement
+ );
+
+ TickCount = CTEConvert100nsToMilliseconds(TickCount);
+
+ ASSERT(TickCount.HighPart == 0);
+
+ return(TickCount.LowPart);
+}
+
+
+extern uint
+CTEBlock(
+ IN CTEBlockStruc *BlockEvent
+ )
+{
+ NTSTATUS Status;
+
+ Status = KeWaitForSingleObject(
+ &(BlockEvent->cbs_event),
+ UserRequest,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ //
+ // BUGBUG: Do something better here.
+ //
+ BlockEvent->cbs_status = Status;
+ }
+
+ return(BlockEvent->cbs_status);
+}
+
+
+extern void
+CTESignal(
+ IN CTEBlockStruc *BlockEvent,
+ IN uint Status
+ )
+{
+ BlockEvent->cbs_status = Status;
+ KeSetEvent(&(BlockEvent->cbs_event), 0, FALSE);
+ return;
+}
+
+
+BOOLEAN
+CTEInitString(
+ IN OUT PNDIS_STRING DestinationString,
+ IN char *SourceString
+ )
+
+/*++
+
+Routine Description:
+
+ Converts a C style ASCII string to an NDIS_STRING. Resources needed for
+ the NDIS_STRING are allocated and must be freed by a call to
+ CTEFreeString.
+
+Arguments:
+
+ DestinationString - A pointer to an NDIS_STRING variable with no
+ associated data buffer.
+
+ SourceString - The C style ASCII string source.
+
+
+Return Value:
+
+ TRUE if the initialization succeeded. FALSE otherwise.
+
+--*/
+
+{
+ STRING AnsiString;
+ ULONG UnicodeLength;
+
+ RtlInitString(&AnsiString, SourceString);
+
+ // calculate size of unicoded ansi string + 2 for NULL terminator
+ UnicodeLength = RtlAnsiStringToUnicodeSize(&AnsiString) + 2;
+ DestinationString->MaximumLength = (USHORT) UnicodeLength;
+
+ // allocate storage for the unicode string
+ DestinationString->Buffer = ExAllocatePool(NonPagedPool, UnicodeLength);
+
+ if (DestinationString->Buffer == NULL) {
+ return(FALSE);
+ }
+
+ // Finally, convert the string to unicode
+ RtlAnsiStringToUnicodeString(DestinationString, &AnsiString, FALSE);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+CTEAllocateString(
+ PNDIS_STRING String,
+ unsigned short MaximumLength
+ )
+
+/*++
+
+Routine Description:
+
+ Allocates a data buffer for Length characters in an uninitialized
+ NDIS_STRING. The allocated space must be freed by a call to CTEFreeString.
+
+
+Arguments:
+
+ String - A pointer to an NDIS_STRING variable with no
+ associated data buffer.
+
+ Length - The maximum length of the string. In Unicode, this is a
+ byte count.
+
+Return Value:
+
+ TRUE if the initialization succeeded. FALSE otherwise.
+
+--*/
+
+{
+ String->Buffer = ExAllocatePool(
+ NonPagedPool,
+ MaximumLength + sizeof(UNICODE_NULL)
+ );
+
+ if (String->Buffer == NULL) {
+ return(FALSE);
+ }
+
+ String->Length = 0;
+ String->MaximumLength = MaximumLength + sizeof(UNICODE_NULL);
+
+ return(TRUE);
+}
+
+
+
+LONG
+CTELogEvent(
+ IN PVOID LoggerId,
+ IN ULONG EventCode,
+ IN ULONG UniqueEventValue,
+ IN USHORT NumStrings,
+ IN PVOID StringsList, OPTIONAL
+ IN ULONG DataSize,
+ IN PVOID Data OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This function allocates an I/O error log record, fills it in and writes it
+ to the I/O error log.
+
+
+Arguments:
+
+ LoggerId - Pointer to the driver object logging this event.
+
+ EventCode - Identifies the error message.
+
+ UniqueEventValue - Identifies this instance of a given error message.
+
+ NumStrings - Number of unicode strings in strings list.
+
+ DataSize - Number of bytes of data.
+
+ Strings - Array of pointers to unicode strings (PWCHAR).
+
+ Data - Binary dump data for this message, each piece being
+ aligned on word boundaries.
+
+Return Value:
+
+ TDI_SUCCESS - The error was successfully logged.
+ TDI_BUFFER_TOO_SMALL - The error data was too large to be logged.
+ TDI_NO_RESOURCES - Unable to allocate memory.
+
+Notes:
+
+ This code is paged and may not be called at raised IRQL.
+
+--*/
+{
+ PIO_ERROR_LOG_PACKET ErrorLogEntry;
+ ULONG PaddedDataSize;
+ ULONG PacketSize;
+ ULONG TotalStringsSize = 0;
+ USHORT i;
+ PWCHAR *Strings;
+ PWCHAR Tmp;
+
+
+ PAGED_CODE();
+
+ Strings = (PWCHAR *) StringsList;
+
+ //
+ // Sum up the length of the strings
+ //
+ for (i=0; i<NumStrings; i++) {
+ PWCHAR currentString;
+ ULONG stringSize;
+
+ stringSize = sizeof(UNICODE_NULL);
+ currentString = Strings[i];
+
+ while (*currentString++ != UNICODE_NULL) {
+ stringSize += sizeof(WCHAR);
+ }
+
+ TotalStringsSize += stringSize;
+ }
+
+ if (DataSize % sizeof(ULONG)) {
+ PaddedDataSize = DataSize +
+ (sizeof(ULONG) - (DataSize % sizeof(ULONG)));
+ }
+ else {
+ PaddedDataSize = DataSize;
+ }
+
+ PacketSize = TotalStringsSize + PaddedDataSize;
+
+ if (PacketSize > CTE_MAX_EVENT_LOG_DATA_SIZE) {
+ return(TDI_BUFFER_TOO_SMALL); // Too much error data
+ }
+
+ //
+ // Now add in the size of the log packet, but subtract 4 from the data
+ // since the packet struct contains a ULONG for data.
+ //
+ if (PacketSize > sizeof(ULONG)) {
+ PacketSize += sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
+ }
+ else {
+ PacketSize += sizeof(IO_ERROR_LOG_PACKET);
+ }
+
+ ASSERT(PacketSize <= ERROR_LOG_MAXIMUM_SIZE);
+
+ ErrorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(
+ (PDRIVER_OBJECT) LoggerId,
+ (UCHAR) PacketSize
+ );
+
+ if (ErrorLogEntry == NULL) {
+ return(TDI_NO_RESOURCES);
+ }
+
+ //
+ // Fill in the necessary log packet fields.
+ //
+ ErrorLogEntry->UniqueErrorValue = UniqueEventValue;
+ ErrorLogEntry->ErrorCode = EventCode;
+ ErrorLogEntry->NumberOfStrings = NumStrings;
+ ErrorLogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) +
+ PaddedDataSize - sizeof(ULONG);
+ ErrorLogEntry->DumpDataSize = (USHORT) PaddedDataSize;
+
+ //
+ // Copy the Dump Data to the packet
+ //
+ if (DataSize > 0) {
+ RtlMoveMemory(
+ (PVOID) ErrorLogEntry->DumpData,
+ Data,
+ DataSize
+ );
+ }
+
+ //
+ // Copy the strings to the packet.
+ //
+ Tmp = (PWCHAR) ((char *) ErrorLogEntry +
+ ErrorLogEntry->StringOffset +
+ PaddedDataSize);
+
+ for (i=0; i<NumStrings; i++) {
+ PWCHAR wchPtr = Strings[i];
+
+ while( (*Tmp++ = *wchPtr++) != UNICODE_NULL);
+ }
+
+ IoWriteErrorLogEntry(ErrorLogEntry);
+
+ return(TDI_SUCCESS);
+}
+