/*! * @brief Insert an IRP into the CSQ * * @param Csq - Pointer to the initialized CSQ * @param Irp - Pointer to the IRP to queue * @param Context - Context record to track the IRP while queued * * @return * - Just passes through to IoCsqInsertIrpEx, with no InsertContext */ VOID NTAPI IoCsqInsertIrp( _Inout_ PIO_CSQ Csq, _Inout_ PIRP Irp, _Out_opt_ PIO_CSQ_IRP_CONTEXT Context) { IoCsqInsertIrpEx(Csq, Irp, Context, 0); }
static NTSTATUS V4vCtrlConnect(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, V4V_CONNECT_VALUES *cvs, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; LONG val; XENV4V_INSERT ins = {FALSE}; val = InterlockedExchangeAdd(&ctx->state, 0); if (val != XENV4V_STATE_BOUND) { TraceWarning(("state not BOUND, cannot complete connect request\n")); return STATUS_INVALID_DEVICE_REQUEST; } // Any IRPs that are queued are given a sanity initialization V4vInitializeIrp(irp); // These stream related values are only set once during a single phase of transitioning // to a stream type. ctx->sdst = cvs->ringAddr; ctx->connId = (ULONG64)(RtlRandomEx(&pde->seed) & 0xffffffff); // Update the stream header in the IRPs buffer. The cvs pointer points to the IRPs actual // in/out buffer the IOCTL is defined to have output. cvs->sh.flags = V4V_SHF_SYN; cvs->sh.conid = (ULONG32)ctx->connId; // Now it becomes a connector type for ever more InterlockedExchange(&ctx->type, XENV4V_TYPE_CONNECTOR); // After this transition, we will still send a SYN datagram and get the ACK InterlockedExchange(&ctx->state, XENV4V_STATE_CONNECTING); // Start the connecting timer each time a context goes into this state. V4vStartConnectionTimer(pde); // Flag it irp->Tail.Overlay.DriverContext[0] = (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_WRITE|XENV4V_PEEK_SYN|XENV4V_PEEK_IOCTL); // Always queue it to the back and marks it pending status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins); if (NT_SUCCESS(status)) { status = STATUS_PENDING; // Drive any write IO V4vProcessContextWrites(pde, ctx); } else { // Fail it in IOCTL routine and return go to disconnected state V4vStopConnectionTimer(pde, FALSE); InterlockedExchange(&ctx->state, XENV4V_STATE_DISCONNECTED); } return status; }
static NTSTATUS V4vCtrlConnectWait(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, V4V_WAIT_VALUES *wvs, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; LONG val; XENV4V_INSERT ins = {FALSE}; // This is the connect wait functionality that allows a single end to end // stream connection. This part serves as the "listening" end. val = InterlockedExchangeAdd(&ctx->state, 0); if (val != XENV4V_STATE_BOUND) { TraceWarning(("state not BOUND, cannot complete connect wait request\n")); return STATUS_INVALID_DEVICE_REQUEST; } // Any IRPs that are queued are given a sanity initialization V4vInitializeIrp(irp); // Update the stream header in the IRPs buffer. Just clear if now, later it will // be used for the ACK. wvs->sh.flags = 0; wvs->sh.conid = 0; // Now it becomes a connector type for ever more InterlockedExchange(&ctx->type, XENV4V_TYPE_CONNECTOR); // After this transition, we will wait to get a SYN and send back the ACK InterlockedExchange(&ctx->state, XENV4V_STATE_WAITING); // Flag it irp->Tail.Overlay.DriverContext[0] = (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_READ|XENV4V_PEEK_SYN|XENV4V_PEEK_IOCTL); // Always queue it to the back and marks it pending status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins); if (NT_SUCCESS(status)) { status = STATUS_PENDING; // Drive any read IO V4vProcessContextReads(pde, ctx); } else { // Fail it in IOCTL routine and return go to disconnected state InterlockedExchange(&ctx->state, XENV4V_STATE_DISCONNECTED); } return status; }
/* * @implemented */ NTSTATUS NTAPI FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized) { BOOLEAN FoundShared = FALSE; PLIST_ENTRY SharedEntry; PLOCK_SHARED_RANGE SharedRange = NULL; COMBINED_LOCK_ELEMENT Find; PCOMBINED_LOCK_ELEMENT Entry; PIRP NextMatchingLockIrp; PLOCK_INFORMATION InternalInfo = FileLock->LockInformation; DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n", &FileObject->FileName, FileOffset->HighPart, FileOffset->LowPart, (int)FileOffset->QuadPart, Length->HighPart, Length->LowPart, (int)Length->QuadPart, Key); // The region to unlock must correspond exactly to a previously locked region // -- msdn // But Windows 2003 doesn't assert on it and simply ignores that parameter // ASSERT(AlreadySynchronized); Find.Exclusive.FileLock.StartingByte = *FileOffset; Find.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart; if (!InternalInfo) { DPRINT("File not previously locked (ever)\n"); return STATUS_RANGE_NOT_LOCKED; } Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find); if (!Entry) { DPRINT("Range not locked %wZ\n", &FileObject->FileName); return STATUS_RANGE_NOT_LOCKED; } DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n", Entry->Exclusive.FileLock.ExclusiveLock, Entry->Exclusive.FileLock.StartingByte.HighPart, Entry->Exclusive.FileLock.StartingByte.LowPart, Entry->Exclusive.FileLock.EndingByte.HighPart, Entry->Exclusive.FileLock.EndingByte.LowPart, &FileObject->FileName); if (Entry->Exclusive.FileLock.ExclusiveLock) { if (Entry->Exclusive.FileLock.Key != Key || Entry->Exclusive.FileLock.ProcessId != Process->UniqueProcessId || Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart || Entry->Exclusive.FileLock.EndingByte.QuadPart != FileOffset->QuadPart + Length->QuadPart) { DPRINT("Range not locked %wZ\n", &FileObject->FileName); return STATUS_RANGE_NOT_LOCKED; } RtlCopyMemory(&Find, Entry, sizeof(Find)); // Remove the old exclusive lock region RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry); } else { DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n", &FileObject->FileName, Entry->Exclusive.FileLock.StartingByte.HighPart, Entry->Exclusive.FileLock.StartingByte.LowPart, Entry->Exclusive.FileLock.EndingByte.HighPart, Entry->Exclusive.FileLock.EndingByte.LowPart); for (SharedEntry = InternalInfo->SharedLocks.Flink; SharedEntry != &InternalInfo->SharedLocks; SharedEntry = SharedEntry->Flink) { SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); if (SharedRange->Start.QuadPart == FileOffset->QuadPart && SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart && SharedRange->Key == Key && SharedRange->ProcessId == Process->UniqueProcessId) { FoundShared = TRUE; DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n", &FileObject->FileName, SharedRange->Start.HighPart, SharedRange->Start.LowPart, SharedRange->End.HighPart, SharedRange->End.LowPart, SharedRange->Key); break; } } if (FoundShared) { /* Remove the found range from the shared range lists */ RemoveEntryList(&SharedRange->Entry); ExFreePoolWithTag(SharedRange, TAG_RANGE); /* We need to rebuild the list of shared ranges. */ DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n", &FileObject->FileName, Entry->Exclusive.FileLock.StartingByte.HighPart, Entry->Exclusive.FileLock.StartingByte.LowPart, Entry->Exclusive.FileLock.EndingByte.HighPart, Entry->Exclusive.FileLock.EndingByte.LowPart); /* Remember what was in there and remove it from the table */ Find = *Entry; RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find); /* Put shared locks back in place */ for (SharedEntry = InternalInfo->SharedLocks.Flink; SharedEntry != &InternalInfo->SharedLocks; SharedEntry = SharedEntry->Flink) { COMBINED_LOCK_ELEMENT LockElement; SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); LockElement.Exclusive.FileLock.FileObject = FileObject; LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start; LockElement.Exclusive.FileLock.EndingByte = SharedRange->End; LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId; LockElement.Exclusive.FileLock.Key = SharedRange->Key; LockElement.Exclusive.FileLock.ExclusiveLock = FALSE; if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual) { DPRINT("Skipping range %08x%08x:%08x%08x\n", LockElement.Exclusive.FileLock.StartingByte.HighPart, LockElement.Exclusive.FileLock.StartingByte.LowPart, LockElement.Exclusive.FileLock.EndingByte.HighPart, LockElement.Exclusive.FileLock.EndingByte.LowPart); continue; } DPRINT("Re-creating range %08x%08x:%08x%08x\n", LockElement.Exclusive.FileLock.StartingByte.HighPart, LockElement.Exclusive.FileLock.StartingByte.LowPart, LockElement.Exclusive.FileLock.EndingByte.HighPart, LockElement.Exclusive.FileLock.EndingByte.LowPart); FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement); } } else { return STATUS_RANGE_NOT_LOCKED; } } #ifndef NDEBUG DPRINT("Lock still has:\n"); for (SharedEntry = InternalInfo->SharedLocks.Flink; SharedEntry != &InternalInfo->SharedLocks; SharedEntry = SharedEntry->Flink) { SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry); DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n", &FileObject->FileName, SharedRange->Start.HighPart, SharedRange->Start.LowPart, SharedRange->End.HighPart, SharedRange->End.LowPart, SharedRange->Key); } #endif // this is definitely the thing we want InternalInfo->Generation++; while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find))) { if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation) { // We've already looked at this one, meaning that we looped. // Put it back and exit. IoCsqInsertIrpEx (&InternalInfo->Csq, NextMatchingLockIrp, NULL, NULL); break; } // Got a new lock irp... try to do the new lock operation // Note that we pick an operation that would succeed at the time // we looked, but can't guarantee that it won't just be re-queued // because somebody else snatched part of the range in a new thread. DPRINT("Locking another IRP %p for %p %wZ\n", &FileObject->FileName, FileLock, NextMatchingLockIrp); FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL); } DPRINT("Success %wZ\n", &FileObject->FileName); return STATUS_SUCCESS; }
/* * @implemented */ BOOLEAN NTAPI FsRtlPrivateLock(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, IN BOOLEAN FailImmediately, IN BOOLEAN ExclusiveLock, OUT PIO_STATUS_BLOCK IoStatus, IN PIRP Irp OPTIONAL, IN PVOID Context OPTIONAL, IN BOOLEAN AlreadySynchronized) { NTSTATUS Status; COMBINED_LOCK_ELEMENT ToInsert; PCOMBINED_LOCK_ELEMENT Conflict; PLOCK_INFORMATION LockInfo; PLOCK_SHARED_RANGE NewSharedRange; BOOLEAN InsertedNew; ULARGE_INTEGER UnsignedStart; ULARGE_INTEGER UnsignedEnd; DPRINT("FsRtlPrivateLock(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x, FailImmediately %u, Exclusive %u)\n", &FileObject->FileName, FileOffset->HighPart, FileOffset->LowPart, (int)FileOffset->QuadPart, Length->HighPart, Length->LowPart, (int)Length->QuadPart, Key, FailImmediately, ExclusiveLock); UnsignedStart.QuadPart = FileOffset->QuadPart; UnsignedEnd.QuadPart = FileOffset->QuadPart + Length->QuadPart; if (UnsignedEnd.QuadPart < UnsignedStart.QuadPart) { DPRINT("File offset out of range\n"); IoStatus->Status = STATUS_INVALID_PARAMETER; if (Irp) { DPRINT("Complete lock %p Status %x\n", Irp, IoStatus->Status); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } /* Initialize the lock, if necessary */ if (!FileLock->LockInformation) { LockInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOCK_INFORMATION), TAG_FLOCK); if (!LockInfo) { IoStatus->Status = STATUS_NO_MEMORY; return FALSE; } FileLock->LockInformation = LockInfo; LockInfo->BelongsTo = FileLock; InitializeListHead(&LockInfo->SharedLocks); RtlInitializeGenericTable (&LockInfo->RangeTable, LockCompare, LockAllocate, LockFree, NULL); KeInitializeSpinLock(&LockInfo->CsqLock); InitializeListHead(&LockInfo->CsqList); IoCsqInitializeEx (&LockInfo->Csq, LockInsertIrpEx, LockRemoveIrp, LockPeekNextIrp, LockAcquireQueueLock, LockReleaseQueueLock, LockCompleteCanceledIrp); } LockInfo = FileLock->LockInformation; ToInsert.Exclusive.FileLock.FileObject = FileObject; ToInsert.Exclusive.FileLock.StartingByte = *FileOffset; ToInsert.Exclusive.FileLock.EndingByte.QuadPart = FileOffset->QuadPart + Length->QuadPart; ToInsert.Exclusive.FileLock.ProcessId = Process->UniqueProcessId; ToInsert.Exclusive.FileLock.Key = Key; ToInsert.Exclusive.FileLock.ExclusiveLock = ExclusiveLock; Conflict = RtlInsertElementGenericTable (FileLock->LockInformation, &ToInsert, sizeof(ToInsert), &InsertedNew); if (Conflict && !InsertedNew) { if (Conflict->Exclusive.FileLock.ExclusiveLock || ExclusiveLock) { DPRINT("Conflict %08x%08x:%08x%08x Exc %u (Want Exc %u)\n", Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart, Conflict->Exclusive.FileLock.ExclusiveLock, ExclusiveLock); if (FailImmediately) { DPRINT("STATUS_FILE_LOCK_CONFLICT\n"); IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; if (Irp) { DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n"); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } else { IoStatus->Status = STATUS_PENDING; if (Irp) { Irp->IoStatus.Information = LockInfo->Generation; IoMarkIrpPending(Irp); IoCsqInsertIrpEx (&LockInfo->Csq, Irp, NULL, NULL); } } return FALSE; } else { ULONG i; /* We know of at least one lock in range that's shared. We need to * find out if any more exist and any are exclusive. */ for (i = 0; i < RtlNumberGenericTableElements(&LockInfo->RangeTable); i++) { Conflict = RtlGetElementGenericTable(&LockInfo->RangeTable, i); /* The first argument will be inserted as a shared range */ if (Conflict && (LockCompare(&LockInfo->RangeTable, Conflict, &ToInsert) == GenericEqual)) { if (Conflict->Exclusive.FileLock.ExclusiveLock) { /* Found an exclusive match */ if (FailImmediately) { IoStatus->Status = STATUS_FILE_LOCK_CONFLICT; DPRINT("STATUS_FILE_LOCK_CONFLICT\n"); if (Irp) { DPRINT("STATUS_FILE_LOCK_CONFLICT: Complete\n"); FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } } else { IoStatus->Status = STATUS_PENDING; if (Irp) { IoMarkIrpPending(Irp); IoCsqInsertIrpEx (&LockInfo->Csq, Irp, NULL, NULL); } } return FALSE; } } } DPRINT("Overlapping shared lock %wZ %08x%08x %08x%08x\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart); Conflict = FsRtlpRebuildSharedLockRange(FileLock, LockInfo, &ToInsert); if (!Conflict) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } } /* We got here because there were only overlapping shared locks */ /* A shared lock is both a range *and* a list entry. Insert the entry here. */ DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange = ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE); if (!NewSharedRange) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange->Start = *FileOffset; NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart; NewSharedRange->Key = Key; NewSharedRange->ProcessId = ToInsert.Exclusive.FileLock.ProcessId; InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry); DPRINT("Acquired shared lock %wZ %08x%08x %08x%08x\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart); IoStatus->Status = STATUS_SUCCESS; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return TRUE; } } else if (!Conflict) { /* Conflict here is (or would be) the newly inserted element, but we ran * out of space probably. */ IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } else { DPRINT("Inserted new lock %wZ %08x%08x %08x%08x exclusive %u\n", &FileObject->FileName, Conflict->Exclusive.FileLock.StartingByte.HighPart, Conflict->Exclusive.FileLock.StartingByte.LowPart, Conflict->Exclusive.FileLock.EndingByte.HighPart, Conflict->Exclusive.FileLock.EndingByte.LowPart, Conflict->Exclusive.FileLock.ExclusiveLock); if (!ExclusiveLock) { NewSharedRange = ExAllocatePoolWithTag(NonPagedPool, sizeof(*NewSharedRange), TAG_RANGE); if (!NewSharedRange) { IoStatus->Status = STATUS_NO_MEMORY; if (Irp) { FsRtlCompleteLockIrpReal (FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); } return FALSE; } DPRINT("Adding shared lock %wZ\n", &FileObject->FileName); NewSharedRange->Start = *FileOffset; NewSharedRange->End.QuadPart = FileOffset->QuadPart + Length->QuadPart; NewSharedRange->Key = Key; NewSharedRange->ProcessId = Process->UniqueProcessId; InsertTailList(&LockInfo->SharedLocks, &NewSharedRange->Entry); } /* Assume all is cool, and lock is set */ IoStatus->Status = STATUS_SUCCESS; if (Irp) { /* Complete the request */ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatus->Status, &Status, FileObject); /* Update the status */ IoStatus->Status = Status; } } return TRUE; }
static NTSTATUS V4vCtrlAccept(XENV4V_EXTENSION *pde, XENV4V_CONTEXT *ctx, ULONG ioc, VOID *iob, ULONG iol, PIRP irp) { NTSTATUS status = STATUS_SUCCESS; LONG val; V4V_INIT_VALUES init; FILE_OBJECT *pfo = NULL; XENV4V_CONTEXT *actx; XENV4V_INSERT ins = {FALSE}; HANDLE fh; HANDLE rxe; V4V_ACCEPT_PRIVATE *priv; val = InterlockedExchangeAdd(&ctx->state, 0); if (val != XENV4V_STATE_LISTENING) { TraceWarning(("state not LISTENING, cannot complete accept request\n")); return STATUS_INVALID_DEVICE_REQUEST; } // Handle 32b/64b thunk sructures here and test input #if defined(_WIN64) if (ioc == V4V_IOCTL_ACCEPT_32) { V4V_ACCEPT_VALUES_32 *avs32 = (V4V_ACCEPT_VALUES_32*)iob; if (iol != sizeof(V4V_ACCEPT_VALUES_32)) { TraceError(("invalid accept values.\n")); return STATUS_INVALID_PARAMETER; } fh = avs32->fileHandle; rxe = avs32->rxEvent; priv = (V4V_ACCEPT_PRIVATE*)((UCHAR*)avs32 + FIELD_OFFSET(V4V_ACCEPT_VALUES_32, priv)); } else #endif { V4V_ACCEPT_VALUES *avs = (V4V_ACCEPT_VALUES*)iob; UNREFERENCED_PARAMETER(ioc); if (iol != sizeof(V4V_ACCEPT_VALUES)) { TraceError(("invalid accept values.\n")); return STATUS_INVALID_PARAMETER; } fh = avs->fileHandle; rxe = avs->rxEvent; priv = (V4V_ACCEPT_PRIVATE*)((UCHAR*)avs + FIELD_OFFSET(V4V_ACCEPT_VALUES, priv)); } // Any IRPs that are queued are given a sanity initialization V4vInitializeIrp(irp); // Get a reference to the file object for the handle status = ObReferenceObjectByHandle(fh, 0, *IoFileObjectType, irp->RequestorMode, &pfo, NULL); if (!NT_SUCCESS(status)) { TraceError(("failed to get a reference to the accepter file object - error: 0x%x\n", status)); return status; } actx = (XENV4V_CONTEXT*)pfo->FsContext; ObDereferenceObject(pfo); // Store the referenced acceptor context in the IOCTL buffer so we can access it at > PASSIVE later. V4vAddRefContext(pde, actx); #if defined(_WIN64) priv->q.a = (ULONG64)actx; #else priv->d.a = (ULONG32)actx; #endif // Do the base initialization of the file object context init.rxEvent = rxe; init.ringLength = ctx->ringLength; // shared ring length status = V4vCtrlInitializeFile(actx, &init, irp); if (!NT_SUCCESS(status)) { V4vReleaseContext(pde, actx); TraceError(("failed to initialize the accepter file object - error: 0x%x\n", status)); return status; } // Now initialize the accepter specific state and associate the accepter // with the listener context and ring. KeInitializeSpinLock(&actx->u.accepter.dataLock); actx->u.accepter.dataList = NULL; actx->u.accepter.dataTail = NULL; V4vAddRefContext(pde, ctx); V4vAddRefRing(pde, ctx->ringObject); actx->u.accepter.listenerContext = ctx; actx->ringObject = ctx->ringObject; // Now it becomes an accepter type for ever more InterlockedExchange(&actx->type, XENV4V_TYPE_ACCEPTER); // After this transition, we will wait for a SYN (may be one in the queue already). InterlockedExchange(&actx->state, XENV4V_STATE_ACCEPTING); // Flag it irp->Tail.Overlay.DriverContext[0] = (PVOID)(ULONG_PTR)(XENV4V_PEEK_STREAM|XENV4V_PEEK_ACCEPT|XENV4V_PEEK_IOCTL); // Always queue it to the back and marks it pending. If it fails to be queued then // the user mode call will close the new handle. status = IoCsqInsertIrpEx(&pde->csqObject, irp, NULL, &ins); if (NT_SUCCESS(status)) { status = STATUS_PENDING; // Drive any accepts V4vDoAccepts(pde, ctx); } return status; }