/*++ Private so we can later expose to someone wanting to use a preallocated buffer --*/ NTSTATUS NTAPI CdRompGetConfiguration( IN PDEVICE_OBJECT Fdo, IN PGET_CONFIGURATION_HEADER Buffer, IN ULONG BufferSize, OUT PULONG ValidBytes, IN FEATURE_NUMBER StartingFeature, IN ULONG RequestedType ) { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension; PCDROM_DATA cdData; SCSI_REQUEST_BLOCK srb; PCDB cdb; ULONG_PTR returned; NTSTATUS status; PAGED_CODE(); ASSERT(Buffer); ASSERT(ValidBytes); *ValidBytes = 0; returned = 0; RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK)); RtlZeroMemory(Buffer, BufferSize); fdoExtension = Fdo->DeviceExtension; cdData = (PCDROM_DATA)(fdoExtension->CommonExtension.DriverData); if (TEST_FLAG(cdData->HackFlags, CDROM_HACK_BAD_GET_CONFIG_SUPPORT)) { return STATUS_INVALID_DEVICE_REQUEST; } srb.TimeOutValue = CDROM_GET_CONFIGURATION_TIMEOUT; srb.CdbLength = 10; cdb = (PCDB)srb.Cdb; cdb->GET_CONFIGURATION.OperationCode = SCSIOP_GET_CONFIGURATION; cdb->GET_CONFIGURATION.RequestType = (UCHAR)RequestedType; cdb->GET_CONFIGURATION.StartingFeature[0] = (UCHAR)(StartingFeature >> 8); cdb->GET_CONFIGURATION.StartingFeature[1] = (UCHAR)(StartingFeature & 0xff); cdb->GET_CONFIGURATION.AllocationLength[0] = (UCHAR)(BufferSize >> 8); cdb->GET_CONFIGURATION.AllocationLength[1] = (UCHAR)(BufferSize & 0xff); status = ClassSendSrbSynchronous(Fdo, &srb, Buffer, BufferSize, FALSE); returned = srb.DataTransferLength; KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdromGetConfiguration: Status was %x\n", status)); if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) { // // if returned more than can be stored in a ULONG, return false // if (returned > (ULONG)(-1)) { return STATUS_UNSUCCESSFUL; } ASSERT(returned <= BufferSize); *ValidBytes = (ULONG)returned; return STATUS_SUCCESS; } else { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdromGetConfiguration: failed %x\n", status)); return status; } ASSERT(FALSE); return STATUS_UNSUCCESSFUL; }
/*++ NOT DOCUMENTED YET - may be called at up to DISPATCH_LEVEL if memory is non-paged --*/ PVOID NTAPI CdRomFindFeaturePage( IN PGET_CONFIGURATION_HEADER FeatureBuffer, IN ULONG Length, IN FEATURE_NUMBER Feature ) { PUCHAR buffer; PUCHAR limit; if (Length < sizeof(GET_CONFIGURATION_HEADER) + sizeof(FEATURE_HEADER)) { return NULL; } // // set limit to point to first illegal address // limit = (PUCHAR)FeatureBuffer; limit += Length; // // set buffer to point to first page // buffer = FeatureBuffer->Data; // // loop through each page until we find the requested one, or // until it's not safe to access the entire feature header // (if equal, have exactly enough for the feature header) // while (buffer + sizeof(FEATURE_HEADER) <= limit) { PFEATURE_HEADER header = (PFEATURE_HEADER)buffer; FEATURE_NUMBER thisFeature; thisFeature = (header->FeatureCode[0] << 8) | (header->FeatureCode[1]); if (thisFeature == Feature) { PUCHAR temp; // // if don't have enough memory to safely access all the feature // information, return NULL // temp = buffer; temp += sizeof(FEATURE_HEADER); temp += header->AdditionalLength; if (temp > limit) { // // this means the transfer was cut-off, an insufficiently // small buffer was given, or other arbitrary error. since // it's not safe to view the amount of data (even though // the header is safe) in this feature, pretend it wasn't // transferred at all... // KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "Feature %x exists, but not safe to access all its " "data. returning NULL\n", Feature)); return NULL; } else { return buffer; } } if (header->AdditionalLength % 4) { ASSERT(!"Feature page AdditionalLength field must be integral multiple of 4!\n"); return NULL; } buffer += sizeof(FEATURE_HEADER); buffer += header->AdditionalLength; } return NULL; }
VOID NTAPI CdRompFlushDelayedList( IN PDEVICE_OBJECT Fdo, IN PCDROM_MMC_EXTENSION MmcData, IN NTSTATUS Status, IN BOOLEAN CalledFromWorkItem ) { PSINGLE_LIST_ENTRY list; PIRP irp; // NOTE - REF #0002 // // need to set the new state first to prevent deadlocks. // this is only done from the workitem, to prevent any // edge cases where we'd "lose" the UpdateRequired // // then, must ignore the state, since it's not guaranteed to // be the same any longer. the only thing left is to handle // all the delayed irps by flushing the queue and sending them // back onto the StartIo queue for the device. // if (CalledFromWorkItem) { LONG oldState; LONG newState; if (NT_SUCCESS(Status)) { newState = CdromMmcUpdateComplete; } else { newState = CdromMmcUpdateRequired; } oldState = InterlockedCompareExchange(&MmcData->UpdateState, newState, CdromMmcUpdateStarted); ASSERT(oldState == CdromMmcUpdateStarted); } else { // // just flushing the queue if not called from the workitem, // and we don't want to ever fail the queue in those cases. // ASSERT(NT_SUCCESS(Status)); } list = ExInterlockedFlushSList(&MmcData->DelayedIrps); // if this assert fires, it means that we have started // a workitem when the previous workitem took the delayed // irp. if this happens, then the logic in HACKHACK #0002 // is either flawed or the rules set within are not being // followed. this would require investigation. ASSERT(list != NULL); // // now either succeed or fail all the delayed irps, according // to the update status. // while (list != NULL) { irp = (PIRP)( ((PUCHAR)list) - FIELD_OFFSET(IRP, Tail.Overlay.DriverContext[0]) ); list = list->Next; irp->Tail.Overlay.DriverContext[0] = 0; irp->Tail.Overlay.DriverContext[1] = 0; irp->Tail.Overlay.DriverContext[2] = 0; irp->Tail.Overlay.DriverContext[3] = 0; if (NT_SUCCESS(Status)) { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Re-sending delayed irp %p\n", irp)); IoStartPacket(Fdo, irp, NULL, NULL); } else { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Failing delayed irp %p with " " status %x\n", irp, Status)); irp->IoStatus.Information = 0; irp->IoStatus.Status = Status; ClassReleaseRemoveLock(Fdo, irp); IoCompleteRequest(irp, IO_CD_ROM_INCREMENT); } } // while (list) return; }
RPSTATUS EventCheck( IN PUNICODE_STRING pusCriminal, IN PUNICODE_STRING pusVictim, IN PEPROCESS pCriminalEproc, IN PEPROCESS pVictimEproc, IN ULONG ulCrimeType, IN ULONG_PTR ulpExtraInfo ) /*++ Routine Description: 处理检测到的违规操作 Arguments: pusCriminal - 违规者名字 pusVictim - 受害者名字 pCriminalEproc - 违规者进程 pVictimEproc - 受害者进程 ulCrimeType - 违规类型 ulpExtraInfo - 额外信息,根据违规类型的不同而不同 Return Value: 允许放行返回 RP_STATUS_OK,拒绝该操作返回 RP_STATUS_ERR Author: Fypher --*/ { PEVENTDATA pEvtData; ULONG ulJudgment; RPSTATUS RpStatus = RP_STATUS_NOT_CLEAR; PAGED_CODE(); if (!g_pProtected) // no ring3 return RP_STATUS_OK; if (!IsMajorProtected(ulCrimeType)) // protect off return RP_STATUS_OK; if (IsInWhiteBlackHashTable(pusCriminal, CRIME_MAJOR_ALL, NODE_TYPE_WHITE)) // Super White List return RP_STATUS_OK; if (IsInWhiteBlackHashTable(pusCriminal, ulCrimeType, NODE_TYPE_WHITE)) // white list RpStatus = RP_STATUS_OK; else if (IsInWhiteBlackHashTable(pusCriminal, ulCrimeType, NODE_TYPE_BLACK)) // black list RpStatus = RP_STATUS_ERR; if (pCriminalEproc && pCriminalEproc == pVictimEproc) // Self xx return RP_STATUS_OK; if (g_ulEventDataCount > MAX_EVENT_IN_LIST) { // too many KdPrintEx((DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "EventCheck! g_ulEventDataCount: %d\r\n", g_ulEventDataCount)); return RP_STATUS_ERR; } switch (ulCrimeType & CRIME_MAJOR_MASK) { // // CRIME_MAJOR_FILE // case CRIME_MAJOR_FILE: if (!IsInWhiteBlackHashTable(pusVictim, CRIME_MAJOR_FILE, NODE_TYPE_BLACK)) return RP_STATUS_OK; break; // // CRIME_MAJOR_PROC // case CRIME_MAJOR_PROC: if (pVictimEproc == g_pProtected) // self protect return RP_STATUS_ERR; // only for self protect if (ulCrimeType == CRIME_MINOR_NtOpenProcess || ulCrimeType == CRIME_MINOR_NtOpenThread || ulCrimeType == CRIME_MINOR_NtAssignProcessToJobObject) { return RP_STATUS_OK; } break; // // CRIME_MAJOR_REG // case CRIME_MAJOR_REG: break; // // CRIME_MAJOR_SYS // case CRIME_MAJOR_SYS: if (ulCrimeType == CRIME_MINOR_NtDuplicateObject) { if (g_pProtected == (PEPROCESS)ulpExtraInfo) { // selfprotect return RP_STATUS_ERR; } } else if (ulCrimeType == CRIME_MINOR_NtOpenSection) { if (/*g_pPhysicalMemoryObj && */g_pPhysicalMemoryObj != (PVOID)ulpExtraInfo) return RP_STATUS_OK; } break; default: KdPrintEx(( DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "EventCheck! How did I get here! %x\r\n", ulCrimeType )); break; } if (RpStatus != RP_STATUS_NOT_CLEAR) return RpStatus; pEvtData = BuildEventData(pusCriminal, pusVictim, pCriminalEproc, pVictimEproc, ulCrimeType, ulpExtraInfo); if (!pEvtData) return RP_STATUS_ERR; PushEvent(pEvtData); KeWaitForSingleObject(&pEvtData->evt, Executive, KernelMode, FALSE, NULL); ulJudgment = pEvtData->ulJudgment; DestroyEventData(pEvtData); if (ulJudgment & JUDGMENT_ACCEPT) { if (ulJudgment & JUDGMENT_ALWAYS) { AddToWhiteBlackHashTable(pusCriminal, ulCrimeType, NODE_TYPE_WHITE); } return RP_STATUS_OK; } else if (ulJudgment & JUDGMENT_REFUSE) { if (ulJudgment & JUDGMENT_ALWAYS) { AddToWhiteBlackHashTable(pusCriminal, ulCrimeType, NODE_TYPE_BLACK); } return RP_STATUS_ERR; } // never reaches here return RP_STATUS_ERR; }
VOID NTAPI CdRomUpdateMmcDriveCapabilities( IN PDEVICE_OBJECT Fdo, IN PVOID Context ) { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension; PCDROM_DATA cdData = fdoExtension->CommonExtension.DriverData; PCDROM_MMC_EXTENSION mmcData = &(cdData->Mmc); PIO_STACK_LOCATION thisStack = IoGetCurrentIrpStackLocation(mmcData->CapabilitiesIrp); PSCSI_REQUEST_BLOCK srb = &(mmcData->CapabilitiesSrb); NTSTATUS status; ASSERT(Context == NULL); // // NOTE: a remove lock is unnecessary, since the delayed irp // will have said lock held for itself, preventing a remove. // CdRomPrepareUpdateCapabilitiesIrp(Fdo); ASSERT(thisStack->Parameters.Others.Argument1 == Fdo); ASSERT(thisStack->Parameters.Others.Argument2 == mmcData->CapabilitiesBuffer); ASSERT(thisStack->Parameters.Others.Argument3 == &(mmcData->CapabilitiesSrb)); mmcData->WriteAllowed = FALSE; // default to read-only // // set max retries, and also allow volume verify override based on // original (delayed) irp // thisStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; // // send to self... note that SL_OVERRIDE_VERIFY_VOLUME is not required, // as this is IRP_MJ_INTERNAL_DEVICE_CONTROL // IoCallDriver(commonExtension->LowerDeviceObject, mmcData->CapabilitiesIrp); KeWaitForSingleObject(&mmcData->CapabilitiesEvent, Executive, KernelMode, FALSE, NULL); status = mmcData->CapabilitiesIrp->IoStatus.Status; if (!NT_SUCCESS(status)) { goto FinishDriveUpdate; } // // we've updated the feature set, so update whether or not reads and writes // are allowed or not. // KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Succeeded " "--------------------" "--------------------\n")); /*++ NOTE: It is important to only use srb->DataTransferLength worth of data at this point, since the bufferSize is what is *available* to use, not what was *actually* used. --*/ #if DBG CdRompPrintAllFeaturePages(mmcData->CapabilitiesBuffer, srb->DataTransferLength); #endif // DBG // // update whether or not writes are allowed. this is currently defined // as requiring TargetDefectManagement and RandomWritable features // { PFEATURE_HEADER defectHeader; PFEATURE_HEADER writableHeader; defectHeader = CdRomFindFeaturePage(mmcData->CapabilitiesBuffer, srb->DataTransferLength, FeatureDefectManagement); writableHeader = CdRomFindFeaturePage(mmcData->CapabilitiesBuffer, srb->DataTransferLength, FeatureRandomWritable); if ((defectHeader != NULL) && (writableHeader != NULL) && (defectHeader->Current) && (writableHeader->Current)) { // // this should be the *ONLY* place writes are set to allowed // KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => Writes *allowed*\n")); mmcData->WriteAllowed = TRUE; } else { if (defectHeader == NULL) { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => No writes - %s = %s\n", "defect management", "DNE")); } else { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => No writes - %s = %s\n", "defect management", "Not Current")); } if (writableHeader == NULL) { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => No writes - %s = %s\n", "sector writable", "DNE")); } else { KdPrintEx((DPFLTR_CDROM_ID, CdromDebugFeatures, "CdRomUpdateMmc => No writes - %s = %s\n", "sector writable", "Not Current")); } } // end of feature checking } // end of check for writability // // update the cached partition table information // // NOTE: THIS WILL CURRENTLY CAUSE A DEADLOCK! // // ISSUE-2000/06/20-henrygab - partition support not implemented // IoReadPartitionTable must be done // at PASSIVE level, requiring a thread // or worker item or other such method. // #if 0 status = IoReadPartitionTable(Fdo, 1 << fdoExtension->SectorShift, TRUE, &mmcData->PartitionList); if (!NT_SUCCESS(status)) { goto FinishDriveUpdate; } #endif status = STATUS_SUCCESS; FinishDriveUpdate: CdRompFlushDelayedList(Fdo, mmcData, status, TRUE); return; }
// // Io events callbacks. // VOID MarsEvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: This event is called when the framework receives IRP_MJ_DEVICE_CONTROL requests from the system. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. OutputBufferLength - length of the request's output buffer, if an output buffer is available. InputBufferLength - length of the request's input buffer, if an input buffer is available. IoControlCode - the driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { PFDO_DATA fdoData = NULL; WDFDEVICE device; NTSTATUS status = STATUS_SUCCESS; PVOID inBuffer = NULL, outBuffer = NULL; size_t bytesReturned = 0; size_t size = 0; PAGED_CODE(); //DbgPrint(("Started MarsEvtIODeviceControl\n")); device = WdfIoQueueGetDevice(Queue); fdoData = MarsFdoGetData(device); //Gets device context // // Get the ioctl input & output buffers // if (InputBufferLength != 0) { status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inBuffer, &size); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } } if (OutputBufferLength != 0) { status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outBuffer, &size); if (!NT_SUCCESS(status)) { WdfRequestComplete(Request, status); return; } } switch (IoControlCode) { case IOCTL_MARS_GET_DRIVER_VERSION: if (OutputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PUSHORT)outBuffer = fdoData->DriverVersion; bytesReturned = sizeof(USHORT); break; case IOCTL_MARS_GET_FUNCTION_NUMBER: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PUCHAR)outBuffer = fdoData->FunctionNumber; bytesReturned = sizeof(UCHAR); break; case IOCTL_MARS_GET_FUNCTION_FOCUS: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } *(PUCHAR)outBuffer = fdoData->FunctionFocus; bytesReturned = sizeof(UCHAR); break; case IOCTL_MARS_SET_FUNCTION_FOCUS: if (InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } fdoData->FunctionFocus = *(PUCHAR)inBuffer; break; //--------------------------------------------------- // // SDP_BUS_WIDTH // //--------------------------------------------------- case IOCTL_MARS_GET_BUS_WIDTH: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_BUS_WIDTH, outBuffer, sizeof(UCHAR)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } break; case IOCTL_MARS_SET_BUS_WIDTH: if (InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_BUS_WIDTH, inBuffer, sizeof(UCHAR)); break; //--------------------------------------------------- // // SDP_BUS_CLOCK // //--------------------------------------------------- case IOCTL_MARS_GET_BUS_CLOCK: if (OutputBufferLength < sizeof(ULONG)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_BUS_CLOCK, outBuffer, sizeof(ULONG)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(ULONG); } break; case IOCTL_MARS_SET_BUS_CLOCK: if (InputBufferLength < sizeof(ULONG)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_BUS_CLOCK, inBuffer, sizeof(ULONG)); break; //--------------------------------------------------- // // SDP_FUNCTION_BLOCK_LENGTH // //--------------------------------------------------- case IOCTL_MARS_GET_BLOCKLEN: if (OutputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_FUNCTION_BLOCK_LENGTH, outBuffer, sizeof(SHORT)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(USHORT); } break; case IOCTL_MARS_SET_BLOCKLEN: if (InputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_FUNCTION_BLOCK_LENGTH, inBuffer, sizeof(SHORT)); break; //--------------------------------------------------- // // SDP_FN0_BLOCK_LENGTH // //--------------------------------------------------- case IOCTL_MARS_GET_FN0_BLOCKLEN: if (OutputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_FN0_BLOCK_LENGTH, outBuffer, sizeof(SHORT)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(USHORT); } break; case IOCTL_MARS_SET_FN0_BLOCKLEN: if (InputBufferLength < sizeof(USHORT)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_FN0_BLOCK_LENGTH, inBuffer, sizeof(SHORT)); break; //--------------------------------------------------- // // SDP_BUS_INTERFACE_CONTROL // //--------------------------------------------------- case IOCTL_MARS_GET_BUS_INTERFACE_CONTROL: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_BUS_INTERFACE_CONTROL, outBuffer, sizeof(UCHAR)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } break; case IOCTL_MARS_SET_BUS_INTERFACE_CONTROL: if (InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_BUS_INTERFACE_CONTROL, inBuffer, sizeof(UCHAR)); break; //--------------------------------------------------- // // SDP_FUNCTION_INT_ENABLE // //--------------------------------------------------- case IOCTL_MARS_GET_INT_ENABLE: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioGetProperty(device, SDP_FUNCTION_INT_ENABLE, outBuffer, sizeof(UCHAR)); if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } break; case IOCTL_MARS_SET_INT_ENABLE: if (InputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioSetProperty(device, SDP_FUNCTION_INT_ENABLE, inBuffer, sizeof(UCHAR)); break; //--------------------------------------------------- // // READ/WRITE BYTE // //--------------------------------------------------- case IOCTL_MARS_READ_BYTE: if ((InputBufferLength < sizeof(ULONG)) || (OutputBufferLength < sizeof(UCHAR))) { status = STATUS_BUFFER_TOO_SMALL; break; } status = SdioReadWriteByte(device, fdoData->FunctionFocus, (PUCHAR)outBuffer, *(PULONG)inBuffer, FALSE); if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } break; case IOCTL_MARS_WRITE_BYTE: if ((InputBufferLength < sizeof(ULONG)*2)) {//||(OutputBufferLength < sizeof(UCHAR))) { status = STATUS_BUFFER_TOO_SMALL; break; } // BUGBUG: check for output buffer length status = SdioReadWriteByte(device, fdoData->FunctionFocus, (PUCHAR)(&((PULONG)inBuffer)[1]), *(PULONG)inBuffer, TRUE); // BUGBUG: Return the right size if (NT_SUCCESS(status)) { bytesReturned = sizeof(UCHAR); } break; //--------------------------------------------------- // // Mode settings // //--------------------------------------------------- case IOCTL_MARS_SET_TRANSFER_MODE: bytesReturned = 0; break; case IOCTL_MARS_TOGGLE_MODE: if (OutputBufferLength < sizeof(UCHAR)) { status = STATUS_BUFFER_TOO_SMALL; break; } if (fdoData->DriverVersion < SDBUS_DRIVER_VERSION_2) { status = STATUS_INVALID_DEVICE_REQUEST; break; } fdoData->BlockMode = fdoData->BlockMode ? 0 : 1; *(PUCHAR)outBuffer = fdoData->BlockMode; bytesReturned = sizeof(UCHAR); break; case IOCTL_MARS_TOGGLE_NOISY: if (OutputBufferLength < sizeof(BOOLEAN)) { status = STATUS_BUFFER_TOO_SMALL; break; } NoisyMode = NoisyMode ? 0 : 1; *(PBOOLEAN)outBuffer = NoisyMode; bytesReturned = sizeof(BOOLEAN); if (NoisyMode) { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "MARS: Noisy mode\n")); } else { KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "MARS: Quiet mode\n")); } break; default: NT_ASSERTMSG("Invalid IOCTL request\n", FALSE); status = STATUS_INVALID_DEVICE_REQUEST; } WdfRequestCompleteWithInformation(Request, status, bytesReturned); return; }
VOID TpmEvtIoDeviceControl ( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) { NTSTATUS status; PTPM_CONTEXT TpmContext; WDFDEVICE Device; PAGED_CODE(); Device = WdfIoQueueGetDevice(Queue); TpmContext = GetTpmContext(Device); KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_WARNING_LEVEL, "TpmEvtIoDeviceControl called - IoControlCode: 0x%x \n", IoControlCode)); switch(IoControlCode) { case TPM_CANCEL_COMMAND: status = TpmAbort(TpmContext,StAvailable,StAborting,IdAbort); break; case TPM_TRANSMIT_COMMAND: status = TpmHandleTransmit(Device, Request, OutputBufferLength, InputBufferLength); break; case TPM_SUMBIT_ACPI_COMMAND: if(TpmContext->TpmState != StAvailable) { status = STATUS_CANCELLED; WdfRequestComplete( Request, status); return; } status = TpmHandleSubmitAcpiCommand(Device, Request, OutputBufferLength, InputBufferLength); break; default: KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtIoDeviceControl: Invalid request 0x%x\n",IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; break; } WdfRequestComplete( Request, status); }
NTSTATUS TpmEvtDevicePrepareHardware ( WDFDEVICE Device, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated ) { NTSTATUS status; ULONG ListCount = 0; ULONG MemLen = 0; // ULONG NumberOfBytes; PTPM_CONTEXT TpmContext; PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDesc; ULONG ListIndex; PHYSICAL_ADDRESS MemoryAddr; BOOLEAN bMemAddr = FALSE; PAGED_CODE(); TpmContext = GetTpmContext(Device); KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDevicePrepareHardware (raw count = %u, trans count = %u)\n", WdfCmResourceListGetCount(Resources), WdfCmResourceListGetCount(ResourcesTranslated))); ListIndex = 0; ListCount = WdfCmResourceListGetCount(ResourcesTranslated); if(ListCount) { while(ListIndex < ListCount) { ResourceDesc = WdfCmResourceListGetDescriptor(ResourcesTranslated,ListIndex); if(!ResourceDesc) break; if(ResourceDesc->Type == CmResourceTypePort) { if(TpmContext->UsePortBasedIO) { TpmContext->PortAddr = (PUCHAR)ResourceDesc->u.Port.Start.u.LowPart; } } else if(ResourceDesc->Type == CmResourceTypeMemory && TpmContext->UsePortBasedIO == 0) { MemoryAddr.u.LowPart = ResourceDesc->u.Memory.Start.u.LowPart; MemoryAddr.u.HighPart = ResourceDesc->u.Memory.Start.u.HighPart; MemLen = ResourceDesc->u.Memory.Length; bMemAddr = TRUE; } ListIndex++; } do { if(ListIndex < WdfCmResourceListGetCount( ResourcesTranslated)) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfCmResourceListGetDescriptor failed.\n")); status = STATUS_DEVICE_CONFIGURATION_ERROR; // 0xC0000182; break; } if(TpmContext->UsePortBasedIO) { if(!TpmContext->PortAddr) { if(TpmContext->UsePortBasedIO != TRUE) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_WARNING_LEVEL, "Port I/O resources required but not allocated for Vendor index %u", TpmContext->UsePortBasedIO)); status = STATUS_DEVICE_CONFIGURATION_ERROR; // 0xC0000182; goto Exit; } KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_WARNING_LEVEL, "No resources allocated for Port-based I/O.")); status = STATUS_DEVICE_CONFIGURATION_ERROR; break; } } else { if(!bMemAddr) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "Physical address resource not provided via ACPI; using default address and size.\n")); MemLen = 1024; MemoryAddr.u.LowPart = TPM_DEFAULT_ADDRESS; MemoryAddr.u.HighPart = 0; } if(MemLen < 1024) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "Physical address length provided is too small (%d)\n",MemLen)); status = STATUS_DEVICE_CONFIGURATION_ERROR; //0xC0000182; break; } if(MemoryAddr.u.LowPart != TPM_DEFAULT_ADDRESS || MemoryAddr.u.HighPart) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "Physical address provided is incorrect: 0x%08x`%08x\n",MemoryAddr.u.HighPart,MemoryAddr.u.LowPart)); status = STATUS_DEVICE_CONFIGURATION_ERROR; //0xC0000182; break; } TpmContext->MemAddr = MmMapIoSpace(MemoryAddr,MemLen,MmNonCached); if(!TpmContext->MemAddr) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "MmMapIoSpace couldn't map the TPM device: 0x%x.\n", MemoryAddr.u.LowPart)); status = STATUS_INSUFFICIENT_RESOURCES; //0xC000009A; break; } TpmContext->MemLen = MemLen; } status = TpmSetDefaultTimingValues(TpmContext); if(!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmSetDefaultTimingValues failed with status 0x%x",status)); break; } if(TpmContext->SkipInitCommands) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "Skipping initialization commands\n")); } else { TpmGetTimeoutInfo(TpmContext); TpmGetDurations(TpmContext); // 获取硬件厂商信息 TpmGetManufacturer(TpmContext); } status = TpmVerifyAccessRegister(TpmContext,TpmINB(TpmContext,0),0); if(!NT_SUCCESS(status)) { break; } #if _NT_TARGET_VERSION >= 0x601 status = TpmEntropyInit(TpmContext); #endif } while(FALSE); } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "Physical address resource not provided via ACPI; using default address and size.\n")); } Exit: KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDevicePrepareHardware exited with Status code 0x%x\n",status)); return status; }
NTSTATUS TpmEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) { NTSTATUS status = STATUS_SUCCESS; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks; WDF_OBJECT_ATTRIBUTES DeviceAttributes; WDFDEVICE device; PTPM_CONTEXT TpmContext; WDF_IO_QUEUE_CONFIG IoQueueConfig; WDFQUEUE hQueue; WDF_QUERY_INTERFACE_CONFIG InterfaceConfig; TPM_INTERFACE_STANDARD TpmInterface; WDF_DEVICE_POWER_CAPABILITIES PowerCaps; PAGED_CODE(); UNREFERENCED_PARAMETER( Driver ); RtlZeroMemory(&PnpPowerEventCallbacks,sizeof(PnpPowerEventCallbacks)); RtlZeroMemory(&PowerCaps,sizeof(PowerCaps)); KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDeviceAdd routine PDO: %p (%p)\n", WdfDriverWdmGetDriverObject(Driver))); // // Zero out the PnpPowerCallbacks structure. // WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks); // // These two callbacks set up and tear down hardware state that must be // done every time the device moves in and out of the D0-working state. // PnpPowerEventCallbacks.EvtDeviceD0Entry = TpmEvtDeviceD0Entry; PnpPowerEventCallbacks.EvtDeviceD0Exit = TpmEvtDeviceD0Exit; // // Set Callbacks for any of the functions we are interested in. // If no callback is set, Framework will take the default action // by itself. // PnpPowerEventCallbacks.EvtDevicePrepareHardware = TpmEvtDevicePrepareHardware; PnpPowerEventCallbacks.EvtDeviceReleaseHardware = TpmEvtDeviceReleaseHardware; WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit,&PnpPowerEventCallbacks); // // Specify the context type and size for the device we are about to create. // RtlZeroMemory(&DeviceAttributes,sizeof(DeviceAttributes)); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&DeviceAttributes, TPM_CONTEXT); DeviceAttributes.Size = sizeof(WDF_OBJECT_ATTRIBUTES); DeviceAttributes.SynchronizationScope = WdfSynchronizationScopeInheritFromParent; DeviceAttributes.ExecutionLevel = WdfExecutionLevelPassive; status = WdfDeviceCreate(&DeviceInit,&DeviceAttributes,&device); if(NT_SUCCESS(status)) { TpmContext = GetTpmContext(device); RtlZeroMemory(TpmContext,sizeof(TPM_CONTEXT)); TpmContext->Device = device; TpmContext->AccessRegister = FALSE; KeInitializeSpinLock(&TpmContext->SpinLock); TpmContext->TpmState = StSuspend; TpmInitStateTable(); KeInitializeEvent(&TpmContext->Event,NotificationEvent,TRUE); status = WdfDeviceCreateDeviceInterface(device,&GUID_DEVINTERFACE_TPM,NULL); if(NT_SUCCESS(status)) { WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE( &IoQueueConfig, WdfIoQueueDispatchParallel ); IoQueueConfig.EvtIoDeviceControl = TpmEvtIoDeviceControl; status = WdfIoQueueCreate( device, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &hQueue ); if(NT_SUCCESS(status)) { WDF_DEVICE_POWER_CAPABILITIES_INIT(&PowerCaps); WdfDeviceSetPowerCapabilities(device,&PowerCaps); // TpmGetRegistryFlags(device,TpmContext); // RtlZeroMemory(&TpmInterface,sizeof(TpmInterface)); TpmInterface.InterfaceHeader.Size = sizeof(TpmInterface); TpmInterface.InterfaceHeader.Version = 1; TpmInterface.InterfaceHeader.Context = (PVOID)TpmContext; TpmInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp; TpmInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp; TpmInterface.pfn_TpmSetMorBitState = TpmSetMorBitState; // // Initialize the InterfaceConfig structure. // WDF_QUERY_INTERFACE_CONFIG_INIT( &InterfaceConfig, (PINTERFACE)&TpmInterface, &GUID_TPM_INTERFACE_STANDARD, NULL ); // // Create the interface. // status = WdfDeviceAddQueryInterface( device, &InterfaceConfig ); if(!NT_SUCCESS(status)) { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceAddQueryInterface failed with NTSTATUS 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfIoQueueCreate failed with Status code 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceCreateDeviceInterface failed with Status code 0x%x\n",status)); } } else { KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "WdfDeviceCreate failed with Status code 0x%x\n",status)); } KdPrintEx((DPFLTR_PNPMEM_ID, DPFLTR_INFO_LEVEL, "TpmEvtDeviceAdd exited with Status code 0x%x\n",status)); return status; }
VOID EvtDriverUnload(_In_ WDFDRIVER DriverObject) { DriverObject; KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Driver Unloaded\n")); }