BOOL NTAPI DbgGdiHTIntegrityCheck() { ULONG i, nDeleted = 0, nFree = 0, nUsed = 0; PGDI_TABLE_ENTRY pEntry; BOOL r = 1; KeEnterCriticalRegion(); /* FIXME: Check reserved entries */ /* Now go through the deleted objects */ i = gulFirstFree & 0xffff; while (i) { pEntry = &GdiHandleTable->Entries[i]; if (i >= GDI_HANDLE_COUNT) { DPRINT1("nDeleted=%lu\n", nDeleted); ASSERT(FALSE); } nDeleted++; /* Check the entry */ if ((pEntry->Type & GDI_ENTRY_BASETYPE_MASK) != 0) { r = 0; DPRINT1("Deleted Entry has a type != 0\n"); } if ((ULONG_PTR)pEntry->KernelData >= GDI_HANDLE_COUNT) { r = 0; DPRINT1("Deleted entries KernelPointer too big\n"); } if (pEntry->UserData != NULL) { r = 0; DPRINT1("Deleted entry has UserData != 0\n"); } if (pEntry->ProcessId != 0) { r = 0; DPRINT1("Deleted entry has ProcessId != 0\n"); } i = (ULONG_PTR)pEntry->KernelData & 0xffff; }; for (i = gulFirstUnused; i < GDI_HANDLE_COUNT; i++) { pEntry = &GdiHandleTable->Entries[i]; if ((pEntry->Type) != 0) { r = 0; DPRINT1("Free Entry has a type != 0\n"); } if ((ULONG_PTR)pEntry->KernelData != 0) { r = 0; DPRINT1("Free entries KernelPointer != 0\n"); } if (pEntry->UserData != NULL) { r = 0; DPRINT1("Free entry has UserData != 0\n"); } if (pEntry->ProcessId != 0) { r = 0; DPRINT1("Free entry has ProcessId != 0\n"); } nFree++; } for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++) { HGDIOBJ Handle; ULONG Type; pEntry = &GdiHandleTable->Entries[i]; Type = pEntry->Type; Handle = (HGDIOBJ)((Type << GDI_ENTRY_UPPER_SHIFT) + i); if (Type & GDI_ENTRY_BASETYPE_MASK) { if (pEntry->KernelData == NULL) { r = 0; DPRINT1("Used entry has KernelData == 0\n"); } else if (pEntry->KernelData <= MmHighestUserAddress) { r = 0; DPRINT1("Used entry invalid KernelData\n"); } else if (((POBJ)(pEntry->KernelData))->hHmgr != Handle) { r = 0; DPRINT1("Used entry %lu, has invalid hHmg %p (expected: %p)\n", i, ((POBJ)(pEntry->KernelData))->hHmgr, Handle); } nUsed++; } } if (RESERVE_ENTRIES_COUNT + nDeleted + nFree + nUsed != GDI_HANDLE_COUNT) { r = 0; DPRINT1("Number of all entries incorrect: RESERVE_ENTRIES_COUNT = %lu, nDeleted = %lu, nFree = %lu, nUsed = %lu\n", RESERVE_ENTRIES_COUNT, nDeleted, nFree, nUsed); } KeLeaveCriticalRegion(); return r; }
NTSTATUS DriverEntry( IN OUT PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) { NDIS_PROTOCOL_DRIVER_CHARACTERISTICS protocolChar; NTSTATUS status = STATUS_SUCCESS; NDIS_STRING protoName = NDIS_STRING_CONST("WIFICAPTURE"); UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; BOOLEAN fSymbolicLink = FALSE; PDEVICE_OBJECT deviceObject = NULL; NDIS_HANDLE ProtocolDriverContext={0}; UNREFERENCED_PARAMETER(pRegistryPath); DEBUGP(DL_LOUD, ("DriverEntry\n")); Globals.pDriverObject = pDriverObject; Globals.EthType = NPROT_ETH_TYPE; NPROT_INIT_EVENT(&Globals.BindsComplete); do { // // Create our device object using which an application can // access NDIS devices. // RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); status = IoCreateDevice (pDriverObject, 0, &ntDeviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject); if (!NT_SUCCESS (status)) { // // Either not enough memory to create a deviceobject or another // deviceobject with the same name exits. This could happen // if you install another instance of this device. // break; } RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName); if (!NT_SUCCESS(status)) { break; } fSymbolicLink = TRUE; deviceObject->Flags |= DO_DIRECT_IO; Globals.ControlDeviceObject = deviceObject; NPROT_INIT_LIST_HEAD(&Globals.OpenList); NPROT_INIT_LOCK(&Globals.GlobalLock); // // Initialize the protocol characterstic structure // NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_DRIVER_CHARACTERISTICS)); protocolChar.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS, protocolChar.Header.Size = sizeof(NDIS_PROTOCOL_DRIVER_CHARACTERISTICS); protocolChar.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; protocolChar.MajorNdisVersion = 6; protocolChar.MinorNdisVersion = 0; protocolChar.Name = protoName; protocolChar.SetOptionsHandler = NULL; protocolChar.OpenAdapterCompleteHandlerEx = NdisprotOpenAdapterComplete; protocolChar.CloseAdapterCompleteHandlerEx = NdisprotCloseAdapterComplete; protocolChar.SendNetBufferListsCompleteHandler = NdisprotSendComplete; protocolChar.OidRequestCompleteHandler = NdisprotRequestComplete; protocolChar.StatusHandlerEx = NdisprotStatus; protocolChar.UninstallHandler = NULL; protocolChar.ReceiveNetBufferListsHandler = NdisprotReceiveNetBufferLists; protocolChar.NetPnPEventHandler = NdisprotPnPEventHandler; protocolChar.BindAdapterHandlerEx = NdisprotBindAdapter; protocolChar.UnbindAdapterHandlerEx = NdisprotUnbindAdapter; // // Register as a protocol driver // status = NdisRegisterProtocolDriver(ProtocolDriverContext, // driver context &protocolChar, &Globals.NdisProtocolHandle); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("Failed to register protocol with NDIS\n")); status = STATUS_UNSUCCESSFUL; break; } Globals.PartialCancelId = NdisGeneratePartialCancelId(); Globals.PartialCancelId <<= ((sizeof(PVOID) - 1) * 8); DEBUGP(DL_LOUD, ("DriverEntry: CancelId %lx\n", Globals.PartialCancelId)); // // Now set only the dispatch points we would like to handle. // pDriverObject->MajorFunction[IRP_MJ_CREATE] = NdisprotOpen; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisprotClose; pDriverObject->MajorFunction[IRP_MJ_READ] = NdisprotRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = NdisprotWrite; pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisprotCleanup; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisprotIoControl; pDriverObject->DriverUnload = NdisprotUnload; status = STATUS_SUCCESS; } while (FALSE); if (!NT_SUCCESS(status)) { if (deviceObject) { KeEnterCriticalRegion(); #pragma prefast(suppress:28107, "The deviceObject is held within the critical section") IoDeleteDevice(deviceObject); KeLeaveCriticalRegion(); Globals.ControlDeviceObject = NULL; } if (fSymbolicLink) { IoDeleteSymbolicLink(&win32DeviceName); fSymbolicLink = FALSE; } if (Globals.NdisProtocolHandle) { NdisDeregisterProtocolDriver(Globals.NdisProtocolHandle); Globals.NdisProtocolHandle = NULL; } } return status; }
BOOLEAN NTAPI ExCompareExchangeCallBack(IN OUT PEX_CALLBACK CallBack, IN PEX_CALLBACK_ROUTINE_BLOCK NewBlock, IN PEX_CALLBACK_ROUTINE_BLOCK OldBlock) { EX_FAST_REF OldValue; PEX_CALLBACK_ROUTINE_BLOCK CallbackBlock; ULONG Count; /* Check that we have a new block */ if (NewBlock) { /* Acquire rundown */ if (!ExfAcquireRundownProtectionEx(&NewBlock->RundownProtect, MAX_FAST_REFS + 1)) { /* This should never happen */ ASSERTMSG("Callback block is already undergoing rundown", FALSE); return FALSE; } } /* Do the swap */ OldValue = ExCompareSwapFastReference(&CallBack->RoutineBlock, NewBlock, OldBlock); /* Get the routine block */ CallbackBlock = ExGetObjectFastReference(OldValue); Count = ExGetCountFastReference(OldValue); /* Make sure the swap worked */ if (CallbackBlock == OldBlock) { /* Make sure we replaced a valid pointer */ if (CallbackBlock) { /* Acquire the flush lock and immediately release it */ KeEnterCriticalRegion(); ExWaitOnPushLock(&ExpCallBackFlush); /* Release rundown protection */ KeLeaveCriticalRegion(); ExfReleaseRundownProtectionEx(&CallbackBlock->RundownProtect, Count + 1); } /* Compare worked */ return TRUE; } else { /* It failed, check if we had a block */ if (NewBlock) { /* We did, remove the refernces that we had added */ ExfReleaseRundownProtectionEx(&NewBlock->RundownProtect, MAX_FAST_REFS + 1); } /* Return failure */ return FALSE; } }
NTSTATUS DokanEventRelease( __in PDEVICE_OBJECT DeviceObject) { PDokanDCB dcb; PDokanVCB vcb; PDokanFCB fcb; PDokanCCB ccb; PLIST_ENTRY fcbEntry, fcbNext, fcbHead; PLIST_ENTRY ccbEntry, ccbNext, ccbHead; NTSTATUS status = STATUS_SUCCESS; vcb = DeviceObject->DeviceExtension; if (GetIdentifierType(vcb) != VCB) { return STATUS_INVALID_PARAMETER; } dcb = vcb->Dcb; //ExAcquireResourceExclusiveLite(&dcb->Resource, TRUE); dcb->Mounted = 0; //ExReleaseResourceLite(&dcb->Resource); // search CCB list to complete not completed Directory Notification KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&vcb->Resource, TRUE); fcbHead = &vcb->NextFCB; for (fcbEntry = fcbHead->Flink; fcbEntry != fcbHead; fcbEntry = fcbNext) { fcbNext = fcbEntry->Flink; fcb = CONTAINING_RECORD(fcbEntry, DokanFCB, NextFCB); ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); ccbHead = &fcb->NextCCB; for (ccbEntry = ccbHead->Flink; ccbEntry != ccbHead; ccbEntry = ccbNext) { ccbNext = ccbEntry->Flink; ccb = CONTAINING_RECORD(ccbEntry, DokanCCB, NextCCB); DDbgPrint(" NotifyCleanup ccb:%X, context:%X, filename:%wZ\n", ccb, (ULONG)ccb->UserContext, &fcb->FileName); FsRtlNotifyCleanup(vcb->NotifySync, &vcb->DirNotifyList, ccb); } ExReleaseResourceLite(&fcb->Resource); } ExReleaseResourceLite(&vcb->Resource); KeLeaveCriticalRegion(); ReleasePendingIrp(&dcb->PendingIrp); ReleasePendingIrp(&dcb->PendingEvent); DokanStopCheckThread(dcb); DokanStopEventNotificationThread(dcb); DokanDeleteDeviceObject(dcb); return status; }
// // configure bus numbers [checked] // VOID PciConfigureBusNumbers(__in PPCI_FDO_EXTENSION FdoExt) { PAGED_CODE(); PPCI_PDO_EXTENSION PdoExt = 0; if(FdoExt != FdoExt->BusRootFdoExtension) PdoExt = static_cast<PPCI_PDO_EXTENSION>(FdoExt->PhysicalDeviceObject->DeviceExtension); KeEnterCriticalRegion(); KeWaitForSingleObject(&FdoExt->ChildListLock,Executive,KernelMode,FALSE,0); PPCI_PDO_EXTENSION BridgeExt = FdoExt->ChildBridgePdoList; ULONG BridgeCount = 0; ULONG ConfiguredBridgeCount = 0; while(BridgeExt) { if(BridgeExt->NotPresent) { PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt); } else { BridgeCount += 1; if((!PdoExt || !PdoExt->Dependent.type1.WeChangedBusNumbers || BridgeExt->Common.DeviceState != PciNotStarted) && PciAreBusNumbersConfigured(BridgeExt)) ConfiguredBridgeCount += 1; else PciDisableBridge(BridgeExt); } BridgeExt = BridgeExt->NextBridge; } KeSetEvent(&FdoExt->ChildListLock,IO_NO_INCREMENT,FALSE); KeLeaveCriticalRegion(); if(!BridgeCount) { PciDebugPrintf(0x100000,"PCI - No bridges found on bus 0x%x\n",FdoExt->BaseBus); return; } if(BridgeCount == ConfiguredBridgeCount) { PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - all already configured\n",BridgeCount,FdoExt->BaseBus); return; } if(!ConfiguredBridgeCount) { PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - all need configuration\n",BridgeCount,FdoExt->BaseBus); return PciSpreadBridges(FdoExt,BridgeCount); } ASSERT(ConfiguredBridgeCount < BridgeCount); PciDebugPrintf(0x100000,"PCI - 0x%x bridges found on bus 0x%x - 0x%x need configuration\n",BridgeCount,FdoExt->BaseBus,BridgeCount - ConfiguredBridgeCount); BridgeExt = FdoExt->ChildBridgePdoList; while(BridgeExt) { if(BridgeExt->NotPresent) { PciDebugPrintf(0x100000,"Skipping not present bridge PDOX @ %p\n",BridgeExt); } else { if((PdoExt && PdoExt->Dependent.type1.WeChangedBusNumbers && BridgeExt->Common.DeviceState == PciNotStarted) || !PciAreBusNumbersConfigured(BridgeExt)) { ASSERT(!BridgeExt->Dependent.type1.PrimaryBus && !BridgeExt->Dependent.type1.SecondaryBus && !BridgeExt->Dependent.type1.SubordinateBus); PciFitBridge(FdoExt,PdoExt); } } BridgeExt = BridgeExt->NextBridge; } }
VOID DokanCompleteCreate( __in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo ) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status; ULONG info; PDokanCCB ccb; PDokanFCB fcb; irp = IrpEntry->Irp; irpSp = IrpEntry->IrpSp; DDbgPrint("==> DokanCompleteCreate\n"); ccb = IrpEntry->FileObject->FsContext2; ASSERT(ccb != NULL); fcb = ccb->Fcb; ASSERT(fcb != NULL); DDbgPrint(" FileName:%wZ\n", &fcb->FileName); ccb->UserContext = EventInfo->Context; //DDbgPrint(" set Context %X\n", (ULONG)ccb->UserContext); status = EventInfo->Status; info = EventInfo->Operation.Create.Information; switch (info) { case FILE_OPENED: DDbgPrint(" FILE_OPENED\n"); break; case FILE_CREATED: DDbgPrint(" FILE_CREATED\n"); break; case FILE_OVERWRITTEN: DDbgPrint(" FILE_OVERWRITTEN\n"); break; case FILE_DOES_NOT_EXIST: DDbgPrint(" FILE_DOES_NOT_EXIST\n"); break; case FILE_EXISTS: DDbgPrint(" FILE_EXISTS\n"); break; case FILE_SUPERSEDED: DDbgPrint(" FILE_SUPERSEDED\n"); break; default: DDbgPrint(" info = %d\n", info); break; } KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); if (NT_SUCCESS(status) && (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE || EventInfo->Operation.Create.Flags & DOKAN_FILE_DIRECTORY)) { if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) { DDbgPrint(" FILE_DIRECTORY_FILE %p\n", fcb); } else { DDbgPrint(" DOKAN_FILE_DIRECTORY %p\n", fcb); } fcb->Flags |= DOKAN_FILE_DIRECTORY; } ExReleaseResourceLite(&fcb->Resource); KeLeaveCriticalRegion(); KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE); if (NT_SUCCESS(status)) { ccb->Flags |= DOKAN_FILE_OPENED; } ExReleaseResourceLite(&ccb->Resource); KeLeaveCriticalRegion(); if (NT_SUCCESS(status)) { if (info == FILE_CREATED) { if (fcb->Flags & DOKAN_FILE_DIRECTORY) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_ADDED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED); } } } else { DDbgPrint(" IRP_MJ_CREATE failed. Free CCB:%p\n", ccb); DokanFreeCCB(ccb); DokanFreeFCB(fcb); } irp->IoStatus.Status = status; irp->IoStatus.Information = info; IoCompleteRequest(irp, IO_NO_INCREMENT); DokanPrintNTStatus(status); DDbgPrint("<== DokanCompleteCreate\n"); }
PDokanFCB DokanGetFCB( __in PDokanVCB Vcb, __in PWCHAR FileName, __in ULONG FileNameLength) { PLIST_ENTRY thisEntry, nextEntry, listHead; PDokanFCB fcb = NULL; ULONG pos; KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&Vcb->Resource, TRUE); // search the FCB which is already allocated // (being used now) listHead = &Vcb->NextFCB; for (thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = nextEntry) { nextEntry = thisEntry->Flink; fcb = CONTAINING_RECORD(thisEntry, DokanFCB, NextFCB); if (fcb->FileName.Length == FileNameLength) { // FileNameLength in bytes for (pos = 0; pos < FileNameLength/sizeof(WCHAR); ++pos) { if (fcb->FileName.Buffer[pos] != FileName[pos]) break; } // we have the FCB which is already allocated and used if (pos == FileNameLength/sizeof(WCHAR)) break; } fcb = NULL; } // we don't have FCB if (fcb == NULL) { DDbgPrint(" Allocate FCB\n"); fcb = DokanAllocateFCB(Vcb); // no memory? if (fcb == NULL) { ExFreePool(FileName); ExReleaseResourceLite(&Vcb->Resource); KeLeaveCriticalRegion(); return NULL; } ASSERT(fcb != NULL); fcb->FileName.Buffer = FileName; fcb->FileName.Length = (USHORT)FileNameLength; fcb->FileName.MaximumLength = (USHORT)FileNameLength; // we already have FCB } else { // FileName (argument) is never used and must be freed ExFreePool(FileName); } InterlockedIncrement(&fcb->FileCount); ExReleaseResourceLite(&Vcb->Resource); KeLeaveCriticalRegion(); return fcb; }
/* * ISSUE: REMOVE this old function implementation as soon as the * boottime pagefile problems with the new one (below) * are resolved. */ NTSTATUS ClasspEjectionControl( IN PDEVICE_OBJECT Fdo, IN PIRP Irp, IN MEDIA_LOCK_TYPE LockType, IN BOOLEAN Lock ) { PFUNCTIONAL_DEVICE_EXTENSION FdoExtension = Fdo->DeviceExtension; PCOMMON_DEVICE_EXTENSION commonExtension = (PCOMMON_DEVICE_EXTENSION) FdoExtension; PFILE_OBJECT_EXTENSION fsContext = NULL; NTSTATUS status; PSCSI_REQUEST_BLOCK srb = NULL; BOOLEAN countChanged = FALSE; PAGED_CODE(); /* * Ensure that the user thread is not suspended while we are holding EjectSynchronizationEvent. */ KeEnterCriticalRegion(); status = KeWaitForSingleObject( &(FdoExtension->EjectSynchronizationEvent), UserRequest, KernelMode, FALSE, NULL); NT_ASSERT(status == STATUS_SUCCESS); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: " "Received request for %s lock type\n", LockTypeStrings[LockType] )); try { PCDB cdb = NULL; // // Determine if this is a "secured" request. // if (LockType == SecureMediaLock) { PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT fileObject = irpStack->FileObject; // // Make sure that the file object we are supplied has a // proper FsContext before we try doing a secured lock. // if (fileObject != NULL) { fsContext = ClassGetFsContext(commonExtension, fileObject); } if (fsContext == NULL) { // // This handle isn't setup correctly. We can't let the // operation go. // status = STATUS_INVALID_PARAMETER; leave; } } if (Lock) { // // This is a lock command. Reissue the command in case bus or // device was reset and the lock was cleared. // note: may need to decrement count if actual lock operation // failed.... // switch (LockType) { case SimpleMediaLock: { FdoExtension->LockCount++; countChanged = TRUE; break; } case SecureMediaLock: { fsContext->LockCount++; FdoExtension->ProtectedLockCount++; countChanged = TRUE; break; } case InternalMediaLock: { FdoExtension->InternalLockCount++; countChanged = TRUE; break; } } } else { // // This is an unlock command. If it's a secured one then make sure // the caller has a lock outstanding or return an error. // note: may need to re-increment the count if actual unlock // operation fails.... // switch (LockType) { case SimpleMediaLock: { if(FdoExtension->LockCount != 0) { FdoExtension->LockCount--; countChanged = TRUE; } break; } case SecureMediaLock: { if(fsContext->LockCount == 0) { status = STATUS_INVALID_DEVICE_STATE; leave; } fsContext->LockCount--; FdoExtension->ProtectedLockCount--; countChanged = TRUE; break; } case InternalMediaLock: { NT_ASSERT(FdoExtension->InternalLockCount != 0); FdoExtension->InternalLockCount--; countChanged = TRUE; break; } } // // We only send an unlock command to the drive if both the // secured and unsecured lock counts have dropped to zero. // if ((FdoExtension->ProtectedLockCount != 0) || (FdoExtension->InternalLockCount != 0) || (FdoExtension->LockCount != 0)) { status = STATUS_SUCCESS; leave; } } status = STATUS_SUCCESS; if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) { srb = (PSCSI_REQUEST_BLOCK)ClasspAllocateSrb(FdoExtension); if (srb == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; leave; } if (FdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) { // // NOTE - this is based on size used in ClasspAllocateSrb // status = InitializeStorageRequestBlock((PSTORAGE_REQUEST_BLOCK)srb, STORAGE_ADDRESS_TYPE_BTL8, CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE, 1, SrbExDataTypeScsiCdb16); if (!NT_SUCCESS(status)) { NT_ASSERT(FALSE); leave; } } else { RtlZeroMemory(srb, sizeof(SCSI_REQUEST_BLOCK)); } SrbSetCdbLength(srb, 6); cdb = SrbGetCdb(srb); NT_ASSERT(cdb != NULL); cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; // // TRUE - prevent media removal. // FALSE - allow media removal. // cdb->MEDIA_REMOVAL.Prevent = Lock; // // Set timeout value. // SrbSetTimeOutValue(srb, FdoExtension->TimeOutValue); // // The actual lock operation on the device isn't so important // as the internal lock counts. Ignore failures. // status = ClassSendSrbSynchronous(FdoExtension->DeviceObject, srb, NULL, 0, FALSE); } } finally { if (!NT_SUCCESS(status)) { TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: FAILED status %x -- " "reverting lock counts\n", status)); if (countChanged) { // // have to revert to previous counts if the // lock/unlock operation actually failed. // if (Lock) { switch (LockType) { case SimpleMediaLock: { FdoExtension->LockCount--; break; } case SecureMediaLock: { fsContext->LockCount--; FdoExtension->ProtectedLockCount--; break; } case InternalMediaLock: { FdoExtension->InternalLockCount--; break; } } } else { switch (LockType) { case SimpleMediaLock: { FdoExtension->LockCount++; break; } case SecureMediaLock: { fsContext->LockCount++; FdoExtension->ProtectedLockCount++; break; } case InternalMediaLock: { FdoExtension->InternalLockCount++; break; } } } } } else { TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: Succeeded\n")); } TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_IOCTL, "ClasspEjectionControl: " "Current Counts: Internal: %x Secure: %x Simple: %x\n", FdoExtension->InternalLockCount, FdoExtension->ProtectedLockCount, FdoExtension->LockCount )); KeSetEvent(&(FdoExtension->EjectSynchronizationEvent), IO_NO_INCREMENT, FALSE); KeLeaveCriticalRegion(); if (srb) { ClassFreeOrReuseSrb(FdoExtension, srb); } } return status; }
VOID DokanCompleteSetInformation( __in PIRP_ENTRY IrpEntry, __in PEVENT_INFORMATION EventInfo ) { PIRP irp; PIO_STACK_LOCATION irpSp; NTSTATUS status; ULONG info = 0; PDokanCCB ccb; PDokanFCB fcb; UNICODE_STRING oldFileName; FILE_INFORMATION_CLASS infoClass; irp = IrpEntry->Irp; status = EventInfo->Status; __try { DDbgPrint("==> DokanCompleteSetInformation\n"); irpSp = IrpEntry->IrpSp; ccb = IrpEntry->FileObject->FsContext2; ASSERT(ccb != NULL); KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&ccb->Resource, TRUE); fcb = ccb->Fcb; ASSERT(fcb != NULL); ccb->UserContext = EventInfo->Context; info = EventInfo->BufferLength; infoClass = irpSp->Parameters.SetFile.FileInformationClass; RtlZeroMemory(&oldFileName, sizeof(UNICODE_STRING)); if (NT_SUCCESS(status)) { if (infoClass == FileDispositionInformation) { if (EventInfo->Operation.Delete.DeleteOnClose) { if (!MmFlushImageSection( &fcb->SectionObjectPointers, MmFlushForDelete)) { DDbgPrint(" Cannot delete user mapped image\n"); status = STATUS_CANNOT_DELETE; } else { ccb->Flags |= DOKAN_DELETE_ON_CLOSE; fcb->Flags |= DOKAN_DELETE_ON_CLOSE; DDbgPrint(" FileObject->DeletePending = TRUE\n"); IrpEntry->FileObject->DeletePending = TRUE; } } else { ccb->Flags &= ~DOKAN_DELETE_ON_CLOSE; fcb->Flags &= ~DOKAN_DELETE_ON_CLOSE; DDbgPrint(" FileObject->DeletePending = FALSE\n"); IrpEntry->FileObject->DeletePending = FALSE; } } // if rename is executed, reassign the file name if(infoClass == FileRenameInformation) { PVOID buffer = NULL; ExAcquireResourceExclusiveLite(&fcb->Resource, TRUE); // this is used to inform rename in the bellow switch case oldFileName.Buffer = fcb->FileName.Buffer; oldFileName.Length = (USHORT)fcb->FileName.Length; oldFileName.MaximumLength = (USHORT)fcb->FileName.Length; // copy new file name buffer = ExAllocatePool(EventInfo->BufferLength+sizeof(WCHAR)); if (buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; ExReleaseResourceLite(&fcb->Resource); ExReleaseResourceLite(&ccb->Resource); KeLeaveCriticalRegion(); __leave; } fcb->FileName.Buffer = buffer; ASSERT(fcb->FileName.Buffer != NULL); RtlZeroMemory(fcb->FileName.Buffer, EventInfo->BufferLength+sizeof(WCHAR)); RtlCopyMemory(fcb->FileName.Buffer, EventInfo->Buffer, EventInfo->BufferLength); fcb->FileName.Length = (USHORT)EventInfo->BufferLength; fcb->FileName.MaximumLength = (USHORT)EventInfo->BufferLength; ExReleaseResourceLite(&fcb->Resource); } } ExReleaseResourceLite(&ccb->Resource); KeLeaveCriticalRegion(); if (NT_SUCCESS(status)) { switch (irpSp->Parameters.SetFile.FileInformationClass) { case FileAllocationInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; case FileBasicInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION, FILE_ACTION_MODIFIED); break; case FileDispositionInformation: if (IrpEntry->FileObject->DeletePending) { if (fcb->Flags & DOKAN_FILE_DIRECTORY) { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_DIR_NAME, FILE_ACTION_REMOVED); } else { DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_REMOVED); } } break; case FileEndOfFileInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; case FileLinkInformation: // TODO: should check whether this is a directory // TODO: should notify new link name //DokanNotifyReportChange(vcb, ccb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_ADDED); break; case FilePositionInformation: // this is never used break; case FileRenameInformation: { DokanNotifyReportChange0(fcb, &oldFileName, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_OLD_NAME); // free old file name ExFreePool(oldFileName.Buffer); DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_FILE_NAME, FILE_ACTION_RENAMED_NEW_NAME); } break; case FileValidDataLengthInformation: DokanNotifyReportChange(fcb, FILE_NOTIFY_CHANGE_SIZE, FILE_ACTION_MODIFIED); break; default: DDbgPrint(" unknown type:%d\n", irpSp->Parameters.SetFile.FileInformationClass); break; } } } __finally { DokanCompleteIrpRequest(irp, status, info); DDbgPrint("<== DokanCompleteSetInformation\n"); } }
NTSTATUS Bus_IoCtl ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; ULONG inlen, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); // // It is not safe to call IOCTL in raised IRQL. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } Bus_IncIoCount (fdoData); irpStack = IoGetCurrentIrpStackLocation (Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_NDASBUS_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(NDASBUS_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PNDASBUS_ADD_TARGET_DATA addTargetData = buffer; BOOLEAN accepted; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType)); status = STATUS_SUCCESS; // // Check structure size // if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) { status = STATUS_INVALID_PARAMETER; break; } if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // // Check to see if acceptable structure. // accepted = TRUE; switch(addTargetData->ucTargetType) { case NDASSCSI_TYPE_DISK_NORMAL: case NDASSCSI_TYPE_DVD: case NDASSCSI_TYPE_VDVD: case NDASSCSI_TYPE_MO: if(addTargetData->ulNumberOfUnitDiskList != 1) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_MIRROR: if(2 != addTargetData->ulNumberOfUnitDiskList) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_AGGREGATION: if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_UNITDISK_FOR_AGGR) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_RAID0: switch(addTargetData->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept accepted = FALSE; break; } break; case NDASSCSI_TYPE_DISK_RAID1R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; if (2 != ulDiskCount) accepted = FALSE; } break; case NDASSCSI_TYPE_DISK_RAID4R3: case NDASSCSI_TYPE_DISK_RAID5: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; switch(ulDiskCount) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept accepted = FALSE; break; } break; } default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n")); accepted = FALSE; break; } if(accepted == FALSE) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n")); status = STATUS_UNSUCCESSFUL; break; } #if DBG NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_TRY_TO_ADDTARGET, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); #endif // Find Pdo Data... pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); break; } // // Save the add target information to the PDO extension // pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, inlen, BUSENUM_POOL_TAG); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { Irp->IoStatus.Information = 0; status = STATUS_INSUFFICIENT_RESOURCES; break; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Init PDO status // pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTER_STATUS_INIT; pdoData->LanscsiAdapterPDO.DeviceMode = addTargetData->DeviceMode; // // Notify to NDASSCSI // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); // // Register Target // if(pdoData->Persistent) { status = LSBus_RegisterTarget(fdoData, addTargetData); if(!NT_SUCCESS(status)) { ExFreePoolWithTag(pdoData->LanscsiAdapterPDO.AddDevInfo, BUSENUM_POOL_TAG); pdoData->LanscsiAdapterPDO.AddDevInfo = NULL; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status)); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_REGISTER_TARGET_FAIL, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n")); } } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REMOVE_TARGET_DATA removeTarget; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REMOVE_TARGET called\n")); if (sizeof (NDASBUS_REMOVE_TARGET_DATA) != inlen) break; removeTarget = (PNDASBUS_REMOVE_TARGET_DATA)buffer; pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); break; } // // redirect to the NDAS SCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_REMOVE_DEVICE, NULL, 0, NULL, 0 ); if(NT_SUCCESS(status) && pdoData->Persistent) { status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ( "REMOVE_TARGET: Removed Target instance," " but LSBus_UnregisterTarget() failed.\n")); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_UNREGISTER_TARGET_FAIL, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n")); } #endif } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = 0; break; } case IOCTL_NDASBUS_STARTSTOP_REGISTRARENUM:{ PULONG onOff = (PULONG)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff)); KeEnterCriticalRegion(); ExAcquireFastMutexUnsafe(&fdoData->RegMutex); if(*onOff != 0) { // // Save old state. // Activate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = TRUE; } else { // // Save old state. // Deactivate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = FALSE; } // // Clean up non-enumerated entries. // LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData); ExReleaseFastMutexUnsafe(&fdoData->RegMutex); KeLeaveCriticalRegion(); Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; } case IOCTL_NDASBUS_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); if ((inlen == outlen)) { PNDASBUS_PLUGIN_HARDWARE_EX2 PlugIn = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n")); status = LSBus_RegisterDevice(fdoData, PlugIn); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("REGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); } break; case IOCTL_NDASBUS_REGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen)) { PNDASBUS_ADD_TARGET_DATA AddTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n")); status = LSBus_RegisterTarget(fdoData, AddTargetData); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_NDASDEV) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_NDASDEV UnregDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n")); status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); } } break; case IOCTL_NDASBUS_UNREGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_TARGET UnregTarget = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n")); status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); } } break; case IOCTL_NDASBUS_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PNDASBUS_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; BOOLEAN acceptStatus; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_SETPDOINFO called\n")); if (sizeof (NDASBUS_SETPDOINFO) != inlen) break; acceptStatus = TRUE; SetPdoInfo = (PNDASBUS_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_SETPDOINFO, SetPdoInfo->SlotNo); break; } // // lock the code section of this function to acquire spinlock in raised IRQL. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: PDO %p: %08lx %08lx %08lx\n", pdoData->Self, SetPdoInfo->AdapterStatus, SetPdoInfo->SupportedFeatures, SetPdoInfo->EnabledFeatures)); // // Deny the status change if the current status is STATUS_STOPPED except for RESETSTATUS flag. // if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n")); if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n")); } else { acceptStatus = FALSE; } } else { if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { acceptStatus = FALSE; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: AddTarget is not occured. Too early to set status.\n")); } } // // Mask off RESETSTATUS. // NDAS service does not need to know it. // SetPdoInfo->AdapterStatus &= ~NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS; // // Set status values to the corresponding physical device object. // Save to the extension // if(acceptStatus) { PNDASBUS_PDOEVENT_ENTRY pdoEventEntry; pdoEventEntry = NdasBusCreatePdoStatusItem(SetPdoInfo->AdapterStatus); if(pdoEventEntry) { NdasBusQueuePdoStatusItem(&pdoData->LanscsiAdapterPDO, pdoEventEntry); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Could not allocate PDO status entry.\n")); } #endif pdoData->LanscsiAdapterPDO.LastAdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures; pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures; // // Queue plugout worker if the NDAS SCSI stop abnormally. // Notify the NDAS service of abnormal termination // if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) && ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_ABNORMAL_TERMINAT)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n")); status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo); // // Set disconnection event // KeSetEvent(pdoData->LanscsiAdapterPDO.DisconEventToService, IO_DISK_INCREMENT, FALSE); } else { // // Notify the adapter status change // KeSetEvent(pdoData->LanscsiAdapterPDO.AlarmEventToService, IO_DISK_INCREMENT, FALSE); } } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // Release the code section. // MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PNDASBUS_NODE_ALIVE_IN pNodeAliveIn; NDASBUS_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(NDASBUS_NODE_ALIVE_IN) || outlen != sizeof(NDASBUS_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PNDASBUS_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_NDASBUS_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_NDASBUS_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPING)) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(NDASBUS_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(NDASBUS_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_NDASBUS_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(NDASBUS_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_UPGRADETOWRITE, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_REDIRECT_NDASSCSI: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REDIRECT_NDASSCSI redirectIoctl; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI called\n")); // Check Parameter. if(inlen < sizeof(NDASBUS_REDIRECT_NDASSCSI)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } redirectIoctl = (PNDASBUS_REDIRECT_NDASSCSI)buffer; pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, redirectIoctl->IoctlCode, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_QUERY_NDASSCSIINFO: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n")); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_QUERY_NDASSCSIINFO, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; NDASBUS_QUERY_INFORMATION Query; PNDASBUS_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(NDASBUS_QUERY_INFORMATION) /*|| outlen < sizeof(NDASBUS_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(NDASBUS_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_NDASBUS_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PNDASBUS_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_NDASBUS_PLUGIN_HARDWARE_EX2: { ULONG structLen; // Without variable length field ULONG wholeStructLen; // With variable length field ULONG inputWholeStructLen; // // Check 32 bit thunking request // if(IoIs32bitProcess(Irp)) { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2_32, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2_32); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2_32) buffer)->Size; } else { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2) buffer)->Size; } if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((structLen + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (wholeStructLen == inputWholeStructLen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx2((PNDASBUS_PLUGIN_HARDWARE_EX2)buffer, inlen, fdoData, IoIs32bitProcess(Irp), Irp->RequestorMode, FALSE); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_GETVERSION: { if (outlen >= sizeof(NDASBUS_GET_VERSION)) { PNDASBUS_GET_VERSION version = (PNDASBUS_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(NDASBUS_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_NDASBUS_UNPLUG_HARDWARE: { if ((sizeof (NDASBUS_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PNDASBUS_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_EJECT_HARDWARE: { if ((sizeof (NDASBUS_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PNDASBUS_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PNDASBUS_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(NDASBUS_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PNDASBUS_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_NDASBUS_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_DVD_GET_STATUS, pDvdStatusData->SlotNo); break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PNDASBUS_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
VOID ClasspCleanupProtectedLocks( IN PFILE_OBJECT_EXTENSION FsContext ) { PCOMMON_DEVICE_EXTENSION commonExtension = FsContext->DeviceObject->DeviceExtension; PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = commonExtension->PartitionZeroExtension; ULONG newDeviceLockCount = 1; PAGED_CODE(); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks called for %p\n", FsContext->DeviceObject)); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks - FsContext %p is locked " "%d times\n", FsContext, FsContext->LockCount)); NT_ASSERT(BreakOnClose == FALSE); // // Synchronize with ejection and ejection control requests. // KeEnterCriticalRegion(); (VOID)KeWaitForSingleObject(&(fdoExtension->EjectSynchronizationEvent), UserRequest, KernelMode, FALSE, NULL); // // For each secure lock on this handle decrement the secured lock count // for the FDO. Keep track of the new value. // if (FsContext->LockCount != 0) { do { InterlockedDecrement((volatile LONG *)&FsContext->LockCount); newDeviceLockCount = InterlockedDecrement(&fdoExtension->ProtectedLockCount); } while (FsContext->LockCount > 0); // // If the new lock count has been dropped to zero then issue a lock // command to the device. // TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: FDO secured lock count = %d " "lock count = %d\n", fdoExtension->ProtectedLockCount, fdoExtension->LockCount)); if ((newDeviceLockCount == 0) && (fdoExtension->LockCount == 0)) { SCSI_REQUEST_BLOCK srb = {0}; UCHAR srbExBuffer[CLASS_SRBEX_SCSI_CDB16_BUFFER_SIZE] = {0}; PSTORAGE_REQUEST_BLOCK srbEx = (PSTORAGE_REQUEST_BLOCK)srbExBuffer; PCDB cdb = NULL; NTSTATUS status; PSCSI_REQUEST_BLOCK srbPtr; TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: FDO lock count dropped " "to zero\n")); if (fdoExtension->AdapterDescriptor->SrbType == SRB_TYPE_STORAGE_REQUEST_BLOCK) { #pragma prefast(suppress:26015, "InitializeStorageRequestBlock ensures buffer access is bounded") status = InitializeStorageRequestBlock(srbEx, STORAGE_ADDRESS_TYPE_BTL8, sizeof(srbExBuffer), 1, SrbExDataTypeScsiCdb16); if (NT_SUCCESS(status)) { srbEx->TimeOutValue = fdoExtension->TimeOutValue; SrbSetCdbLength(srbEx, 6); cdb = SrbGetCdb(srbEx); srbPtr = (PSCSI_REQUEST_BLOCK)srbEx; } else { // // Should not happen. Revert to legacy SRB. // NT_ASSERT(FALSE); srb.TimeOutValue = fdoExtension->TimeOutValue; srb.CdbLength = 6; cdb = (PCDB) &(srb.Cdb); srbPtr = &srb; } } else { srb.TimeOutValue = fdoExtension->TimeOutValue; srb.CdbLength = 6; cdb = (PCDB) &(srb.Cdb); srbPtr = &srb; } cdb->MEDIA_REMOVAL.OperationCode = SCSIOP_MEDIUM_REMOVAL; // // TRUE - prevent media removal. // FALSE - allow media removal. // cdb->MEDIA_REMOVAL.Prevent = FALSE; status = ClassSendSrbSynchronous(fdoExtension->DeviceObject, srbPtr, NULL, 0, FALSE); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_INIT, "ClasspCleanupProtectedLocks: unlock request to drive " "returned status %lx\n", status)); } } KeSetEvent(&fdoExtension->EjectSynchronizationEvent, IO_NO_INCREMENT, FALSE); KeLeaveCriticalRegion(); return; }
VOID ApphelpCacheReleaseLock(VOID) { ExReleaseResourceLite(&ApphelpCacheLock); KeLeaveCriticalRegion(); }
BOOLEAN KspSynchronizedEventRoutine( IN KSEVENTS_LOCKTYPE EventsFlags, IN PVOID EventsLock, IN PKSEVENT_SYNCHRONIZED_ROUTINE SynchronizedRoutine, IN PKSEVENT_CTX Ctx) { BOOLEAN Result = FALSE; KIRQL OldLevel; if (EventsFlags == KSEVENTS_NONE) { /* no synchronization required */ Result = SynchronizedRoutine(Ctx); } else if (EventsFlags == KSEVENTS_SPINLOCK) { /* use spin lock */ KeAcquireSpinLock((PKSPIN_LOCK)EventsLock, &OldLevel); Result = SynchronizedRoutine(Ctx); KeReleaseSpinLock((PKSPIN_LOCK)EventsLock, OldLevel); } else if (EventsFlags == KSEVENTS_MUTEX) { /* use a mutex */ KeWaitForSingleObject(EventsLock, Executive, KernelMode, FALSE, NULL); Result = SynchronizedRoutine(Ctx); KeReleaseMutex((PRKMUTEX)EventsLock, FALSE); } else if (EventsFlags == KSEVENTS_FMUTEX) { /* use a fast mutex */ ExAcquireFastMutex((PFAST_MUTEX)EventsLock); Result = SynchronizedRoutine(Ctx); ExReleaseFastMutex((PFAST_MUTEX)EventsLock); } else if (EventsFlags == KSEVENTS_FMUTEXUNSAFE) { /* acquire fast mutex unsafe */ KeEnterCriticalRegion(); ExAcquireFastMutexUnsafe((PFAST_MUTEX)EventsLock); Result = SynchronizedRoutine(Ctx); ExReleaseFastMutexUnsafe((PFAST_MUTEX)EventsLock); KeLeaveCriticalRegion(); } else if (EventsFlags == KSEVENTS_INTERRUPT) { /* use interrupt for locking */ Result = KeSynchronizeExecution((PKINTERRUPT)EventsLock, (PKSYNCHRONIZE_ROUTINE)SynchronizedRoutine, (PVOID)Ctx); } else if (EventsFlags == KSEVENTS_ERESOURCE) { /* use an eresource */ KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite((PERESOURCE)EventsLock, TRUE); Result = SynchronizedRoutine(Ctx); ExReleaseResourceLite((PERESOURCE)EventsLock); KeLeaveCriticalRegion(); } return Result; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) /*++ Routine Description: Called on loading. We create a device object to handle user-mode requests on, and register ourselves as a protocol with NDIS. Arguments: pDriverObject - Pointer to driver object created by system. pRegistryPath - Pointer to the Unicode name of the registry path for this driver. Return Value: NT Status code --*/ { NDIS_PROTOCOL_DRIVER_CHARACTERISTICS protocolChar = {0}; NTSTATUS status = STATUS_SUCCESS; NDIS_STRING protoName = NDIS_STRING_CONST("NDISPROT"); UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; BOOLEAN fSymbolicLink = FALSE; PDEVICE_OBJECT deviceObject = NULL; NDIS_HANDLE ProtocolDriverContext={0}; UNREFERENCED_PARAMETER(pRegistryPath); DEBUGP(DL_LOUD, ("DriverEntry\n")); Globals.pDriverObject = pDriverObject; Globals.EthType = NPROT_ETH_TYPE; NPROT_INIT_EVENT(&Globals.BindsComplete); do { // // Create our device object using which an application can // access NDIS devices. // RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); status = IoCreateDevice (pDriverObject, 0, &ntDeviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject); if (!NT_SUCCESS (status)) { // // Either not enough memory to create a deviceobject or another // deviceobject with the same name exits. This could happen // if you install another instance of this device. // break; } RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName); if (!NT_SUCCESS(status)) { break; } fSymbolicLink = TRUE; deviceObject->Flags |= DO_DIRECT_IO; Globals.ControlDeviceObject = deviceObject; NPROT_INIT_LIST_HEAD(&Globals.OpenList); NPROT_INIT_LOCK(&Globals.GlobalLock); // // Initialize the protocol characterstic structure // #if (NDIS_SUPPORT_NDIS630) {C_ASSERT(sizeof(protocolChar) >= NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2);} protocolChar.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS, protocolChar.Header.Size = NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2; protocolChar.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_2; #elif (NDIS_SUPPORT_NDIS6) {C_ASSERT(sizeof(protocolChar) >= NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1);} protocolChar.Header.Type = NDIS_OBJECT_TYPE_PROTOCOL_DRIVER_CHARACTERISTICS, protocolChar.Header.Size = NDIS_SIZEOF_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; protocolChar.Header.Revision = NDIS_PROTOCOL_DRIVER_CHARACTERISTICS_REVISION_1; #endif // NDIS MINIPORT VERSION protocolChar.MajorNdisVersion = NDIS_PROT_MAJOR_VERSION; protocolChar.MinorNdisVersion = NDIS_PROT_MINOR_VERSION; protocolChar.MajorDriverVersion = MAJOR_DRIVER_VERSION; protocolChar.MinorDriverVersion = MINOR_DRIVER_VERISON; protocolChar.Name = protoName; protocolChar.SetOptionsHandler = NULL; protocolChar.OpenAdapterCompleteHandlerEx = NdisprotOpenAdapterComplete; protocolChar.CloseAdapterCompleteHandlerEx = NdisprotCloseAdapterComplete; protocolChar.SendNetBufferListsCompleteHandler = NdisprotSendComplete; protocolChar.OidRequestCompleteHandler = NdisprotRequestComplete; protocolChar.StatusHandlerEx = NdisprotStatus; protocolChar.UninstallHandler = NULL; protocolChar.ReceiveNetBufferListsHandler = NdisprotReceiveNetBufferLists; protocolChar.NetPnPEventHandler = NdisprotPnPEventHandler; protocolChar.BindAdapterHandlerEx = NdisprotBindAdapter; protocolChar.UnbindAdapterHandlerEx = NdisprotUnbindAdapter; // // Register as a protocol driver // status = NdisRegisterProtocolDriver(ProtocolDriverContext, // driver context &protocolChar, &Globals.NdisProtocolHandle); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("Failed to register protocol with NDIS\n")); status = STATUS_UNSUCCESSFUL; break; } Globals.PartialCancelId = NdisGeneratePartialCancelId(); Globals.PartialCancelId <<= ((sizeof(PVOID) - 1) * 8); DEBUGP(DL_LOUD, ("DriverEntry: CancelId %lx\n", Globals.PartialCancelId)); // // Now set only the dispatch points we would like to handle. // pDriverObject->MajorFunction[IRP_MJ_CREATE] = NdisprotOpen; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisprotClose; pDriverObject->MajorFunction[IRP_MJ_READ] = NdisprotRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = NdisprotWrite; pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisprotCleanup; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisprotIoControl; pDriverObject->DriverUnload = NdisprotUnload; status = STATUS_SUCCESS; } while (FALSE); if (!NT_SUCCESS(status)) { if (deviceObject) { KeEnterCriticalRegion(); IoDeleteDevice(deviceObject); KeLeaveCriticalRegion(); Globals.ControlDeviceObject = NULL; } if (fSymbolicLink) { IoDeleteSymbolicLink(&win32DeviceName); fSymbolicLink = FALSE; } if (Globals.NdisProtocolHandle) { NdisDeregisterProtocolDriver(Globals.NdisProtocolHandle); Globals.NdisProtocolHandle = NULL; } } return status; }
/* * @implemented */ LONG NTAPI KeReleaseMutant(IN PKMUTANT Mutant, IN KPRIORITY Increment, IN BOOLEAN Abandon, IN BOOLEAN Wait) { KIRQL OldIrql; LONG PreviousState; PKTHREAD CurrentThread = KeGetCurrentThread(); BOOLEAN EnableApc = FALSE; ASSERT_MUTANT(Mutant); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); /* Lock the Dispatcher Database */ OldIrql = KiAcquireDispatcherLock(); /* Save the Previous State */ PreviousState = Mutant->Header.SignalState; /* Check if it is to be abandonned */ if (Abandon == FALSE) { /* Make sure that the Owner Thread is the current Thread */ if (Mutant->OwnerThread != CurrentThread) { /* Release the lock */ KiReleaseDispatcherLock(OldIrql); /* Raise an exception */ ExRaiseStatus(Mutant->Abandoned ? STATUS_ABANDONED : STATUS_MUTANT_NOT_OWNED); } /* If the thread owns it, then increase the signal state */ Mutant->Header.SignalState++; } else { /* It's going to be abandonned */ Mutant->Header.SignalState = 1; Mutant->Abandoned = TRUE; } /* Check if the signal state is only single */ if (Mutant->Header.SignalState == 1) { /* Check if it's below 0 now */ if (PreviousState <= 0) { /* Remove the mutant from the list */ RemoveEntryList(&Mutant->MutantListEntry); /* Save if we need to re-enable APCs */ EnableApc = Mutant->ApcDisable; } /* Remove the Owning Thread and wake it */ Mutant->OwnerThread = NULL; /* Check if the Wait List isn't empty */ if (!IsListEmpty(&Mutant->Header.WaitListHead)) { /* Wake the Mutant */ KiWaitTest(&Mutant->Header, Increment); } } /* Check if the caller wants to wait after this release */ if (Wait == FALSE) { /* Release the Lock */ KiReleaseDispatcherLock(OldIrql); } else { /* Set a wait */ CurrentThread->WaitNext = TRUE; CurrentThread->WaitIrql = OldIrql; } /* Check if we need to re-enable APCs */ if (EnableApc) KeLeaveCriticalRegion(); /* Return the previous state */ return PreviousState; }
NTSTATUS NTAPI PspCreateThread(OUT PHANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ProcessHandle, IN PEPROCESS TargetProcess, OUT PCLIENT_ID ClientId, IN PCONTEXT ThreadContext, IN PINITIAL_TEB InitialTeb, IN BOOLEAN CreateSuspended, IN PKSTART_ROUTINE StartRoutine OPTIONAL, IN PVOID StartContext OPTIONAL) { HANDLE hThread; PEPROCESS Process; PETHREAD Thread; PTEB TebBase = NULL; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status, AccessStatus; HANDLE_TABLE_ENTRY CidEntry; ACCESS_STATE LocalAccessState; PACCESS_STATE AccessState = &LocalAccessState; AUX_ACCESS_DATA AuxData; BOOLEAN Result, SdAllocated; PSECURITY_DESCRIPTOR SecurityDescriptor; SECURITY_SUBJECT_CONTEXT SubjectContext; PAGED_CODE(); PSTRACE(PS_THREAD_DEBUG, "ThreadContext: %p TargetProcess: %p ProcessHandle: %p\n", ThreadContext, TargetProcess, ProcessHandle); /* If we were called from PsCreateSystemThread, then we're kernel mode */ if (StartRoutine) PreviousMode = KernelMode; /* Reference the Process by handle or pointer, depending on what we got */ if (ProcessHandle) { /* Normal thread or System Thread */ Status = ObReferenceObjectByHandle(ProcessHandle, PROCESS_CREATE_THREAD, PsProcessType, PreviousMode, (PVOID*)&Process, NULL); PSREFTRACE(Process); } else { /* System thread inside System Process, or Normal Thread with a bug */ if (StartRoutine) { /* Reference the Process by Pointer */ ObReferenceObject(TargetProcess); Process = TargetProcess; Status = STATUS_SUCCESS; } else { /* Fake ObReference returning this */ Status = STATUS_INVALID_HANDLE; } } /* Check for success */ if (!NT_SUCCESS(Status)) return Status; /* Also make sure that User-Mode isn't trying to create a system thread */ if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess)) { /* Fail */ ObDereferenceObject(Process); return STATUS_INVALID_HANDLE; } /* Create Thread Object */ Status = ObCreateObject(PreviousMode, PsThreadType, ObjectAttributes, PreviousMode, NULL, sizeof(ETHREAD), 0, 0, (PVOID*)&Thread); if (!NT_SUCCESS(Status)) { /* We failed; dereference the process and exit */ ObDereferenceObject(Process); return Status; } /* Zero the Object entirely */ RtlZeroMemory(Thread, sizeof(ETHREAD)); /* Initialize rundown protection */ ExInitializeRundownProtection(&Thread->RundownProtect); /* Initialize exit code */ Thread->ExitStatus = STATUS_PENDING; /* Set the Process CID */ Thread->ThreadsProcess = Process; Thread->Cid.UniqueProcess = Process->UniqueProcessId; /* Create Cid Handle */ CidEntry.Object = Thread; CidEntry.GrantedAccess = 0; Thread->Cid.UniqueThread = ExCreateHandle(PspCidTable, &CidEntry); if (!Thread->Cid.UniqueThread) { /* We couldn't create the CID, dereference the thread and fail */ ObDereferenceObject(Thread); return STATUS_INSUFFICIENT_RESOURCES; } /* Save the read cluster size */ Thread->ReadClusterSize = MmReadClusterSize; /* Initialize the LPC Reply Semaphore */ KeInitializeSemaphore(&Thread->LpcReplySemaphore, 0, 1); /* Initialize the list heads and locks */ InitializeListHead(&Thread->LpcReplyChain); InitializeListHead(&Thread->IrpList); InitializeListHead(&Thread->PostBlockList); InitializeListHead(&Thread->ActiveTimerListHead); KeInitializeSpinLock(&Thread->ActiveTimerListLock); /* Acquire rundown protection */ if (!ExAcquireRundownProtection (&Process->RundownProtect)) { /* Fail */ ObDereferenceObject(Thread); return STATUS_PROCESS_IS_TERMINATING; } /* Now let the kernel initialize the context */ if (ThreadContext) { /* User-mode Thread, create Teb */ Status = MmCreateTeb(Process, &Thread->Cid, InitialTeb, &TebBase); if (!NT_SUCCESS(Status)) { /* Failed to create the TEB. Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Set the Start Addresses */ Thread->StartAddress = (PVOID)KeGetContextPc(ThreadContext); Thread->Win32StartAddress = (PVOID)KeGetContextReturnRegister(ThreadContext); /* Let the kernel intialize the Thread */ Status = KeInitThread(&Thread->Tcb, NULL, PspUserThreadStartup, NULL, Thread->StartAddress, ThreadContext, TebBase, &Process->Pcb); } else { /* System Thread */ Thread->StartAddress = StartRoutine; PspSetCrossThreadFlag(Thread, CT_SYSTEM_THREAD_BIT); /* Let the kernel intialize the Thread */ Status = KeInitThread(&Thread->Tcb, NULL, PspSystemThreadStartup, StartRoutine, StartContext, NULL, NULL, &Process->Pcb); } /* Check if we failed */ if (!NT_SUCCESS(Status)) { /* Delete the TEB if we had done */ if (TebBase) MmDeleteTeb(Process, TebBase); /* Release rundown and dereference */ ExReleaseRundownProtection(&Process->RundownProtect); ObDereferenceObject(Thread); return Status; } /* Lock the process */ KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&Process->ProcessLock); /* Make sure the proces didn't just die on us */ if (Process->ProcessDelete) goto Quickie; /* Check if the thread was ours, terminated and it was user mode */ if ((Thread->Terminated) && (ThreadContext) && (Thread->ThreadsProcess == Process)) { /* Cleanup, we don't want to start it up and context switch */ goto Quickie; } /* * Insert the Thread into the Process's Thread List * Note, this is the ETHREAD Thread List. It is removed in * ps/kill.c!PspExitThread. */ InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry); Process->ActiveThreads++; /* Start the thread */ KeStartThread(&Thread->Tcb); /* Release the process lock */ ExReleasePushLockExclusive(&Process->ProcessLock); KeLeaveCriticalRegion(); /* Release rundown */ ExReleaseRundownProtection(&Process->RundownProtect); /* Notify WMI */ //WmiTraceProcess(Process, TRUE); //WmiTraceThread(Thread, InitialTeb, TRUE); /* Notify Thread Creation */ PspRunCreateThreadNotifyRoutines(Thread, TRUE); /* Reference ourselves as a keep-alive */ ObReferenceObjectEx(Thread, 2); /* Suspend the Thread if we have to */ if (CreateSuspended) KeSuspendThread(&Thread->Tcb); /* Check if we were already terminated */ if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb); /* Create an access state */ Status = SeCreateAccessStateEx(NULL, ThreadContext ? PsGetCurrentProcess() : Process, &LocalAccessState, &AuxData, DesiredAccess, &PsThreadType->TypeInfo.GenericMapping); if (!NT_SUCCESS(Status)) { /* Access state failed, thread is dead */ PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT); /* If we were suspended, wake it up */ if (CreateSuspended) KeResumeThread(&Thread->Tcb); /* Dispatch thread */ KeReadyThread(&Thread->Tcb); /* Dereference completely to kill it */ ObDereferenceObjectEx(Thread, 2); return Status; } /* Insert the Thread into the Object Manager */ Status = ObInsertObject(Thread, AccessState, DesiredAccess, 0, NULL, &hThread); /* Delete the access state if we had one */ if (AccessState) SeDeleteAccessState(AccessState); /* Check for success */ if (NT_SUCCESS(Status)) { /* Wrap in SEH to protect against bad user-mode pointers */ _SEH2_TRY { /* Return Cid and Handle */ if (ClientId) *ClientId = Thread->Cid; *ThreadHandle = hThread; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Thread insertion failed, thread is dead */ PspSetCrossThreadFlag(Thread, CT_DEAD_THREAD_BIT); /* If we were suspended, wake it up */ if (CreateSuspended) KeResumeThread(&Thread->Tcb); /* Dispatch thread */ KeReadyThread(&Thread->Tcb); /* Dereference it, leaving only the keep-alive */ ObDereferenceObject(Thread); /* Close its handle, killing it */ ObCloseHandle(ThreadHandle, PreviousMode); /* Return the exception code */ _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; } else {