static NTSTATUS Pkt0DispatchWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_WORKITEM work_item; KIRQL old_irql; NTSTATUS status; work_item = IoAllocateWorkItem(DeviceObject); if (work_item == NULL) { return Pkt0CompleteIrp(Irp, STATUS_INSUFFICIENT_RESOURCES, 0); } KeAcquireSpinLock(&Pkt0ContextLock, &old_irql); if (Pkt0Context->closing) { status = Pkt0CompleteIrp(Irp, STATUS_PIPE_CLOSING, 0); } else { InsertTailList(&Pkt0Context->irp_write_queue, &Irp->Tail.Overlay.ListEntry); IoMarkIrpPending(Irp); status = STATUS_PENDING; } KeReleaseSpinLock(&Pkt0ContextLock, old_irql); if (status == STATUS_PENDING) { IoQueueWorkItemEx(work_item, Pkt0DeferredWrite, DelayedWorkQueue, NULL); } else { IoFreeWorkItem(work_item); } return status; }
NTSTATUS HidUmdfInternalIoctl( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp ) { PIO_WORKITEM workitem; NTSTATUS status; // // If Irql is not dispatch, handle it in the current thread. // otherwise queue a workitem because UMDF cannot handle io request at // dispatch level. HID minidriver receives IOCTLS normally at // passive level but it may receive ping pong irp at dispatch level in some // error conditions. // if (KeGetCurrentIrql() < DISPATCH_LEVEL) { return HidUmdfInternalIoctlWorker(DeviceObject, Irp); } // // allocate and queue workitem // workitem = IoAllocateWorkItem(DeviceObject); if (workitem == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; KdPrint(("HidUmdf: Failed to allocate workitem to process IOCTL " "0x%p devobj 0x%p sent at dispatch level. status 0x%x\n", Irp, DeviceObject, status)); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } // // since we are going to return STATUS_PENDING, mark the irp pending. // IoMarkIrpPending(Irp); // // Queue the workitem. The workitem will be freed by the worker function. // IoQueueWorkItemEx(workitem, IoctlWorkItemEx, DelayedWorkQueue, Irp); return STATUS_PENDING; }
NTSTATUS Log_Print(LOG_LEVEL Level, LPCSTR pszFormat, ...) { NTSTATUS Status = STATUS_SUCCESS; LARGE_INTEGER SystemTime, LocalTime; TIME_FIELDS TimeFields; PLOG_COUNTED_STRING Line = NULL; va_list args; KIRQL Irql = KeGetCurrentIrql(); LPCSTR StrLevel = " :"; if (!LogFile) return STATUS_INVALID_DEVICE_STATE; if (Irql > DISPATCH_LEVEL) return STATUS_INVALID_LEVEL; KeQuerySystemTime(&SystemTime); ExSystemTimeToLocalTime(&SystemTime, &LocalTime); RtlTimeToTimeFields(&LocalTime, &TimeFields); Line = ExAllocatePoolWithTag(NonPagedPool, MAX_LOG_STRING_SIZE + FIELD_OFFSET(LOG_COUNTED_STRING, Data), LogAllocationTag); if (!Line) return STATUS_INSUFFICIENT_RESOURCES; switch (Level) { case LL_FATAL: #if DBG DbgBreakPointWithStatus(DBG_STATUS_FATAL); #endif StrLevel = "FATAL :"; break; case LL_ERROR: StrLevel = "ERROR :"; break; case LL_WARNING: StrLevel = "WARNING:"; break; case LL_INFO: StrLevel = "INFO :"; break; case LL_VERBOSE: StrLevel = "VERBOSE:"; break; case LL_DEBUG: StrLevel = "DEBUG :"; break; } Status = StringCbPrintfA(Line->Data, MAX_LOG_STRING_SIZE, "%04u.%02u.%02u %02u:%02u:%02u.%03u PR:0x%04X TH:0x%04X IL:%d %s ", TimeFields.Year, TimeFields.Month, TimeFields.Day, TimeFields.Hour, TimeFields.Minute, TimeFields.Second, TimeFields.Milliseconds, (ULONG)PsGetCurrentProcessId() & 0xFFFF, (ULONG)PsGetCurrentThreadId() & 0xFFFF, (ULONG)Irql, StrLevel); if (SUCCEEDED(Status)) { va_start(args, pszFormat); Line->DataLength = (USHORT)strlen(Line->Data); Status = StringCbVPrintfA(Line->Data + Line->DataLength, MAX_LOG_STRING_SIZE - Line->DataLength, pszFormat, args); if (SUCCEEDED(Status)) { Line->DataLength = (USHORT)strlen(Line->Data); if (Irql != PASSIVE_LEVEL) { PIO_WORKITEM pWorkItem = IoAllocateWorkItem(LogDeviceObject); InterlockedIncrement(&LogScheduledPrints); IoQueueWorkItemEx(pWorkItem, Log_WriteWorker, DelayedWorkQueue, Line); Status = STATUS_PENDING; } else { Status = Log_WriteLine(Line); } } va_end(args); } if (Status != STATUS_PENDING) ExFreePoolWithTag(Line, LogAllocationTag); return Status; }