// // Send Stop Ccb to the LURN. // NTSTATUS SendStopCcbToLurn( PLURELATION_NODE Lurn ) { PCCB ccb; NTSTATUS ntStatus; KDPrintM(DBG_LURN_TRACE,("entered.\n")); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); ntStatus = LSCcbAllocate(&ccb); if(!NT_SUCCESS(ntStatus)) { return STATUS_INSUFFICIENT_RESOURCES; } LSCCB_INITIALIZE(ccb, 0); ccb->OperationCode = CCB_OPCODE_STOP; ccb->HwDeviceExtension = NULL; LSCcbSetFlag(ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED|CCB_FLAG_LOWER_LURN); LSCcbSetCompletionRoutine(ccb, NULL, NULL); // // Send a CCB to the LURN. // ntStatus = LurnRequest( Lurn, ccb ); if(!NT_SUCCESS(ntStatus)) { LSCcbFree(ccb); } return ntStatus; }
NTSTATUS NdasDluSrbIoctlSendCCBWithComp( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PNDAS_DLU_EXTENSION NdasDluLuExtension, IN PSCSI_REQUEST_BLOCK Srb, IN UINT32 CcbOpCode, IN PVOID CmdBuffer, IN ULONG CmdBufferLen ){ NTSTATUS status; PCCB ccb; // // Query to the LUR // status = LsCcbAllocate(&ccb); if(!NT_SUCCESS(status)) { Srb->SrbStatus = SRB_STATUS_ERROR; KDPrint(1,("LsCcbAllocate() failed.\n")); return STATUS_SUCCESS; } LSCCB_INITIALIZE(ccb); ccb->OperationCode = CcbOpCode; LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED); ccb->Srb = Srb; ccb->DataBufferLength = CmdBufferLen; ccb->DataBuffer = CmdBuffer; LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension); InterlockedIncrement(&NdasDluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); status = LurRequest( NdasDluLuExtension->LUR, ccb ); if(!NT_SUCCESS(status)) { LsCcbFree(ccb); Srb->SrbStatus = SRB_STATUS_ERROR; LsuDecrementTdiClientInProgress(); KDPrint(1,("LurRequest() failed.\n")); return STATUS_SUCCESS; } return STATUS_PENDING; }
NTSTATUS NdasDluSrbControl( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PSCSI_REQUEST_BLOCK Srb ) { PSRB_IO_CONTROL srbIoControl; PUCHAR srbIoctlBuffer; LONG srbIoctlBufferLength; ULONG controlCode; NTSTATUS status; UCHAR srbStatus; PNDAS_DLU_EXTENSION ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension); // // Start off being paranoid. // if (Srb->DataBuffer == NULL) { KDPrint(1,("DataBuffer is NULL\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } status = STATUS_MORE_PROCESSING_REQUIRED; srbStatus = SRB_STATUS_SUCCESS; // // Extract the io_control // srbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer; // // Based on the signature, determine if this is Disk class ioctl or our own's those. // if (strncmp(srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE, 8) == 0) { // // NDAS MINIPORT own's. // Continue to the parsing and execution in this function. // } else if(strncmp(srbIoControl->Signature, "SCSIDISK", 8) == 0) { #if 1 // // Disk class request // Complete the SRB in the disk class ioctl function. // return NdasDluDiskClassControl(LogicalUnitExtension, ndasDluExtension, Srb); #else KDPrint(1,("Disk class control disabled.\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; #endif } else { KDPrint(1,("Signature mismatch %8s, %8s\n", srbIoControl->Signature, NDASSCSI_IOCTL_SIGNATURE)); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } // // Get the control code. // controlCode = srbIoControl->ControlCode; // // Get the Ioctl buffer. If this is a send message request, it gets // fixed up to be an I2O message later. // srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL); srbIoctlBufferLength = srbIoControl->Length; // // Based on the control code, figure out what to do. // switch (controlCode) { case NDASSCSI_IOCTL_GET_DVD_STATUS: { srbStatus = NdasDluSrbIoctlGetDVDSTatus( LogicalUnitExtension, ndasDluExtension, srbIoctlBufferLength, srbIoctlBuffer, &srbIoControl->ReturnCode ); if(srbStatus == SRB_STATUS_SUCCESS) { KDPrint(4,("NDASSCSI_IOCTL_QUERYINFO_EX: Successful.\n")); status = STATUS_SUCCESS; } else { status = STATUS_UNSUCCESSFUL; } } break; case NDASSCSI_IOCTL_GET_SLOT_NO: KDPrint(2,("Get Slot No. Slot number is %d\n", ndasDluExtension->LogicalUnitAddress)); if(srbIoctlBufferLength < sizeof(ULONG)) { srbIoControl->ReturnCode = SRB_STATUS_DATA_OVERRUN; srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } *(PULONG)srbIoctlBuffer = ndasDluExtension->LogicalUnitAddress; srbIoControl->ReturnCode = SRB_STATUS_SUCCESS; srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; case NDASSCSI_IOCTL_QUERYINFO_EX: { PNDASSCSI_QUERY_INFO_DATA QueryInfo; PUCHAR tmpBuffer; KDPrint(5, ("Query information EX.\n")); QueryInfo = (PNDASSCSI_QUERY_INFO_DATA)srbIoctlBuffer; tmpBuffer = ExAllocatePoolWithTag(NonPagedPool, srbIoctlBufferLength, NDAS_DLU_PTAG_IOCTL); if(tmpBuffer == NULL) { ASSERT(FALSE); KDPrint(1,("NDASSCSI_IOCTL_QUERYINFO_EX: SRB_STATUS_DATA_OVERRUN. BufferLength:%d\n", srbIoctlBufferLength)); srbStatus = SRB_STATUS_DATA_OVERRUN; break; } status = NdasDluSrbIoctlQueryInfo( LogicalUnitExtension, ndasDluExtension, Srb, QueryInfo, srbIoctlBufferLength, tmpBuffer, &srbIoControl->ReturnCode, &srbStatus ); // // tmpBuffer only lives up to the end of current scope. // // When NdasDluSrbIoctlQueryInfo returns STATUS_PENDING, // we cannot touch srbIoctlBuffer at all because srbIoctlBuffer // is being touch by the completion routine. // // Other cases, we have to copy from the temporarily output buffer // (tmpBuffer) to the final output buffer (srbIoctlBuffer) // if (STATUS_PENDING != status) { RtlCopyMemory(srbIoctlBuffer, tmpBuffer, srbIoctlBufferLength); } ExFreePoolWithTag(tmpBuffer, NDAS_DLU_PTAG_IOCTL); break; } case NDASSCSI_IOCTL_UPGRADETOWRITE: { PLURN_UPDATE LurnUpdate; PCCB Ccb; // // Set a CCB // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: LsCcbAllocate() failed.\n")); break; } LurnUpdate = (PLURN_UPDATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_UPDATE), NDAS_DLU_PTAG_IOCTL); if(!LurnUpdate) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: ExAllocatePoolWithTag() failed.\n")); status = STATUS_INSUFFICIENT_RESOURCES; break; } LSCCB_INITIALIZE(Ccb); Ccb->OperationCode = CCB_OPCODE_UPDATE; Ccb->DataBuffer = LurnUpdate; Ccb->DataBufferLength = sizeof(LURN_UPDATE); LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); // Ioctl Srb will complete asynchronously. Ccb->Srb = Srb; InterlockedIncrement(&ndasDluExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension); LurnUpdate->UpdateClass = LURN_UPDATECLASS_WRITEACCESS_USERID; status = LurRequest( ndasDluExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { KDPrint(1,("NDASSCSI_IOCTL_UPGRADETOWRITE: LurnRequest() failed.\n")); NdasDluLogError( LogicalUnitExtension, Srb, Srb->PathId, Srb->TargetId, Srb->Lun, NDASSCSI_IO_UPGRADEIOCTL_FAIL, EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_UPGRADEIOCTL, 0) ); LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); ExFreePoolWithTag(LurnUpdate, NDSC_PTAG_IOCTL); status = STATUS_SUCCESS; srbStatus = SRB_STATUS_INVALID_REQUEST; } else { status = STATUS_PENDING; } break; } case NDASSCSI_IOCTL_NOOP: { PCCB Ccb; // // Query to the LUR // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LsCcbAllocate() failed.\n")); break; } LSCCB_INITIALIZE(Ccb); Ccb->OperationCode = CCB_OPCODE_NOOP; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED); Ccb->Srb = Srb; LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, LogicalUnitExtension); InterlockedIncrement(&ndasDluExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); status = LurRequest( ndasDluExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LurRequest() failed.\n")); break; } srbStatus = SRB_STATUS_SUCCESS; status = STATUS_PENDING; break; } case NDASSCSI_IOCTL_ADD_USERBACL: { PNDAS_BLOCK_ACE bace = (PNDAS_BLOCK_ACE)srbIoctlBuffer; // input PBLOCKACE_ID blockAceId = (PBLOCKACE_ID)srbIoctlBuffer; // output UCHAR lsuAccessMode; PLSU_BLOCK_ACE lsuBace; UINT64 blockStartAddr; UINT64 blockEndAddr; if(srbIoctlBufferLength < sizeof(NDAS_BLOCK_ACE)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } lsuAccessMode = 0; if(bace->AccessMode & NBACE_ACCESS_READ) { lsuAccessMode |= LSUBACE_ACCESS_READ; } if(bace->AccessMode & NBACE_ACCESS_WRITE) { lsuAccessMode |= LSUBACE_ACCESS_WRITE; } if (bace->IsByteAddress) { blockStartAddr = bace->StartingOffset / ndasDluExtension->LUR->BlockBytes; blockEndAddr = (bace->StartingOffset + bace->Length) / ndasDluExtension->LUR->BlockBytes - 1; } else { blockStartAddr = bace->BlockStartAddr; blockEndAddr = bace->BlockEndAddr; } lsuBace = LsuCreateBlockAce( lsuAccessMode, blockStartAddr, blockEndAddr ); if(lsuBace == NULL) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } // Set returned BACE ID. *blockAceId = lsuBace->BlockAceId; LsuInsertAce(&ndasDluExtension->LUR->UserBacl, lsuBace); srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case NDASSCSI_IOCTL_REMOVE_USERBACL: { PNDSCIOCTL_REMOVE_USERBACL ioctlRemoveUserAcl = (PNDSCIOCTL_REMOVE_USERBACL)srbIoctlBuffer; BLOCKACE_ID blockAceId; PLSU_BLOCK_ACE lsuBacl; if(srbIoctlBufferLength < sizeof(NDSCIOCTL_REMOVE_USERBACL)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } blockAceId = ioctlRemoveUserAcl->NdasBlockAceId; // input if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } if(blockAceId == 0) { KDPrint(1,("REMOVE_USERBACL: Zero block ACE ID.\n")); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } lsuBacl = LsuRemoveAceById(&ndasDluExtension->LUR->UserBacl, blockAceId); if(lsuBacl == NULL) { KDPrint(1,("REMOVE_USERBACL: Invalid block ACE ID.\n")); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } LsuFreeBlockAce(lsuBacl); srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } case NDASSCSI_IOCTL_DEVICE_LOCK: { if(srbIoctlBufferLength < sizeof(NDSCIOCTL_DEVICELOCK)) { srbStatus = SRB_STATUS_DATA_OVERRUN; status = STATUS_UNSUCCESSFUL; break; } if(ndasDluExtension->LUR == NULL) { srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = NdasDluIoctlDeviceLock( LogicalUnitExtension, ndasDluExtension, (PNDSCIOCTL_DEVICELOCK)srbIoctlBuffer, Srb); srbStatus = Srb->SrbStatus; break; } default: KDPrint(2,("Control Code (%x)\n", controlCode)); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_MORE_PROCESSING_REQUIRED; } Srb->SrbStatus = srbStatus; return status; }
NTSTATUS NdasDluIoctlDeviceLock( IN PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, IN PNDAS_DLU_EXTENSION DluLuExtension, IN PNDSCIOCTL_DEVICELOCK DeviceLockControl, IN PSCSI_REQUEST_BLOCK Srb ){ NTSTATUS status; PLURN_DEVLOCK_CONTROL lurnDeviceLock; PCCB ccb; PNDAS_DLU_EXTENSION ndasDluExtension = NdasDluGetExtension(LogicalUnitExtension); // // Create a CCB // status = LsCcbAllocate(&ccb); if(!NT_SUCCESS(status)) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("LsCcbAllocate() failed.\n")); return status; } lurnDeviceLock = (PLURN_DEVLOCK_CONTROL)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_DEVLOCK_CONTROL), NDAS_DLU_PTAG_IOCTL); if(!lurnDeviceLock) { Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("ExAllocatePoolWithTag() failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } LSCCB_INITIALIZE(ccb); ccb->OperationCode = CCB_OPCODE_DEVLOCK; ccb->DataBuffer = lurnDeviceLock; ccb->DataBufferLength = sizeof(LURN_DEVLOCK_CONTROL); LsCcbSetFlag(ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); // Ioctl Srb will complete asynchronously. ccb->Srb = Srb; InterlockedIncrement(&DluLuExtension->RequestExecuting); // // Increment in-progress count // LsuIncrementTdiClientInProgress(); LsCcbSetCompletionRoutine(ccb, NdasDluCcbCompletion, LogicalUnitExtension); // // Set up request // lurnDeviceLock->LockId = DeviceLockControl->LockId; lurnDeviceLock->LockOpCode = DeviceLockControl->LockOpCode; lurnDeviceLock->AdvancedLock = DeviceLockControl->AdvancedLock; lurnDeviceLock->AddressRangeValid = DeviceLockControl->AddressRangeValid; lurnDeviceLock->RequireLockAcquisition = DeviceLockControl->RequireLockAcquisition; lurnDeviceLock->StartingAddress = DeviceLockControl->StartingAddress; lurnDeviceLock->ContentionTimeOut = DeviceLockControl->ContentionTimeOut; RtlCopyMemory(lurnDeviceLock->LockData, DeviceLockControl->LockData, NDSCLOCK_LOCKDATA_LENGTH); ASSERT(NDSCLOCK_LOCKDATA_LENGTH == LURNDEVLOCK_LOCKDATA_LENGTH); // // Send the request // status = LurRequest( ndasDluExtension->LUR, ccb ); if(!NT_SUCCESS(status)) { KDPrint(1,("LurnRequest() failed.\n")); LsCcbFree(ccb); ExFreePoolWithTag(lurnDeviceLock, NDSC_PTAG_IOCTL); status = STATUS_SUCCESS; Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; } else { status = STATUS_PENDING; } return status; }
NTSTATUS NdasDluSrbIoctlQueryInfo( PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, PNDAS_DLU_EXTENSION DluLuExtension, PSCSI_REQUEST_BLOCK Srb, PNDASSCSI_QUERY_INFO_DATA QueryInfo, ULONG OutputBufferLength, PUCHAR OutputBuffer, PULONG SrbIoctlReturnCode, PUCHAR SrbStatus ) { NTSTATUS status; PCCB Ccb; // KIRQL oldIrql; UNREFERENCED_PARAMETER(LogicalUnitExtension); UNREFERENCED_PARAMETER(DluLuExtension); *SrbIoctlReturnCode = SRB_STATUS_SUCCESS; *SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; switch(QueryInfo->InfoClass) { case NdscPrimaryUnitDiskInformation: { PNDSCIOCTL_PRIMUNITDISKINFO primUnitDisk = (PNDSCIOCTL_PRIMUNITDISKINFO)OutputBuffer; PLUR_QUERY lurQuery; PLURN_PRIMARYINFORMATION lurPrimaryInfo; PBYTE lurBuffer; KDPrint(1,("NdscPrimaryUnitDiskInformation\n")); if(OutputBufferLength < sizeof(NDSCIOCTL_PRIMUNITDISKINFO)) { KDPrint(1,("Too small output buffer\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_BUFFER_TOO_SMALL; if (OutputBufferLength > sizeof(UINT32)) primUnitDisk->Length = sizeof(NDSCIOCTL_PRIMUNITDISKINFO); break; } // // Query to the LUR // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } lurBuffer = ExAllocatePoolWithTag( NonPagedPool, SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)), LURN_IOCTL_POOL_TAG); if(lurBuffer == NULL) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } // // Set up asynchronous CCB // LSCCB_INITIALIZE(Ccb); Ccb->Srb = Srb; Ccb->OperationCode = CCB_OPCODE_QUERY; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); Ccb->DataBuffer = lurBuffer; Ccb->DataBufferLength = sizeof(LURN_PRIMARYINFORMATION); LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension); InterlockedIncrement(&DluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); lurQuery = (PLUR_QUERY)lurBuffer; lurQuery->InfoClass = LurPrimaryLurnInformation; lurQuery->Length = SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)); lurQuery->QueryDataLength = 0; lurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(lurQuery); if(DluLuExtension->LUR == NULL) { LsuDecrementTdiClientInProgress(); InterlockedDecrement(&DluLuExtension->RequestExecuting); ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG); LsCcbFree(Ccb); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = LurRequest( DluLuExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { LsuDecrementTdiClientInProgress(); InterlockedDecrement(&DluLuExtension->RequestExecuting); ExFreePoolWithTag(lurBuffer, LURN_IOCTL_POOL_TAG); LsCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = STATUS_PENDING; break; } case NdscLurInformation: { PNDSCIOCTL_LURINFO info = (PNDSCIOCTL_LURINFO)OutputBuffer; PLUR_QUERY lurQuery; UINT32 lurnEnumInfoLen; UINT32 nodeCount; KDPrint(1,("NdscLurInformation\n")); if(OutputBufferLength < FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns)) { KDPrint(2,("LurInfo: Buffer size %d is less than required %d bytes\n", OutputBufferLength, FIELD_OFFSET(NDSCIOCTL_LURINFO, Lurns))); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } // // allocate a CCB // status = LsCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { KDPrint(1,("LsCcbAllocate() failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; break; } // // initialize query CCB // LSCCB_INITIALIZE(Ccb); Ccb->Srb = Srb; Ccb->OperationCode = CCB_OPCODE_QUERY; LsCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); if (DluLuExtension->LUR) { nodeCount = DluLuExtension->LUR->NodeCount; } else { nodeCount = 0; ASSERT(FALSE); } lurnEnumInfoLen = FIELD_OFFSET(LURN_ENUM_INFORMATION, Lurns) + sizeof(LURN_INFORMATION) * nodeCount; // Allocate memory and initialize it. LUR_QUERY_INITIALIZE(lurQuery, LurEnumerateLurn, 0, lurnEnumInfoLen); if(!lurQuery) { LsCcbFree(Ccb); KDPrint(1,("allocating DataBuffer failed.\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INSUFFICIENT_RESOURCES; break; } Ccb->DataBuffer = lurQuery; Ccb->DataBufferLength = lurQuery->Length; // // Set completion routine // LsCcbSetCompletionRoutine(Ccb, NdasDluCcbCompletion, DluLuExtension); InterlockedIncrement(&DluLuExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); // // send the CCB down // status = LurRequest( DluLuExtension->LUR, Ccb ); if(!NT_SUCCESS(status)) { InterlockedDecrement(&DluLuExtension->RequestExecuting); LsuDecrementTdiClientInProgress(); LsCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); ExFreePoolWithTag(lurQuery, NDSC_PTAG_IOCTL); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } status = STATUS_PENDING; break; } case NdscSystemBacl: case NdscUserBacl: { ULONG requiredBufLen; PNDAS_BLOCK_ACL ndasBacl = (PNDAS_BLOCK_ACL)OutputBuffer; PLSU_BLOCK_ACL targetBacl; KDPrint(1,("NdscSystemBacl/UserBacl: going to default LuExtention 0.\n")); if(DluLuExtension->LUR == NULL) { *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; break; } if(QueryInfo->InfoClass == NdscSystemBacl) targetBacl = &DluLuExtension->LUR->SystemBacl; else targetBacl = &DluLuExtension->LUR->UserBacl; status = LsuConvertLsuBaclToNdasBacl( ndasBacl, OutputBufferLength, &requiredBufLen, targetBacl); if(status == STATUS_BUFFER_TOO_SMALL) { // // Set required field. // if(OutputBufferLength >= FIELD_OFFSET(NDAS_BLOCK_ACL, BlockACECnt)) { ndasBacl->Length = requiredBufLen; } // // Set error code to the srb ioctl, but return success // *SrbIoctlReturnCode = SRB_STATUS_DATA_OVERRUN; } else if(!NT_SUCCESS(status)) { *SrbStatus = SRB_STATUS_ERROR; break; } *SrbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } default: KDPrint(1,("Invalid Information Class!!\n")); *SrbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_INVALID_PARAMETER; } return status; }
NTSTATUS MiniSrbControl( IN PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, IN PMINIPORT_LU_EXTENSION LuExtension, IN PSCSI_REQUEST_BLOCK Srb, IN ULONG CurSrbSequence ) /*++ Routine Description: This is the SRB_IO_CONTROL handler for this driver. These requests come from the management driver. Arguments: DeviceExtension - Context Srb - The request to process. Return Value: Value from the helper routines, or if handled in-line, SUCCESS or INVALID_REQUEST. --*/ { PSRB_IO_CONTROL srbIoControl; PUCHAR srbIoctlBuffer; LONG srbIoctlBufferLength; ULONG controlCode; ULONG transferPages = 0; NTSTATUS status; UCHAR srbStatus; // // Start off being paranoid. // if (Srb->DataBuffer == NULL) { KDPrint(1,("DataBuffer is NULL\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } status = STATUS_MORE_PROCESSING_REQUIRED; srbStatus = SRB_STATUS_SUCCESS; // // Extract the io_control // srbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer; // // Ensure the signature is correct. // if (strncmp(srbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8) != 0) { KDPrint(1,("Signature mismatch %8s, %8s\n", srbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE)); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; return STATUS_INVALID_PARAMETER; } // // Get the control code. // controlCode = srbIoControl->ControlCode; // // Get the Ioctl buffer. If this is a send message request, it gets // fixed up to be an I2O message later. // srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL); srbIoctlBufferLength = srbIoControl->Length; // // Based on the control code, figure out what to do. // switch (controlCode) { case LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS: { srbStatus = SrbIoctlGetDVDSTatus( HwDeviceExtension, LuExtension, srbIoctlBufferLength, srbIoctlBuffer, &srbIoControl->ReturnCode, CurSrbSequence ); if(srbStatus == SRB_STATUS_SUCCESS) { KDPrint(4,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: Successful.\n")); status = STATUS_SUCCESS; } else { status = STATUS_UNSUCCESSFUL; } } break; case LANSCSIMINIPORT_IOCTL_GET_SLOT_NO: KDPrint(2,("Get Slot No. Slot number is %d\n", HwDeviceExtension->SlotNumber)); *(PULONG)srbIoctlBuffer = HwDeviceExtension->SlotNumber; srbIoControl->ReturnCode = 0; srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; case LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: { PLSMPIOCTL_QUERYINFO QueryInfo; PUCHAR tmpBuffer; KDPrint(5, ("Query information EX.\n")); QueryInfo = (PLSMPIOCTL_QUERYINFO)srbIoctlBuffer; tmpBuffer = ExAllocatePoolWithTag(NonPagedPool, srbIoctlBufferLength, LSMP_PTAG_IOCTL); if(tmpBuffer == NULL) { ASSERT(FALSE); KDPrint(1,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: SRB_STATUS_DATA_OVERRUN. BufferLength:%d\n", srbIoctlBufferLength)); srbStatus = SRB_STATUS_DATA_OVERRUN; break; } srbStatus = SrbIoctlQueryInfo( HwDeviceExtension, LuExtension, QueryInfo, srbIoctlBufferLength, tmpBuffer, &srbIoControl->ReturnCode, CurSrbSequence ); if(srbStatus == SRB_STATUS_SUCCESS) { KDPrint(4,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: Successful.\n")); RtlCopyMemory(srbIoctlBuffer, tmpBuffer, srbIoctlBufferLength); status = STATUS_SUCCESS; } else { status = STATUS_UNSUCCESSFUL; } ExFreePoolWithTag(tmpBuffer, LSMP_PTAG_IOCTL); break; } case LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: { PLURN_UPDATE LurnUpdate; PCCB Ccb; // // Set a CCB // status = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: LSCcbAllocate() failed.\n")); break; } LurnUpdate = (PLURN_UPDATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_UPDATE), LSMP_PTAG_IOCTL); if(!LurnUpdate) { srbStatus = SRB_STATUS_INVALID_REQUEST; KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: ExAllocatePoolWithTag() failed.\n")); status = STATUS_INSUFFICIENT_RESOURCES; break; } LSCCB_INITIALIZE(Ccb, CurSrbSequence); Ccb->OperationCode = CCB_OPCODE_UPDATE; Ccb->DataBuffer = LurnUpdate; Ccb->DataBufferLength = sizeof(LURN_UPDATE); LSCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED); // Ioctl Srb will complete asynchronously. Ccb->Srb = Srb; InterlockedIncrement(&HwDeviceExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension); LurnUpdate->UpdateClass = LURN_UPDATECLASS_WRITEACCESS_USERID; KDPrint(3,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: going to default LuExtention 0.\n")); status = LurRequest( HwDeviceExtension->LURs[0], // default: 0. Ccb ); if(!NT_SUCCESS(status)) { KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: LurnRequest() failed.\n")); NDScsiLogError( HwDeviceExtension, Srb, Srb->PathId, Srb->TargetId, Srb->Lun, NDASSCSI_IO_UPGRADEIOCTL_FAIL, EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_UPGRADEIOCTL, 0) ); LSCcbFree(Ccb); ExFreePoolWithTag(LurnUpdate, LSMP_PTAG_IOCTL); status = STATUS_SUCCESS; srbStatus = SRB_STATUS_INVALID_REQUEST; } else { status = STATUS_PENDING; } break; } case LANSCSIMINIPORT_IOCTL_ADD_TARGET: { PLANSCSI_ADD_TARGET_DATA AddTargetData; PLURELATION_DESC LurDesc; LONG LurDescLength; LONG LurnCnt; AddTargetData = (PLANSCSI_ADD_TARGET_DATA)srbIoctlBuffer; LurnCnt = AddTargetData->ulNumberOfUnitDiskList; LurDescLength = sizeof(LURELATION_DESC) + // LURELATION_DESC (sizeof(LURELATION_NODE_DESC) + sizeof(LONG) * (LurnCnt-1)) * // LURELATION_NODE_DESC (LurnCnt - 1); // // Allocate LUR Descriptor // It will be freed in the worker routine. // LurDesc = (PLURELATION_DESC)ExAllocatePoolWithTag(NonPagedPool, LurDescLength, LSMP_PTAG_IOCTL); if(LurDesc == NULL) { srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; break; } // Pass Adapter max request block as LUR max request blocks status = LurTranslateAddTargetDataToLURDesc( AddTargetData, HwDeviceExtension->AdapterMaxBlocksPerRequest, LurDescLength, LurDesc ); if(NT_SUCCESS(status)) { ASSERT(LurDescLength>0); status = AddNewDeviceToMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence, LurDesc); } } case LANSCSIMINIPORT_IOCTL_ADD_DEVICE: { PLURELATION_DESC LurDesc; LurDesc = (PLURELATION_DESC)srbIoctlBuffer; status = AddNewDeviceToMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence, LurDesc); break; } case LANSCSIMINIPORT_IOCTL_REMOVE_DEVICE: { status = RemoveDeviceFromMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence); break; } case LANSCSIMINIPORT_IOCTL_REMOVE_TARGET: { PLANSCSI_REMOVE_TARGET_DATA RemoveTargetData; RemoveTargetData = (PLANSCSI_REMOVE_TARGET_DATA)srbIoctlBuffer; status = RemoveDeviceFromMiniport(HwDeviceExtension, NULL, Srb, CurSrbSequence); break; } case LANSCSIMINIPORT_IOCTL_NOOP: { PCCB Ccb; // // Query to the LUR // status = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LSCcbAllocate() failed.\n")); break; } LSCCB_INITIALIZE(Ccb, CurSrbSequence); Ccb->OperationCode = CCB_OPCODE_NOOP; LSCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED); Ccb->Srb = Srb; LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension); KDPrint(3,("going to default LuExtention 0.\n")); InterlockedIncrement(&HwDeviceExtension->RequestExecuting); LsuIncrementTdiClientInProgress(); status = LurRequest( HwDeviceExtension->LURs[0], // default: 0. Ccb ); if(!NT_SUCCESS(status)) { srbStatus = SRB_STATUS_ERROR; status = STATUS_SUCCESS; KDPrint(1,("LurRequest() failed.\n")); break; } srbStatus = SRB_STATUS_SUCCESS; status = STATUS_PENDING; break; } case LANSCSIMINIPORT_IOCTL_GET_VERSION: { PLSMPIOCTL_DRVVER version = (PLSMPIOCTL_DRVVER)srbIoctlBuffer; version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; srbStatus = SRB_STATUS_SUCCESS; status = STATUS_SUCCESS; break; } default: KDPrint(2,("Control Code (%x)\n", controlCode)); srbStatus = SRB_STATUS_INVALID_REQUEST; status = STATUS_MORE_PROCESSING_REQUIRED; } Srb->SrbStatus = srbStatus; return status; }
UCHAR SrbIoctlGetDVDSTatus( PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, PMINIPORT_LU_EXTENSION LuExtension, ULONG OutputBufferLength, PUCHAR OutputBuffer, PNTSTATUS NtStatus, ULONG CurSrbSequence ) { UCHAR status; PCCB Ccb; NTSTATUS ntStatus; PBUSENUM_DVD_STATUS DvdStatusInfo = (PBUSENUM_DVD_STATUS)OutputBuffer; BYTE LurBuffer[sizeof(LURN_DVD_STATUS)]; PLURN_DVD_STATUS pDvdStatusHeader; UNREFERENCED_PARAMETER(LuExtension); KDPrint(1,("\n")); if(OutputBufferLength < sizeof(BUSENUM_DVD_STATUS)) { KDPrint(1,("Too small output buffer\n")); *NtStatus = STATUS_BUFFER_TOO_SMALL; status = SRB_STATUS_INVALID_REQUEST; return status; } // // Query to the LUR // ntStatus = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("LSCcbAllocate() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; return status; } LSCCB_INITIALIZE(Ccb, CurSrbSequence); Ccb->OperationCode = CCB_OPCODE_DVD_STATUS; LSCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED); Ccb->DataBuffer = LurBuffer; Ccb->DataBufferLength = sizeof(LURN_DVD_STATUS); pDvdStatusHeader = (PLURN_DVD_STATUS)LurBuffer; pDvdStatusHeader->Length = sizeof(LURN_DVD_STATUS); KDPrint(3,("going to default LUR 0.\n")); ntStatus = LurRequest( HwDeviceExtension->LURs[0], // default: 0. Ccb ); if(!NT_SUCCESS(ntStatus)) { LSCcbFree(Ccb); KDPrint(1,("LurnRequest() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; return status; } // // Set return values. // KDPrint(1,("Last Access Time :%I64d\n",pDvdStatusHeader->Last_Access_Time.QuadPart)); KDPrint(1,("Result %d\n",pDvdStatusHeader->Status)); DvdStatusInfo->Status = pDvdStatusHeader->Status; *NtStatus = STATUS_SUCCESS; return SRB_STATUS_SUCCESS; }
UCHAR SrbIoctlQueryInfo( PMINIPORT_DEVICE_EXTENSION HwDeviceExtension, PMINIPORT_LU_EXTENSION LuExtension, PLSMPIOCTL_QUERYINFO QueryInfo, ULONG OutputBufferLength, PUCHAR OutputBuffer, PNTSTATUS NtStatus, ULONG CurSrbSequence ) { UCHAR status; PCCB Ccb; NTSTATUS ntStatus; KIRQL oldIrql; UNREFERENCED_PARAMETER(LuExtension); status = SRB_STATUS_SUCCESS; switch(QueryInfo->InfoClass) { case LsmpAdapterInformation: { PLSMPIOCTL_ADAPTERINFO adapter = (PLSMPIOCTL_ADAPTERINFO)OutputBuffer; KDPrint(1,("LsmpAdapterInformation\n")); if(OutputBufferLength < sizeof(LSMPIOCTL_ADAPTERINFO)) { KDPrint(1,("Too small output buffer. OutputBufferLength:%d\n", OutputBufferLength)); *NtStatus = STATUS_BUFFER_TOO_SMALL; status = SRB_STATUS_INVALID_REQUEST; break; } adapter->Length = sizeof(LSMPIOCTL_ADAPTERINFO); adapter->Adapter.SlotNo = HwDeviceExtension->SlotNumber; adapter->Adapter.Length = sizeof(LSMP_ADAPTER); adapter->Adapter.InitiatorId = HwDeviceExtension->InitiatorId; adapter->Adapter.NumberOfBuses = HwDeviceExtension->NumberOfBuses; adapter->Adapter.MaximumNumberOfTargets = HwDeviceExtension->MaximumNumberOfTargets; adapter->Adapter.MaximumNumberOfLogicalUnits= HwDeviceExtension->MaximumNumberOfLogicalUnits; adapter->Adapter.MaxBlocksPerRequest = HwDeviceExtension->AdapterMaxBlocksPerRequest; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); adapter->Adapter.Status = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); *NtStatus = STATUS_SUCCESS; status = SRB_STATUS_SUCCESS; break; } case LsmpPrimaryUnitDiskInformation: { PLSMPIOCTL_PRIMUNITDISKINFO primUnitDisk = (PLSMPIOCTL_PRIMUNITDISKINFO)OutputBuffer; PLUR_QUERY LurQuery; PLURN_PRIMARYINFORMATION LurPrimaryInfo; BYTE LurBuffer[SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION))]; ACCESS_MASK DesiredAccess; KDPrint(1,("LsmpPrimaryUnitDiskInformation\n")); if(OutputBufferLength < sizeof(LSMPIOCTL_PRIMUNITDISKINFO)) { KDPrint(1,("Too small output buffer\n")); *NtStatus = STATUS_BUFFER_TOO_SMALL; status = SRB_STATUS_INVALID_REQUEST; break; } // // Query to the LUR // ntStatus = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("LSCcbAllocate() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; break; } LSCCB_INITIALIZE(Ccb, CurSrbSequence); Ccb->OperationCode = CCB_OPCODE_QUERY; LSCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED); Ccb->DataBuffer = LurBuffer; Ccb->DataBufferLength = sizeof(LURN_PRIMARYINFORMATION); LurQuery = (PLUR_QUERY)LurBuffer; LurQuery->InfoClass = LurPrimaryLurnInformation; LurQuery->Length = SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION)); LurQuery->QueryDataLength = 0; LurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(LurQuery); KDPrint(3,("going to default LuExtention 0.\n")); if(HwDeviceExtension->LURs[0] == NULL || HwDeviceExtension->LURCount == 0) { LSCcbFree(Ccb); *NtStatus = STATUS_INVALID_PARAMETER; status = SRB_STATUS_INVALID_REQUEST; break; } ntStatus = LurRequest( HwDeviceExtension->LURs[0], // default: 0. Ccb ); DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess; if(!NT_SUCCESS(ntStatus)) { LSCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; break; } // // Set return values. // primUnitDisk->Length = sizeof(LSMPIOCTL_PRIMUNITDISKINFO); primUnitDisk->UnitDisk.Length = sizeof(LSMP_UNITDISK); // // Adapter information // primUnitDisk->EnabledTime.QuadPart = HwDeviceExtension->EnabledTime.QuadPart; primUnitDisk->Adapter.SlotNo = HwDeviceExtension->SlotNumber; primUnitDisk->Adapter.Length = sizeof(LSMP_ADAPTER); primUnitDisk->Adapter.InitiatorId = HwDeviceExtension->InitiatorId; primUnitDisk->Adapter.NumberOfBuses = HwDeviceExtension->NumberOfBuses; primUnitDisk->Adapter.MaximumNumberOfTargets = HwDeviceExtension->MaximumNumberOfTargets; primUnitDisk->Adapter.MaximumNumberOfLogicalUnits = HwDeviceExtension->MaximumNumberOfLogicalUnits; primUnitDisk->Adapter.MaxBlocksPerRequest = HwDeviceExtension->AdapterMaxBlocksPerRequest; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); primUnitDisk->Adapter.Status = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); // // LUR information ( Scsi LU information ) // primUnitDisk->Lur.Length = sizeof(LSMP_LUR); primUnitDisk->Lur.DevType = HwDeviceExtension->LURs[0]->DevType; primUnitDisk->Lur.TargetId = HwDeviceExtension->LURs[0]->LurId[1]; primUnitDisk->Lur.Lun = HwDeviceExtension->LURs[0]->LurId[2]; primUnitDisk->Lur.LurnCnt = HwDeviceExtension->LURs[0]->NodeCount; primUnitDisk->Lur.DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess; primUnitDisk->Lur.GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess; primUnitDisk->Lur.LowestHwVer = HwDeviceExtension->LURs[0]->LowestHwVer; // // Unit device // primUnitDisk->UnitDisk.UnitDiskId = LurPrimaryInfo->PrimaryLurn.UnitDiskId; primUnitDisk->UnitDisk.DesiredAccess = DesiredAccess; primUnitDisk->UnitDisk.GrantedAccess = LurPrimaryInfo->PrimaryLurn.AccessRight; RtlCopyMemory( primUnitDisk->UnitDisk.UserID, &LurPrimaryInfo->PrimaryLurn.UserID, sizeof(primUnitDisk->UnitDisk.UserID) ); RtlCopyMemory( primUnitDisk->UnitDisk.Password, &LurPrimaryInfo->PrimaryLurn.Password, sizeof(primUnitDisk->UnitDisk.Password) ); RtlCopyMemory( &primUnitDisk->UnitDisk.NetDiskAddress, &LurPrimaryInfo->PrimaryLurn.NetDiskAddress, sizeof(TA_LSTRANS_ADDRESS) ); RtlCopyMemory( &primUnitDisk->UnitDisk.BindingAddress, &LurPrimaryInfo->PrimaryLurn.BindingAddress, sizeof(TA_LSTRANS_ADDRESS) ); primUnitDisk->UnitDisk.UnitBlocks = (UINT32)LurPrimaryInfo->PrimaryLurn.UnitBlocks; primUnitDisk->UnitDisk.SlotNo = HwDeviceExtension->SlotNumber; break; } case LsmpAdapterLurInformation: { PLSMPIOCTL_ADAPTERLURINFO info = (PLSMPIOCTL_ADAPTERLURINFO)OutputBuffer; PLSMP_LURN_FULL unitDisk; PLUR_QUERY LurQuery; PLURN_ENUM_INFORMATION LurnEnumInfo; UINT32 LurnEnumInfoLen; PLURN_INFORMATION lurnInformation; ACCESS_MASK DesiredAccess; ACCESS_MASK GrantedAccess; ULONG idx_lurn; UINT32 returnLength; KDPrint(1,("LsmpAdapterLurInformation\n")); if(OutputBufferLength < FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks)) { KDPrint(1,("PDOSLOTLIST: Buffer size is less than required %d bytes\n", FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks))); *NtStatus = STATUS_INVALID_PARAMETER; status = SRB_STATUS_INVALID_REQUEST; break; } returnLength = FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks); // // Adapter information // info->EnabledTime.QuadPart = HwDeviceExtension->EnabledTime.QuadPart; info->Adapter.SlotNo = HwDeviceExtension->SlotNumber; info->Adapter.Length = sizeof(LSMP_ADAPTER); info->Adapter.InitiatorId = HwDeviceExtension->InitiatorId; info->Adapter.NumberOfBuses = HwDeviceExtension->NumberOfBuses; info->Adapter.MaximumNumberOfTargets = HwDeviceExtension->MaximumNumberOfTargets; info->Adapter.MaximumNumberOfLogicalUnits = HwDeviceExtension->MaximumNumberOfLogicalUnits; info->Adapter.MaxBlocksPerRequest = HwDeviceExtension->AdapterMaxBlocksPerRequest; ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql); info->Adapter.Status = HwDeviceExtension->AdapterStatus; RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql); // // LUR information ( Scsi LU information ) // if(!HwDeviceExtension->LURs[0]) { KDPrint(1,("No LUR exists.\n")); *NtStatus = STATUS_INVALID_PARAMETER; status = SRB_STATUS_INVALID_REQUEST; break; } info->Lur.Length = sizeof(LSMP_LUR); info->Lur.DevType = HwDeviceExtension->LURs[0]->DevType; info->Lur.TargetId = HwDeviceExtension->LURs[0]->LurId[1]; info->Lur.Lun = HwDeviceExtension->LURs[0]->LurId[2]; info->Lur.LurnCnt = HwDeviceExtension->LURs[0]->NodeCount; info->Lur.LowestHwVer = HwDeviceExtension->LURs[0]->LowestHwVer; info->UnitDiskCnt = info->Lur.LurnCnt; ASSERT(HwDeviceExtension->LURs[0]->NodeCount >= 1); info->Length = sizeof(LSMPIOCTL_ADAPTERLURINFO) + sizeof(LSMP_LURN_FULL) * (HwDeviceExtension->LURs[0]->NodeCount - 1); // // Lurn information. // Query to the LUR // unitDisk = info->UnitDisks; // // allocate a CCB // ntStatus = LSCcbAllocate(&Ccb); if(!NT_SUCCESS(ntStatus)) { KDPrint(1,("LSCcbAllocate() failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; break; } // // initialize query CCB // LSCCB_INITIALIZE(Ccb, CurSrbSequence); Ccb->OperationCode = CCB_OPCODE_QUERY; LSCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED); ASSERT(info->Lur.LurnCnt >= 1); LurnEnumInfoLen = sizeof(LURN_ENUM_INFORMATION) + sizeof(LURN_INFORMATION) * (info->Lur.LurnCnt-1); LUR_QUERY_INITIALIZE(LurQuery, LurEnumerateLurn, 0, LurnEnumInfoLen); if(!LurQuery) { LSCcbFree(Ccb); KDPrint(1,("allocating DataBuffer failed.\n")); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; break; } Ccb->DataBuffer = LurQuery; Ccb->DataBufferLength = LurQuery->Length; LurnEnumInfo = (PLURN_ENUM_INFORMATION)LUR_QUERY_INFORMATION(LurQuery); // // send the CCB down // KDPrint(3,("going to default LuExtention 0.\n")); ntStatus = LurRequest( HwDeviceExtension->LURs[0], // default: 0. Ccb ); DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess; GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess; if(!NT_SUCCESS(ntStatus)) { LSCcbFree(Ccb); KDPrint(1,("LurRequest() failed.\n")); ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL); *NtStatus = STATUS_INSUFFICIENT_RESOURCES; status = SRB_STATUS_INVALID_REQUEST; break; } info->Lur.DesiredAccess = DesiredAccess; info->Lur.GrantedAccess = GrantedAccess; // // Set return values for each LURN. // for(idx_lurn = 0; idx_lurn < info->UnitDiskCnt; idx_lurn++) { // // Add one Unitdisk to return bytes and check the user buffer size. // returnLength += sizeof(LSMP_LURN_FULL); if(returnLength > OutputBufferLength) { continue; } unitDisk = info->UnitDisks + idx_lurn; lurnInformation = LurnEnumInfo->Lurns + idx_lurn; unitDisk->Length = sizeof(LSMP_LURN_FULL); unitDisk->UnitDiskId = lurnInformation->UnitDiskId; unitDisk->AccessRight = lurnInformation->AccessRight; unitDisk->UnitBlocks = lurnInformation->UnitBlocks; unitDisk->StatusFlags = lurnInformation->StatusFlags; unitDisk->LurnId = lurnInformation->LurnId; unitDisk->LurnType = lurnInformation->LurnType; unitDisk->StatusFlags = lurnInformation->StatusFlags; RtlCopyMemory( unitDisk->UserID, &lurnInformation->UserID, sizeof(unitDisk->UserID) ); RtlCopyMemory( unitDisk->Password, &lurnInformation->Password, sizeof(unitDisk->Password) ); RtlCopyMemory( &unitDisk->NetDiskAddress, &lurnInformation->NetDiskAddress, sizeof(TA_LSTRANS_ADDRESS) ); RtlCopyMemory( &unitDisk->BindingAddress, &lurnInformation->BindingAddress, sizeof(TA_LSTRANS_ADDRESS) ); } if(returnLength > OutputBufferLength) { KDPrint(1,("Output buffer too small. outbuffer:%u required:%u\n", OutputBufferLength, returnLength)); ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL); *NtStatus = STATUS_BUFFER_TOO_SMALL; status = SRB_STATUS_SUCCESS; break; } ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL); *NtStatus = STATUS_SUCCESS; status = SRB_STATUS_SUCCESS; break; } // // User application can use this information instead of LANSCSIMINIPORT_IOCTL_GET_VERSION. // case LsmpDriverVersion: // 5 { PLSMPIOCTL_DRVVER version = (PLSMPIOCTL_DRVVER)OutputBuffer; version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; *NtStatus = STATUS_SUCCESS; status = SRB_STATUS_SUCCESS; break; } default: KDPrint(1,("Invalid Information Class!!\n")); *NtStatus = STATUS_INVALID_PARAMETER; status = SRB_STATUS_INVALID_REQUEST; } return status; }