Example #1
0
DWORD FanCtrlRead(PDEVICE_OBJECT pDriverObject, PIRP pIRP)
{
  int i;
  PCHAR pReadBuffer;
  UCHAR uTemp[12];

  // load structure data
  ECCtrlRead(TP_OFF_FANMOD,  &data.uMode);
  ECCtrlRead(TP_OFF_FANSPDL, &data.uSpeedL);
  ECCtrlRead(TP_OFF_FANSPDH, &data.uSpeedH);

  // load temperature sets
  for (i = 0; i < 8; i++) ECCtrlRead(TP_OFF_TEMP0 + i, &uTemp[i]);
  for (i = 0; i < 4; i++) ECCtrlRead(TP_OFF_TEMP1 + i, &uTemp[8 + i]);

  // store only valid data
  for (i = 0; i < 12; i++) if (uTemp[i] > 0) data.uTemp[i] = uTemp[i];

  // setup read buffer
  pReadBuffer = (PCHAR)pIRP->AssociatedIrp.SystemBuffer;

  // setup buffer data
  RtlCopyBytes(pReadBuffer, &data, sizeof(data));
  pIRP->IoStatus.Information = sizeof(data);

  return STATUS_SUCCESS;
}
Example #2
0
NTSTATUS Ds4_AddQueryInterfaces(WDFDEVICE Device)
{
    NTSTATUS status;
    WDF_QUERY_INTERFACE_CONFIG ifaceCfg;
    INTERFACE devinterfaceHid;

    devinterfaceHid.Size = sizeof(INTERFACE);
    devinterfaceHid.Version = 1;
    devinterfaceHid.Context = (PVOID)Device;

    devinterfaceHid.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
    devinterfaceHid.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;

    // Expose GUID_DEVINTERFACE_HID so HIDUSB can initialize
    WDF_QUERY_INTERFACE_CONFIG_INIT(&ifaceCfg, (PINTERFACE)&devinterfaceHid, &GUID_DEVINTERFACE_HID, NULL);

    status = WdfDeviceAddQueryInterface(Device, &ifaceCfg);
    if (!NT_SUCCESS(status))
    {
        KdPrint(("WdfDeviceAddQueryInterface failed status 0x%x\n", status));
        return status;
    }

    PDS4_DEVICE_DATA ds4Data = Ds4GetData(Device);

    // Set default HID input report (everything zero`d)
    UCHAR DefaultHidReport[DS4_HID_REPORT_SIZE] =
    {
        0x01, 0x82, 0x7F, 0x7E, 0x80, 0x08, 0x00, 0x58,
        0x00, 0x00, 0xFD, 0x63, 0x06, 0x03, 0x00, 0xFE,
        0xFF, 0xFC, 0xFF, 0x79, 0xFD, 0x1B, 0x14, 0xD1,
        0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x00,
        0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
        0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
        0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00
    };

    // Initialize HID reports to defaults
    RtlCopyBytes(ds4Data->HidInputReport, DefaultHidReport, DS4_HID_REPORT_SIZE);
    RtlZeroMemory(&ds4Data->OutputReport, sizeof(DS4_OUTPUT_REPORT));

    // Start pending IRP queue flush timer
    WdfTimerStart(ds4Data->PendingUsbInRequestsTimer, DS4_QUEUE_FLUSH_PERIOD);

    return STATUS_SUCCESS;
}
Example #3
0
NTSTATUS BulkUsb_QueryWmiDataBlock(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN ULONG GuidIndex,
								   IN ULONG InstanceIndex, IN ULONG InstanceCount, 
								   IN OUT PULONG InstanceLengthArray, IN ULONG OutBufferSize,
								   OUT PUCHAR Buffer)
{
    PTDeviceExtension deviceExtension;
    NTSTATUS          ntStatus;
    ULONG             size;
    WCHAR             modelName[] = L"Aishverya\0\0";
    USHORT            modelNameLen;

    PAGED_CODE();
    BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - begins\n"));
    size = 0;
    modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR);

    ASSERT((InstanceIndex == 0) && (InstanceCount == 1));
    
    deviceExtension = (PTDeviceExtension) DeviceObject->DeviceExtension;
    switch (GuidIndex) 
	{
    case WMI_BULKUSB_DRIVER_INFORMATION:
        size = sizeof(ULONG) + modelNameLen + sizeof(USHORT);
        if (OutBufferSize < size ) 
		{
            BulkUsb_DbgPrint(3, ("file bulkwmi: OutBuffer too small\n"));
            ntStatus = STATUS_BUFFER_TOO_SMALL;
            break;
        }
        * (PULONG) Buffer = DebugLevel;
        Buffer += sizeof(ULONG);
        *((PUSHORT)Buffer) = modelNameLen;
        Buffer = (PUCHAR)Buffer + sizeof(USHORT);
        RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen);
        *InstanceLengthArray = size ;
        ntStatus = STATUS_SUCCESS;
        break;

    default:
        ntStatus = STATUS_WMI_GUID_NOT_FOUND;
		break;
    }
    ntStatus = WmiCompleteRequest(DeviceObject, Irp, ntStatus, size, IO_NO_INCREMENT);
    BulkUsb_DbgPrint(3, ("file bulkwmi: BulkUsb_QueryWmiDataBlock - ends\n"));
    return ntStatus;
}
Example #4
0
DWORD FanCtrlWrite(PDEVICE_OBJECT pDriverObject, PIRP pIRP)
{
  int i;
  UCHAR uValue;
  PCHAR pReadBuffer;

  // setup read buffer
  pReadBuffer = (PCHAR)pIRP->AssociatedIrp.SystemBuffer;

  // setup buffer data
  RtlCopyBytes(&uValue, pReadBuffer, 1);
  pIRP->IoStatus.Information = 1;

  // output the expected fan speed
  ECCtrlWrite(TP_OFF_FANMOD, &uValue);

  return STATUS_SUCCESS;
}
Example #5
0
NTSTATUS
DriverDeviceControl(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{

    NTSTATUS           Status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION IrpSp;
    ULONG              IOControlCode = 0;
    ULONG              dwBytesWritten = 0;
    PCHAR              pInBuf = NULL, pOutBuf = NULL;
    unsigned int       _cpu_thread_id = 0;
    unsigned int       new_cpu_thread_id = 0;
    ULONG              _num_active_cpus = 0;
    KAFFINITY          _kaffinity = 0;
    UINT32             core_id = 0;

    //
    // Get the current IRP stack location of this request
    //
    IrpSp = IoGetCurrentIrpStackLocation (Irp);
    IOControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;

    DbgPrint( "[chipsec] >>>>>>>>>> IOCTL >>>>>>>>>>\n" );
    DbgPrint( "[chipsec] DeviceObject = 0x%x IOCTL = 0x%x\n", DeviceObject, IOControlCode );
    DbgPrint( "[chipsec] InputBufferLength = 0x%x, OutputBufferLength = 0x%x\n", IrpSp->Parameters.DeviceIoControl.InputBufferLength, IrpSp->Parameters.DeviceIoControl.OutputBufferLength );

    //
    // CPU thread ID
    // 
    _num_active_cpus = KeQueryActiveProcessorCount( NULL );
    _kaffinity       = KeQueryActiveProcessors();
    _cpu_thread_id   = KeGetCurrentProcessorNumber();
    DbgPrint( "[chipsec] Active CPU threads         : %d (KeNumberProcessors = %d)\n", _num_active_cpus, KeNumberProcessors );
    DbgPrint( "[chipsec] Active CPU mask (KAFFINITY): 0x%08X\n", _kaffinity );
    DbgPrint( "[chipsec] Current CPU thread         : %d\n", _cpu_thread_id );

    //
    // Switch on the IOCTL code that is being requested by the user.  If the
    // operation is a valid one for this device do the needful.
    //
    Irp -> IoStatus.Information = 0;
    switch( IOControlCode )
      {
        case READ_PCI_CFG_REGISTER:
          {
            DWORD val;
            BYTE size = 0;
            WORD bdf[4];
            BYTE bus = 0, dev = 0, fun = 0, off = 0;
            DbgPrint( "[chipsec] > READ_PCI_CFG_REGISTER\n" );

            RtlCopyBytes( bdf,Irp->AssociatedIrp.SystemBuffer, 4*sizeof(WORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 4*sizeof(WORD), sizeof(BYTE) );
            bus = (UINT8)bdf[0];
            dev = (UINT8)bdf[1];
            fun = (UINT8)bdf[2];
            off = (UINT8)bdf[3];

            if( 1 != size && 2 != size && 4 != size)
              {
              DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
              Status = STATUS_INVALID_PARAMETER;
              break;
              }
            val = ReadPCICfg( bus, dev, fun, off, size );             

            IrpSp->Parameters.Read.Length = size;
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&val, size );
            DbgPrint( "[chipsec][READ_PCI_CFG_REGISTER] B/D/F: %#04x/%#04x/%#04x, OFFSET: %#04x, value = %#010x (size = 0x%x)\n", bus, dev, fun, off, val, size );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case WRITE_PCI_CFG_REGISTER:
          {
            DWORD val = 0;
            WORD bdf[6];
            BYTE bus = 0, dev = 0, fun = 0, off = 0;
            BYTE size = 0;
            DbgPrint( "[chipsec] > WRITE_PCI_CFG_REGISTER\n" );

            RtlCopyBytes( bdf, Irp->AssociatedIrp.SystemBuffer, 6 * sizeof(WORD) );
            bus = (UINT8)bdf[0];
            dev = (UINT8)bdf[1];
            fun = (UINT8)bdf[2];
            off = (UINT8)bdf[3];
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 6*sizeof(WORD), sizeof(BYTE) );

            val = ((DWORD)bdf[5] << 16) | bdf[4];
            DbgPrint( "[chipsec][WRITE_PCI_CFG_REGISTER] B/D/F: %#02x/%#02x/%#02x, OFFSET: %#02x, value = %#010x (size = %#02x)\n", bus, dev, fun, off, val, size );
            WritePCICfg( bus, dev, fun, off, size, val );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_READ_PHYSMEM:
          {
            UINT32 len = 0;
            PVOID virt_addr;
            PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };

            DbgPrint( "[chipsec] > IOCTL_READ_PHYSMEM\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32))
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            phys_addr.HighPart = ((UINT32*)pInBuf)[0];
            phys_addr.LowPart  = ((UINT32*)pInBuf)[1];
            len                = ((UINT32*)pInBuf)[2];
            if( !len ) len = 4;

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len )
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
                break;
              }

            __try
              {
                Status = _read_phys_mem( phys_addr, len, pOutBuf );
              }
            __except (EXCEPTION_EXECUTE_HANDLER)
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] ERROR: exception code 0x%X\n", Status );
                break;
              }

            if( NT_SUCCESS(Status) )
              {
                DbgPrint( "[chipsec][IOCTL_READ_PHYSMEM] Contents:\n" );
                _dump_buffer( (unsigned char *)pOutBuf, min(len,0x100) );
                dwBytesWritten = len;
              }
            break;
          }
        case IOCTL_WRITE_PHYSMEM:
          {
            UINT32 len = 0;
            PVOID virt_addr = 0;
            PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };

            DbgPrint( "[chipsec] > IOCTL_WRITE_PHYSMEM\n" );
            if( Irp->AssociatedIrp.SystemBuffer )
              {
                pInBuf = Irp->AssociatedIrp.SystemBuffer;
                pOutBuf = Irp->AssociatedIrp.SystemBuffer;

                if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3*sizeof(UINT32) )
                  {
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                    Status = STATUS_INVALID_PARAMETER;
                    break;
                  }

                phys_addr.HighPart = ((UINT32*)pInBuf)[0];
                phys_addr.LowPart  = ((UINT32*)pInBuf)[1];
                len                = ((UINT32*)pInBuf)[2];
                ((UINT32*)pInBuf) += 3;

                if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3*sizeof(UINT32) )
                  {
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: STATUS_INVALID_PARAMETER\n" );
                    Status = STATUS_INVALID_PARAMETER;
                    break;
                  }

                DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] Writing contents:\n" );
                _dump_buffer( (unsigned char *)pInBuf, min(len,0x100) );

                __try
                  {
                    Status = _write_phys_mem( phys_addr, len, pInBuf );
                  }
                __except (EXCEPTION_EXECUTE_HANDLER)
                  {
                    Status = GetExceptionCode();
                    DbgPrint( "[chipsec][IOCTL_WRITE_PHYSMEM] ERROR: exception code 0x%X\n", Status );
                    break;
                  }

                break;
              }
          }
        case IOCTL_ALLOC_PHYSMEM:
          {
            SIZE_T NumberOfBytes = 0;
            PVOID va = 0;
            PHYSICAL_ADDRESS HighestAcceptableAddress = { 0xFFFFFFFF, 0xFFFFFFFF };

            DbgPrint( "[chipsec] > IOCTL_ALLOC_PHYSMEM\n" );
            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf || IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT64) + sizeof(UINT32))
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( &HighestAcceptableAddress.QuadPart, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            RtlCopyBytes( &NumberOfBytes, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT64), sizeof(UINT32) );
            DbgPrint( "[chipsec] Allocating: NumberOfBytes = 0x%X, PhysAddr = 0x%I64x", NumberOfBytes, HighestAcceptableAddress.QuadPart );
            va = MmAllocateContiguousMemory( NumberOfBytes, HighestAcceptableAddress );
            if( !va )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_UNSUCCESSFUL - could not allocate memory\n" );
                Status = STATUS_UNSUCCESSFUL;
              }
            else if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 2*sizeof(UINT64) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2*UINT64\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
              }
            else
              {
                PHYSICAL_ADDRESS pa   = MmGetPhysicalAddress( va );
                DbgPrint( "[chipsec] Allocated Buffer: VirtAddr = 0x%I64x, PhysAddr = 0x%I64x\n", (UINT64)va, pa.QuadPart );
                ((UINT64*)pOutBuf)[0] = (UINT64)va;
                ((UINT64*)pOutBuf)[1] = pa.QuadPart;

                IrpSp->Parameters.Read.Length = 2*sizeof(UINT64);
                dwBytesWritten = IrpSp->Parameters.Read.Length;
                Status = STATUS_SUCCESS;
              }

            break;
          }

        case IOCTL_FREE_PHYSMEM:
          {
            UINT64 va = 0x0;
            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_FREE_PHYSMEM\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            DbgPrint( "[chipsec][IOCTL_FREE_PHYSMEM] Virtual address of the memory being freed: 0x%I64X\n", va );
            MmFreeContiguousMemory( (PVOID)va );

            IrpSp->Parameters.Read.Length = 0;
            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_GET_PHYSADDR:
          {
            UINT64 va = 0x0;
            PHYSICAL_ADDRESS pa = { 0x0, 0x0 };

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_GET_PHYSADDR\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( &va, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64) );
            pa = MmGetPhysicalAddress( (PVOID)va );

            DbgPrint( "[chipsec][IOCTL_GET_PHYSADDR] Traslated virtual address 0x%I64X to physical: 0x%I64X\n", va, pa.QuadPart, pa.LowPart);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&pa, sizeof(UINT64) );
            IrpSp->Parameters.Read.Length = sizeof(UINT64);
            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_MAP_IO_SPACE:
          {
            PVOID va  = 0x0;
            PHYSICAL_ADDRESS pa = { 0x0, 0x0 };
            unsigned int len = 0;
            unsigned int cache_type = 0;

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;

            DbgPrint( "[chipsec] > IOCTL_MAP_IO_SPACE\n" );
            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != 3*8)
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( &pa,         (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x00, 0x8 );
            RtlCopyBytes( &len,        (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x08, 0x4 );
            RtlCopyBytes( &cache_type, (BYTE*)Irp->AssociatedIrp.SystemBuffer + 0x10, 0x4 );

            va = MmMapIoSpace(pa, len, cache_type);

            DbgPrint( "[chipsec][IOCTL_MAP_IO_SPACE] Mapping physical address 0x%016llX to virtual 0x%016llX\n", pa, va);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&va, sizeof(va) );
            IrpSp->Parameters.Read.Length = sizeof(va);
            dwBytesWritten = sizeof(va);
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_LOAD_UCODE_PATCH:
          {
            PVOID ucode_buf = NULL;
            UINT64 ucode_start = 0;
            UINT16 ucode_size = 0;
            UINT32 _eax = 0, _edx = 0;
            int CPUInfo[4] = {-1};

            DbgPrint("[chipsec] > IOCTL_LOAD_UCODE_UPDATE\n" );

            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT16) )
            {
               DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < 3)\n" );
               Status = STATUS_INVALID_PARAMETER;
               break;
            }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( &ucode_size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT16) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Ucode update size = 0x%X\n", ucode_size );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < ucode_size + sizeof(BYTE) + sizeof(UINT16) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < ucode_size + 3)\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            ucode_buf = ExAllocatePoolWithTag( NonPagedPool, ucode_size, 0x3184 );
            if( !ucode_buf )
              {
                DbgPrint( "[chipsec] ERROR: couldn't allocate pool for ucode binary\n" );
                break;
              }           
            RtlCopyBytes( ucode_buf, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE) + sizeof(UINT16), ucode_size );
            ucode_start = (UINT64)ucode_buf;
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update address = 0x%p (eax = 0x%08X, edx = 0x%08X)\n", ucode_start, (UINT32)(ucode_start & 0xFFFFFFFF), (UINT32)((ucode_start >> 32) & 0xFFFFFFFF) );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] ucode update contents:\n" );
            _dump_buffer( (unsigned char *)ucode_buf, min(ucode_size,0x100) );

            // --
            // -- trigger CPU ucode patch update
            // -- pInBuf points to the beginning of ucode update binary
            // --
            _wrmsr( MSR_IA32_BIOS_UPDT_TRIG, (UINT32)((ucode_start >> 32) & 0xFFFFFFFF), (UINT32)(ucode_start & 0xFFFFFFFF) );

            ExFreePoolWithTag( ucode_buf, 0x3184 );

            // --
            // -- check if patch was loaded
            // --
            // -- need to clear IA32_BIOS_SIGN_ID MSR first
            // -- CPUID will deposit an update ID value in 64-bit MSR at address MSR_IA32_BIOS_SIGN_ID
            // -- read IA32_BIOS_SIGN_ID MSR to check patch ID != 0
            // --
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] checking ucode update was loaded..\n" );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] clear IA32_BIOS_SIGN_ID, CPUID EAX=1, read back IA32_BIOS_SIGN_ID\n" );
            _wrmsr( MSR_IA32_BIOS_SIGN_ID, 0, 0 );
            __cpuid(CPUInfo, 1);
            _rdmsr( MSR_IA32_BIOS_SIGN_ID, &_eax, &_edx );
            DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] RDMSR( IA32_BIOS_SIGN_ID=0x8b ) = 0x%08x%08x\n", _edx, _eax );
            if( 0 != _edx ) DbgPrint( "[chipsec][IOCTL_LOAD_UCODE_UPDATE] Microcode update loaded (ID != 0)\n" );
            else            DbgPrint( "[chipsec] ERROR: Microcode update failed\n" );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_WRMSR:
          {

            UINT32 msrData[3];
            UINT32 _eax = 0, _edx = 0;
            unsigned int _msr_addr;

            DbgPrint("[chipsec] > IOCTL_WRMSR\n");

            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + 3*sizeof(UINT32) )
              {
                DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(BYTE) + 3*sizeof(UINT32))\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_WRMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), 3 * sizeof(UINT32) );
            _msr_addr = msrData[0];
            _eax      = msrData[1];
            _edx      = msrData[2];
            DbgPrint( "[chipsec][IOCTL_WRMSR] WRMSR( 0x%x ) <-- 0x%08x%08x\n", _msr_addr, _edx, _eax );

            // --
            // -- write MSR
            // --
            __try
              {
                _wrmsr( _msr_addr, _edx, _eax );
              }
            __except (EXCEPTION_EXECUTE_HANDLER)
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_WRMSR] ERROR: exception code 0x%X\n", Status );
                break;
              }

            // --
            // -- read MSR to check if it was written
            // --
//            _rdmsr( _msr_addr, &_eax, &_edx );
//            DbgPrint( "[chipsec][IOCTL_WRMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax );

            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_RDMSR:
          {
            UINT32 msrData[1];
            UINT32 _eax = 0;
            UINT32 _edx = 0;
            UINT32 _msr_addr = 0;

            DbgPrint("[chipsec] > IOCTL_RDMSR\n");

            pInBuf  = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
                DbgPrint( "[chipsec] ERROR: No input provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(BYTE) + sizeof(UINT32) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER - input buffer size < sizeof(BYTE) + sizeof(UINT32)\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][IOCTL_RDMSR] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );

            RtlCopyBytes( msrData, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(UINT32) );
            _msr_addr = msrData[0];

            __try
              {
                _rdmsr( _msr_addr, &_eax, &_edx );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_RDMSR] ERROR: exception code 0x%X\n", Status );
                break;
              }
            DbgPrint( "[chipsec][IOCTL_RDMSR] RDMSR( 0x%x ) --> 0x%08x%08x\n", _msr_addr, _edx, _eax );

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= 2*sizeof(UINT32) )
              {
                IrpSp->Parameters.Read.Length = 2*sizeof(UINT32);
                RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&_eax, sizeof(UINT32) );
                RtlCopyBytes( ((UINT8*)Irp->AssociatedIrp.SystemBuffer) + sizeof(UINT32), (VOID*)&_edx, sizeof(UINT32) );

                dwBytesWritten = 2*sizeof(UINT32);
                Status = STATUS_SUCCESS;
              }
            else
              {
                DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL - should be at least 2 UINT32\n" );
                Status = STATUS_BUFFER_TOO_SMALL;
              }

            break;
          }
        case READ_IO_PORT:
          {
            DWORD value;
            BYTE size = 0;
            WORD io_port;
            DbgPrint( "[chipsec] > READ_IO_PORT\n" );

            RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(BYTE) );
            if( 1 != size && 2 != size && 4 != size)
              {
              DbgPrint( "[chipsec][READ_IO_PORT] ERROR: STATUS_INVALID_PARAMETER\n" );
              Status = STATUS_INVALID_PARAMETER;
              break;
              }

            __try
              {
                value = ReadIOPort( io_port, size );             
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][READ_IO_PORT] ERROR: exception code 0x%X\n", Status );
                break;
              }

            IrpSp->Parameters.Read.Length = size;
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (VOID*)&value, size );
            DbgPrint( "[chipsec][READ_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case WRITE_IO_PORT:
          {
            DWORD value = 0;
            WORD io_port = 0;
            BYTE size = 0;
            DbgPrint( "[chipsec] > WRITE_IO_PORT\n" );

            RtlCopyBytes( &io_port, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(WORD) );
            RtlCopyBytes( &value, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD), sizeof(DWORD) );
            RtlCopyBytes( &size, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(WORD) + sizeof(DWORD), sizeof(BYTE) );
            DbgPrint( "[chipsec][WRITE_IO_PORT] I/O Port %#04x, value = %#010x (size = %#02x)\n", io_port, value, size );

            __try
              {
                WriteIOPort( value, io_port, size );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][WRITE_IO_PORT] ERROR: exception code 0x%X\n", Status );
                break;
              }

            Status = STATUS_SUCCESS;
            break;
          }
        case GET_CPU_DESCRIPTOR_TABLE:
          {
            BYTE dt_code = 0;
            DESCRIPTOR_TABLE_RECORD dtr;
            PDESCRIPTOR_TABLE_RECORD pdtr = &dtr;
            PHYSICAL_ADDRESS dt_pa;

            DbgPrint( "[chipsec] > GET_CPU_DESCRIPTOR_TABLE\n" );

            RtlCopyBytes( &new_cpu_thread_id, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(BYTE) );
            if( new_cpu_thread_id >= _num_active_cpus ) new_cpu_thread_id = 0;
            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Changed CPU thread to %d\n", KeGetCurrentProcessorNumber() );
            RtlCopyBytes( &dt_code, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(BYTE), sizeof(BYTE) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table: %x\n", dt_code );

            switch( dt_code )
              {
                case CPU_DT_CODE_GDTR:  { _store_gdtr( (void*)pdtr ); break; }
                case CPU_DT_CODE_LDTR:  { _store_ldtr( (void*)pdtr ); break; }
                case CPU_DT_CODE_IDTR:
                default:                { _store_idtr( (void*)pdtr ); break; }
              }

            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table register contents:\n" );
            _dump_buffer( (unsigned char *)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] IDTR: Limit = 0x%04x, Base = 0x%I64x\n", dtr.limit, dtr.base );

            dt_pa = MmGetPhysicalAddress( (PVOID)dtr.base );
            DbgPrint( "[chipsec][GET_CPU_DESCRIPTOR_TABLE] Descriptor table PA: 0x%I64X (0x%08X_%08X)\n", dt_pa.QuadPart, dt_pa.HighPart, dt_pa.LowPart );

            IrpSp->Parameters.Read.Length = sizeof(DESCRIPTOR_TABLE_RECORD) + sizeof(dt_pa.QuadPart);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)pdtr, sizeof(DESCRIPTOR_TABLE_RECORD) );    
            RtlCopyBytes( (UINT8*)Irp->AssociatedIrp.SystemBuffer + sizeof(DESCRIPTOR_TABLE_RECORD), (VOID*)&dt_pa.QuadPart, sizeof(dt_pa.QuadPart) );    

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_SWSMI:
          {
            CPU_REG_TYPE gprs[6] = {0};
            CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0;
            unsigned int _smi_code_data = 0;

            DbgPrint("[chipsec] > IOCTL_SWSMI\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(UINT16) + sizeof(gprs) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < sizeof(UINT16) + sizeof(gprs))\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( &_smi_code_data, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT16) );
            RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(UINT16), sizeof(gprs) );
            _rax = gprs[ 0 ];
            _rbx = gprs[ 1 ];
            _rcx = gprs[ 2 ];
            _rdx = gprs[ 3 ];
            _rsi = gprs[ 4 ];
            _rdi = gprs[ 5 ];
            DbgPrint( "[chipsec][IOCTL_SWSMI] SW SMI to ports 0x%X-0x%X <- 0x%04X\n", 0xB2, 0xB3, _smi_code_data );
            DbgPrint( "                       RAX = 0x%I64x\n", _rax );
            DbgPrint( "                       RBX = 0x%I64x\n", _rbx );
            DbgPrint( "                       RCX = 0x%I64x\n", _rcx );
            DbgPrint( "                       RDX = 0x%I64x\n", _rdx );
            DbgPrint( "                       RSI = 0x%I64x\n", _rsi );
            DbgPrint( "                       RDI = 0x%I64x\n", _rdi );
            // --
            // -- send SMI using port 0xB2
            // --
            __try
              {
                _swsmi( _smi_code_data, _rax, _rbx, _rcx, _rdx, _rsi, _rdi );
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                break;
              }
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_CPUID:
          {
            DWORD CPUInfo[4] = {-1};
            DWORD gprs[2] = {0};
            DWORD _rax = 0, _rcx = 0;
            //CPU_REG_TYPE gprs[6];
            //CPU_REG_TYPE _rax = 0, _rbx = 0, _rcx = 0, _rdx = 0, _rsi = 0, _rdi = 0;

            DbgPrint("[chipsec] > IOCTL_CPUID\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            if( !pInBuf )
              {
	        DbgPrint( "[chipsec] ERROR: NO data provided\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(gprs) )
              {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER (input buffer size < %d)\n", sizeof(gprs) );
                Status = STATUS_INVALID_PARAMETER;
                break;
              }
            RtlCopyBytes( gprs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(gprs) );
            _rax = gprs[ 0 ];
            _rcx = gprs[ 1 ];
            DbgPrint( "[chipsec][IOCTL_CPUID] CPUID:\n" );
            DbgPrint( "                       EAX = 0x%08X\n", _rax );
            DbgPrint( "                       ECX = 0x%08X\n", _rcx );

            __cpuidex( CPUInfo, _rax, _rcx );

            DbgPrint( "[chipsec][IOCTL_CPUID] CPUID returned:\n" );
            DbgPrint( "                       EAX = 0x%08X\n", CPUInfo[0] );
            DbgPrint( "                       EBX = 0x%08X\n", CPUInfo[1] );
            DbgPrint( "                       ECX = 0x%08X\n", CPUInfo[2] );
            DbgPrint( "                       EDX = 0x%08X\n", CPUInfo[3] );

            IrpSp->Parameters.Read.Length = sizeof(CPUInfo);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)CPUInfo, sizeof(CPUInfo) );    

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        case IOCTL_WRCR:
          {
            UINT64 val64 = 0;
            CPU_REG_TYPE value = 0;
            WORD cr_reg = 0;
            DbgPrint( "[chipsec] > WRITE_CR\n" );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg) + sizeof(val64) + sizeof(BYTE)))
            {
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) );
            RtlCopyBytes( &val64, (BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg), sizeof(val64) );
            new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg) + sizeof(val64));
            if( new_cpu_thread_id >= _num_active_cpus )
            {
            //    new_cpu_thread_id = 0;
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );
            value = (CPU_REG_TYPE)val64;
            DbgPrint( "[chipsec][WRITE_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value );

            switch (cr_reg) {
            case 0: WriteCR0(value);
                Status = STATUS_SUCCESS;
                break;
            case 2: WriteCR2(value);
                Status = STATUS_SUCCESS;
                break;
            case 3: WriteCR3(value);
                Status = STATUS_SUCCESS;
                break;
            case 4: WriteCR4(value);
                Status = STATUS_SUCCESS;
                break;
            case 8:
#if defined(_M_AMD64)
                WriteCR8(value);
                Status = STATUS_SUCCESS;
                break;
#endif
            default:
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            if( !NT_SUCCESS(Status) ) {
                break;
            }

            dwBytesWritten = 0;
            Status = STATUS_SUCCESS;
            break;
          }
        case IOCTL_RDCR:
          {
            UINT64 val64 = 0;
            CPU_REG_TYPE value = 0;
            WORD cr_reg = 0;
            DbgPrint( "[chipsec] > READ_CR\n" );

            if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < (sizeof(cr_reg)+sizeof(BYTE))
             || IrpSp->Parameters.DeviceIoControl.OutputBufferLength < (sizeof(val64))
              )
            {
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            RtlCopyBytes( &cr_reg, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(cr_reg) );
            new_cpu_thread_id = *((BYTE*)Irp->AssociatedIrp.SystemBuffer + sizeof(cr_reg));
            if( new_cpu_thread_id >= _num_active_cpus )
            {
            //    new_cpu_thread_id = 0;
                 Status = STATUS_INVALID_PARAMETER;
                 break;
            }

            KeSetSystemAffinityThread( (KAFFINITY)(1 << new_cpu_thread_id) );

            switch (cr_reg) {
            case 0: value = ReadCR0();
                Status = STATUS_SUCCESS;
                break;
            case 2: value = ReadCR2();
                Status = STATUS_SUCCESS;
                break;
            case 3: value = ReadCR3();
                Status = STATUS_SUCCESS;
                break;
            case 4: value = ReadCR4();
                Status = STATUS_SUCCESS;
                break;
            case 8:
#if defined(_M_AMD64)
                value = ReadCR8();
                Status = STATUS_SUCCESS;
                break;
#endif
            default:
                Status = STATUS_INVALID_PARAMETER;
                break;
            }
            
            if( !NT_SUCCESS(Status) ) {
                break;
            }

            val64 = value;
            RtlCopyBytes( (BYTE*)Irp->AssociatedIrp.SystemBuffer, &val64, sizeof(val64) );
            dwBytesWritten = sizeof(val64);

            DbgPrint( "[chipsec][READ_CR] CR Reg %#04x, value = %#010x \n", cr_reg, value );

            Status = STATUS_SUCCESS;
            break;

          }
        case IOCTL_HYPERCALL:
          {
            CPU_REG_TYPE regs[11] = {0};
            CPU_REG_TYPE result = 0;

            DbgPrint("[chipsec] > IOCTL_HYPERCALL\n");
            pInBuf = Irp->AssociatedIrp.SystemBuffer;

            if( !Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(regs))
            {
                DbgPrint( "[chipsec] ERROR: STATUS_INVALID_PARAMETER\n" );
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            if( IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(result))
            {
               DbgPrint( "[chipsec] ERROR: STATUS_BUFFER_TOO_SMALL\n" );
               Status = STATUS_BUFFER_TOO_SMALL;
               break;
            }

            RtlCopyBytes( regs, (BYTE*)Irp->AssociatedIrp.SystemBuffer, sizeof(regs) );
            DbgPrint( "[chipsec][IOCTL_HYPERCALL] HYPERCALL:\n" );
            #if defined(_M_AMD64)
            DbgPrint( "    RCX = 0x%016llX  RDX = 0x%016llX\n", regs[0], regs[1] );
            DbgPrint( "    R8  = 0x%016llX  R9  = 0x%016llX\n", regs[2], regs[3] );
            DbgPrint( "    R10 = 0x%016llX  R11 = 0x%016llX\n", regs[4], regs[5] );
            DbgPrint( "    RAX = 0x%016llX  RBX = 0x%016llX\n", regs[6], regs[7] );
            DbgPrint( "    RDI = 0x%016llX  RSI = 0x%016llX\n", regs[8], regs[9] );
            #endif
            #if defined(_M_IX86)
            DbgPrint( "    EAX = 0x%08X  EBX = 0x%08X  ECX = 0x%08X\n", regs[6], regs[7], regs[0] );
            DbgPrint( "    EDX = 0x%08X  ESI = 0x%08X  EDI = 0x%08X\n", regs[1], regs[8], regs[9] );
            #endif
            DbgPrint( "    XMM0-XMM5 buffer VA = 0x%016llX\n", regs[9] );

            __try
              {
                result = hypercall(regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6], regs[7], regs[8], regs[9], regs[10], &hypercall_page);
              }
            __except( EXCEPTION_EXECUTE_HANDLER )
              {
                Status = GetExceptionCode();
                DbgPrint( "[chipsec][IOCTL_HYPERCALL] ERROR: exception code 0x%X\n", Status );
                break;
              }

            DbgPrint( "[chipsec][IOCTL_HYPERCALL] returned: 0x%016llX\n", result);

            IrpSp->Parameters.Read.Length = sizeof(result);
            RtlCopyBytes( Irp->AssociatedIrp.SystemBuffer, (void*)&result, sizeof(result) );

            dwBytesWritten = IrpSp->Parameters.Read.Length;
            Status = STATUS_SUCCESS;
            break;
          }

        default:
            DbgPrint( "[chipsec] ERROR: invalid IOCTL\n");
            Status = STATUS_NOT_IMPLEMENTED;
            break;

      } // -- switch
NTSTATUS DeviceControlCompleteRoutine(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
	UNREFERENCED_PARAMETER(pDeviceObject);

	NTSTATUS			status = STATUS_SUCCESS;
	PIO_STACK_LOCATION	pIrpsp = IoGetCurrentIrpStackLocation(pIrp);
	ULONG				uLength = 0;

	PVOID				pBuffer = pIrp->AssociatedIrp.SystemBuffer;
	ULONG				ulInputlength = pIrpsp->Parameters.DeviceIoControl.InputBufferLength;
	ULONG				ulOutputlength = pIrpsp->Parameters.DeviceIoControl.OutputBufferLength;

	do
	{
		switch (pIrpsp->Parameters.DeviceIoControl.IoControlCode)
		{
		case CWK_DVC_SEND_STR:
			{
				ASSERT(pBuffer != NULL);
				ASSERT(ulInputlength > 0);
				ASSERT(ulOutputlength == 0);
			}
			break;
		case CWK_DVC_RECV_STR:
			{
				ASSERT(ulInputlength == 0);

				while (TRUE)
				{
					PEVENT_DATA_NODE pNode = (PEVENT_DATA_NODE)ExInterlockedRemoveHeadList(&g_ListHead, &g_Lock);
					if (NULL != pNode)
					{
						PREGISTRY_EVENT pOutputBuffer = (PREGISTRY_EVENT)pBuffer;
						SIZE_T			ulNumberOfBytes = sizeof(REGISTRY_EVENT) +						// 结构体大小
							pNode->pstRegistryEvent->ulProcessPathLength +								// 进程路径长度
							pNode->pstRegistryEvent->ulRegistryPathLength +								// 路径长度
							pNode->pstRegistryEvent->ulDataLength;										// 数据长度

						if (NULL != pNode->pstRegistryEvent)
						{
							if (ulOutputlength >= ulNumberOfBytes)
							{
								RtlCopyBytes(pOutputBuffer, pNode->pstRegistryEvent, ulNumberOfBytes);
								ExFreePoolWithTag(pNode->pstRegistryEvent, MEM_TAG);
								ExFreePoolWithTag(pNode, MEM_TAG);
							}
							else
							{
								ExInterlockedInsertHeadList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock);
							}						
						}

						uLength = (ULONG)ulNumberOfBytes;
						break;
					}
					else
					{
						KeWaitForSingleObject(&g_Event, Executive, KernelMode, 0, 0);
					}
				}
			}
			break;
		default:
			{
				status = STATUS_INVALID_PARAMETER;
			}
			break;
		}
	} while (FALSE);

	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = uLength;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);

	return status;
}
NTSTATUS RegistryCallback(
	_In_      PVOID CallbackContext,
	_In_opt_  PVOID Argument1,
	_In_opt_  PVOID Argument2
)
{
	NTSTATUS			status = STATUS_SUCCESS;
	ULONG				ulCallbackCtx;
	REG_NOTIFY_CLASS	ulType = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
	UNICODE_STRING		usRegistryPath = { 0 };
	BOOLEAN				bSuccess = FALSE;
	LARGE_INTEGER		unCurrentSystemTime;
	LARGE_INTEGER		unCurrentLocalTime;
	PVOID				pData = NULL;
	ULONG				ulDataSize = 0;
	ULONG				ulKeyValueType = REG_NONE;
	WCHAR				wzProcessPath[MAX_STRING_LENGTH] = { 0 };

	// 时间
	KeQuerySystemTime(&unCurrentSystemTime);
	ExSystemTimeToLocalTime(&unCurrentSystemTime, &unCurrentLocalTime);

	ulCallbackCtx = (ULONG)(ULONG_PTR)CallbackContext;

	usRegistryPath.Length = 0;
	usRegistryPath.MaximumLength = 2048 * sizeof(WCHAR);
	usRegistryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, usRegistryPath.MaximumLength, MEM_TAG);
	if (NULL == usRegistryPath.Buffer)
	{
		KdPrint(("[RegistryCallback] Failed to call ExAllocPollWithTag.\r\n"));
		return status;
	}

	switch (ulType)
	{
	case RegNtPreCreateKeyEx:
		{
			PREG_CREATE_KEY_INFORMATION_V1	pCreateInfo = (PREG_CREATE_KEY_INFORMATION_V1)Argument2;
			UNICODE_STRING					usFilter = { 0 };
			BOOLEAN							bEqual = FALSE;
			WCHAR							*wzFilters[] =
			{
				L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses",
				L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses",
				L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters",
				L"\\REGISTRY\\MACHINE\\System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
			};

			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath,
				pCreateInfo->CompleteName,
				pCreateInfo->RootObject);
			
			if (bSuccess)
			{
				for (size_t nCount = 0; nCount < sizeof(wzFilters) / sizeof(ULONG_PTR); nCount++)
				{
					RtlInitUnicodeString(&usFilter, wzFilters[nCount]);
					if (RtlEqualUnicodeString(&usRegistryPath, &usFilter, TRUE))
					{
						bEqual = TRUE;
					}
				}
				if (!bEqual)
				{
					//WCHAR wzProcessPath[MAX_STRING_LENGTH] = { 0 };
					//GetProcessPathBySectionObject(PsGetCurrentProcessId(), wzProcessPath);
					//KdPrint(("[RegNtPreCreateKeyEx] [%ws] %wZ\r\n", wzProcessPath, &usRegistryPath));
				}
				else
				{
					usRegistryPath.Length = 0;
				}
			}
		}
		break;
	case RegNtPreDeleteKey:
		{
			PREG_DELETE_KEY_INFORMATION pDeleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath, 
				NULL, 
				pDeleteKey->Object);
			if (bSuccess)
			{
				// KdPrint(("[RegNtPreDeleteKey]: %wZ\r\n", &usRegistryPath));
			}
		}
		break;
	case RegNtPreSetValueKey:
		{
			PREG_SET_VALUE_KEY_INFORMATION	pSetKeyValue = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(
				&usRegistryPath,
				NULL,
				pSetKeyValue->Object);
			if (bSuccess && pSetKeyValue->ValueName->Length > 0 && 
				(REG_SZ == pSetKeyValue->Type || REG_DWORD == pSetKeyValue->Type || REG_QWORD == pSetKeyValue->Type))
			{
				RtlUnicodeStringCatString(&usRegistryPath, L"\\");
				RtlUnicodeStringCat(&usRegistryPath, pSetKeyValue->ValueName);

				ulKeyValueType = pSetKeyValue->Type;
				ulDataSize = pSetKeyValue->DataSize;
				pData = pSetKeyValue->Data;
			}
			else
			{
				usRegistryPath.Length = 0;
			}
		}
		break;
	case RegNtPreDeleteValueKey:
		{
			PREG_DELETE_VALUE_KEY_INFORMATION pDeleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;
			bSuccess = GetRegistryObjectCompleteName(&usRegistryPath, NULL, pDeleteValueKey->Object);
			if (bSuccess && (pDeleteValueKey->ValueName->Length > 0))
			{
				RtlUnicodeStringCatString(&usRegistryPath, L"\\");
				RtlUnicodeStringCat(&usRegistryPath, pDeleteValueKey->ValueName);
			}
		}
		break;
	default:
		break;
	}

	// 创建数据链表
	if (usRegistryPath.Length != 0)
	{
		PEVENT_DATA_NODE	pNode = InitListNode();
		HANDLE				hProcessId = NULL;

		hProcessId = PsGetCurrentProcessId();
		GetProcessPathBySectionObject(hProcessId, wzProcessPath);

		ULONG				ulProcessPathLength = (ULONG)(wcslen(wzProcessPath) * sizeof(WCHAR) + sizeof(WCHAR));					// 进程的长度
		ULONG				ulRegistryPathLength = usRegistryPath.Length + sizeof(WCHAR);											// 注册表路径的长度
		SIZE_T				ulNumberOfBytes = sizeof(REGISTRY_EVENT) + ulProcessPathLength + ulRegistryPathLength + ulDataSize;		// 总长度=进程+注册表+数据
																																	// 进程路径
		pNode->pstRegistryEvent = ExAllocatePoolWithTag(NonPagedPool, ulNumberOfBytes, MEM_TAG);

		// 给各节点数据赋值
		pNode->pstRegistryEvent->hProcessId					= hProcessId;
		pNode->pstRegistryEvent->enRegistryNotifyClass		= ulType;
		pNode->pstRegistryEvent->ulDataLength				= ulDataSize;
		pNode->pstRegistryEvent->ulProcessPathLength		= ulProcessPathLength;
		pNode->pstRegistryEvent->ulRegistryPathLength		= ulRegistryPathLength;
		pNode->pstRegistryEvent->ulKeyValueType				= ulKeyValueType;
		
		RtlTimeToTimeFields(&unCurrentLocalTime, &pNode->pstRegistryEvent->time);											// 时间信息

		RtlCopyBytes(pNode->pstRegistryEvent->uData,						wzProcessPath, ulProcessPathLength);			// 拷贝进程信息
		RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength,	usRegistryPath.Buffer, usRegistryPath.Length);	// 追加注册表路径信息
		pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 0] = '\0';								// 给注册表路径后面添加 \0 结束符
		pNode->pstRegistryEvent->uData[ulProcessPathLength + usRegistryPath.Length + 1] = '\0';
		RtlCopyBytes(pNode->pstRegistryEvent->uData + ulProcessPathLength + ulRegistryPathLength, pData, ulDataSize);		// 追加修改的数据信息(如果不是修改值,这里可能为空)

		ExInterlockedInsertTailList(&g_ListHead, (PLIST_ENTRY)pNode, &g_Lock);
		KeSetEvent(&g_Event, 0, FALSE);

		KdPrint(("hProcessId = %ld", hProcessId));
	}

	if (NULL != usRegistryPath.Buffer)
	{
		ExFreePoolWithTag(usRegistryPath.Buffer, MEM_TAG);
	}

	return status;
}
Example #8
0
NTSTATUS NTAPI FreeBT_QueryWmiDataBlock(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP           Irp,
    IN ULONG          GuidIndex,
    IN ULONG          InstanceIndex,
    IN ULONG          InstanceCount,
    IN OUT PULONG     InstanceLengthArray,
    IN ULONG          OutBufferSize,
    OUT PUCHAR        Buffer
    )
/*++

Routine Description:

    This routine is a callback into the driver to query for the contents of
    a data block. When the driver has finished filling the data block it
    must call WmiCompleteRequest to complete the irp. The driver can
    return STATUS_PENDING if the irp cannot be completed immediately.

Arguments:

    DeviceObject is the device whose data block is being queried

    Irp is the Irp that makes this request

    GuidIndex is the index into the list of guids provided when the
        device registered

    InstanceIndex is the index that denotes which instance of the data block
        is being queried.

    InstanceCount is the number of instances expected to be returned for
        the data block.

    InstanceLengthArray is a pointer to an array of ULONG that returns the
        lengths of each instance of the data block. If this is NULL then
        there was not enough space in the output buffer to fulfill the request
        so the irp should be completed with the buffer needed.

    OutBufferSize has the maximum size available to write the data
        block.

    Buffer on return is filled with the returned data block


Return Value:

    status

--*/
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS          ntStatus;
    ULONG             size;
    WCHAR             modelName[] = L"Aishverya\0\0";
    USHORT            modelNameLen;

    PAGED_CODE();

    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Entered\n"));

    size = 0;
    modelNameLen = (wcslen(modelName) + 1) * sizeof(WCHAR);

    // Only ever registers 1 instance per guid
    ASSERT((InstanceIndex == 0) && (InstanceCount == 1));

    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
    switch (GuidIndex)
	{
    case WMI_FREEBT_DRIVER_INFORMATION:
        size = sizeof(ULONG) + modelNameLen + sizeof(USHORT);
        if (OutBufferSize < size )
		{
            FreeBT_DbgPrint(3, ("FBTUSB: OutBuffer too small\n"));
            ntStatus = STATUS_BUFFER_TOO_SMALL;
            break;

        }

        * (PULONG) Buffer = DebugLevel;
        Buffer += sizeof(ULONG);

        // put length of string ahead of string
        *((PUSHORT)Buffer) = modelNameLen;
        Buffer = (PUCHAR)Buffer + sizeof(USHORT);
        RtlCopyBytes((PVOID)Buffer, (PVOID)modelName, modelNameLen);
        *InstanceLengthArray = size ;

        ntStatus = STATUS_SUCCESS;
        break;

    default:
        ntStatus = STATUS_WMI_GUID_NOT_FOUND;

    }

    ntStatus = WmiCompleteRequest(DeviceObject,
                                Irp,
                                ntStatus,
                                size,
                                IO_NO_INCREMENT);

    FreeBT_DbgPrint(3, ("FBTUSB: FreeBT_QueryWmiDataBlock: Leaving\n"));

    return ntStatus;

}
Example #9
0
File: sioctl.c Project: huyna/GHAST
NTSTATUS
SioctlDeviceControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )

/*++

Routine Description:

    This routine is called by the I/O system to perform a device I/O
    control function.

Arguments:

    DeviceObject - a pointer to the object that represents the device
        that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    NT status code

--*/

{
    PIO_STACK_LOCATION  irpSp;// Pointer to current stack location
    NTSTATUS            ntStatus = STATUS_SUCCESS;// Assume success
    ULONG               inBufLength; // Input buffer length
    ULONG               outBufLength; // Output buffer length
    PCHAR               inBuf, outBuf; // pointer to Input and output buffer
    PCHAR               data = "This String is from Device Driver !!!";
    size_t              datalen = strlen(data)+1;//Length of data including null
    PMDL                mdl = NULL;
    PCHAR               buffer = NULL;

    UNREFERENCED_PARAMETER(DeviceObject);

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation( Irp );
    inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
    outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    if (!inBufLength || !outBufLength)
    {
        ntStatus = STATUS_INVALID_PARAMETER;
        goto End;
    }

    //
    // Determine which I/O control code was specified.
    //

    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
    case IOCTL_SIOCTL_METHOD_BUFFERED:

        //
        // In this method the I/O manager allocates a buffer large enough to
        // to accommodate larger of the user input buffer and output buffer,
        // assigns the address to Irp->AssociatedIrp.SystemBuffer, and
        // copies the content of the user input buffer into this SystemBuffer
        //

        SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_BUFFERED\n"));
        PrintIrpInfo(Irp);

        //
        // Input buffer and output buffer is same in this case, read the
        // content of the buffer before writing to it
        //

        inBuf = Irp->AssociatedIrp.SystemBuffer;
        outBuf = Irp->AssociatedIrp.SystemBuffer;

        //
        // Read the data from the buffer
        //

        SIOCTL_KDPRINT(("\tData from User :"******"\tData to User : "******"Called IOCTL_SIOCTL_METHOD_NEITHER\n"));

        PrintIrpInfo(Irp);

        //
        // A driver may access these buffers directly if it is a highest level
        // driver whose Dispatch routine runs in the context
        // of the thread that made this request. The driver should always
        // check the validity of the user buffer's address range and check whether
        // the appropriate read or write access is permitted on the buffer.
        // It must also wrap its accesses to the buffer's address range within
        // an exception handler in case another user thread deallocates the buffer
        // or attempts to change the access rights for the buffer while the driver
        // is accessing memory.
        //

        inBuf = irpSp->Parameters.DeviceIoControl.Type3InputBuffer;
        outBuf =  Irp->UserBuffer;

        //
        // Access the buffers directly if only if you are running in the
        // context of the calling process. Only top level drivers are
        // guaranteed to have the context of process that made the request.
        //

        try {
            //
            // Before accessing user buffer, you must probe for read/write
            // to make sure the buffer is indeed an userbuffer with proper access
            // rights and length. ProbeForRead/Write will raise an exception if it's otherwise.
            //
            ProbeForRead( inBuf, inBufLength, sizeof( UCHAR ) );

            //
            // Since the buffer access rights can be changed or buffer can be freed
            // anytime by another thread of the same process, you must always access
            // it within an exception handler.
            //

            SIOCTL_KDPRINT(("\tData from User :"******"Exception while accessing inBuf 0X%08X in METHOD_NEITHER\n",
                            ntStatus));
            break;
        }


        //
        // If you are accessing these buffers in an arbitrary thread context,
        // say in your DPC or ISR, if you are using it for DMA, or passing these buffers to the
        // next level driver, you should map them in the system process address space.
        // First allocate an MDL large enough to describe the buffer
        // and initilize it. Please note that on a x86 system, the maximum size of a buffer
        // that an MDL can describe is 65508 KB.
        //

        mdl = IoAllocateMdl(inBuf, inBufLength,  FALSE, TRUE, NULL);
        if (!mdl)
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        try
        {

            //
            // Probe and lock the pages of this buffer in physical memory.
            // You can specify IoReadAccess, IoWriteAccess or IoModifyAccess
            // Always perform this operation in a try except block.
            //  MmProbeAndLockPages will raise an exception if it fails.
            //
            MmProbeAndLockPages(mdl, UserMode, IoReadAccess);
        }
        except(EXCEPTION_EXECUTE_HANDLER)
        {

            ntStatus = GetExceptionCode();
            SIOCTL_KDPRINT((
                "Exception while locking inBuf 0X%08X in METHOD_NEITHER\n",
                    ntStatus));
            IoFreeMdl(mdl);
            break;
        }

        //
        // Map the physical pages described by the MDL into system space.
        // Note: double mapping the buffer this way causes lot of
        // system overhead for large size buffers.
        //

        buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority );

        if (!buffer) {
                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                MmUnlockPages(mdl);
                IoFreeMdl(mdl);
                break;
        }

        //
        // Now you can safely read the data from the buffer.
        //
        SIOCTL_KDPRINT(("\tData from User (SystemAddress) : "));
        PrintChars(buffer, inBufLength);

        //
        // Once the read is over unmap and unlock the pages.
        //

        MmUnlockPages(mdl);
        IoFreeMdl(mdl);

        //
        // The same steps can be followed to access the output buffer.
        //

        mdl = IoAllocateMdl(outBuf, outBufLength,  FALSE, TRUE, NULL);
        if (!mdl)
        {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }


        try {
            //
            // Probe and lock the pages of this buffer in physical memory.
            // You can specify IoReadAccess, IoWriteAccess or IoModifyAccess.
            //

            MmProbeAndLockPages(mdl, UserMode, IoWriteAccess);
        }
        except(EXCEPTION_EXECUTE_HANDLER)
        {

            ntStatus = GetExceptionCode();
            SIOCTL_KDPRINT((
                "Exception while locking outBuf 0X%08X in METHOD_NEITHER\n",
                    ntStatus));
            IoFreeMdl(mdl);
            break;
        }


        buffer = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority );

        if (!buffer) {
            MmUnlockPages(mdl);
            IoFreeMdl(mdl);
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }
        //
        // Write to the buffer
        //

        RtlCopyBytes(buffer, data, outBufLength);

        SIOCTL_KDPRINT(("\tData to User : %s\n", buffer));
        PrintChars(buffer, datalen);

        MmUnlockPages(mdl);

        //
        // Free the allocated MDL
        //

        IoFreeMdl(mdl);

        //
        // Assign the length of the data copied to IoStatus.Information
        // of the Irp and complete the Irp.
        //

        Irp->IoStatus.Information = (outBufLength<datalen?outBufLength:datalen);

        break;

    case IOCTL_SIOCTL_METHOD_IN_DIRECT:

        //
        // In this type of transfer,  the I/O manager allocates a system buffer
        // large enough to accommodatethe User input buffer, sets the buffer address
        // in Irp->AssociatedIrp.SystemBuffer and copies the content of user input buffer
        // into the SystemBuffer. For the user output buffer, the  I/O manager
        // probes to see whether the virtual address is readable in the callers
        // access mode, locks the pages in memory and passes the pointer to
        // MDL describing the buffer in Irp->MdlAddress.
        //

        SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_IN_DIRECT\n"));

        PrintIrpInfo(Irp);

        inBuf = Irp->AssociatedIrp.SystemBuffer;

        SIOCTL_KDPRINT(("\tData from User in InputBuffer: "));
        PrintChars(inBuf, inBufLength);

        //
        // To access the output buffer, just get the system address
        // for the buffer. For this method, this buffer is intended for transfering data
        // from the application to the driver.
        //

        buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

        if (!buffer) {
            ntStatus = STATUS_INSUFFICIENT_RESOURCES;
            break;
        }

        SIOCTL_KDPRINT(("\tData from User in OutputBuffer: "));
        PrintChars(buffer, outBufLength);

        //
        // Return total bytes read from the output buffer.
        // Note OutBufLength = MmGetMdlByteCount(Irp->MdlAddress)
        //

        Irp->IoStatus.Information = MmGetMdlByteCount(Irp->MdlAddress);

        //
        // NOTE: Changes made to the  SystemBuffer are not copied
        // to the user input buffer by the I/O manager
        //

      break;

    case IOCTL_SIOCTL_METHOD_OUT_DIRECT:

        //
        // In this type of transfer, the I/O manager allocates a system buffer
        // large enough to accommodate the User input buffer, sets the buffer address
        // in Irp->AssociatedIrp.SystemBuffer and copies the content of user input buffer
        // into the SystemBuffer. For the output buffer, the I/O manager
        // probes to see whether the virtual address is writable in the callers
        // access mode, locks the pages in memory and passes the pointer to MDL
        // describing the buffer in Irp->MdlAddress.
        //


        SIOCTL_KDPRINT(("Called IOCTL_SIOCTL_METHOD_OUT_DIRECT\n"));

        PrintIrpInfo(Irp);


        inBuf = Irp->AssociatedIrp.SystemBuffer;

        SIOCTL_KDPRINT(("\tData from User : "******"\tData to User : "******"ERROR: unrecognized IOCTL %x\n",
            irpSp->Parameters.DeviceIoControl.IoControlCode));
        break;
    }

End:
    //
    // Finish the I/O operation by simply completing the packet and returning
    // the same status as in the packet itself.
    //

    Irp->IoStatus.Status = ntStatus;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return ntStatus;
}
Example #10
0
NTSTATUS OnDriverDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    PIO_STACK_LOCATION IrpSp;
    ULONG ControlCode = 0;
    ULONG dwBytesWritten = 0;
    PCHAR pInBuf = NULL, pOutBuf = NULL;
    KAFFINITY affinity = 0;
    UNREFERENCED_PARAMETER(DeviceObject);
    IrpSp = IoGetCurrentIrpStackLocation(Irp);
    ControlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
    affinity = KeQueryActiveProcessors();
    Irp->IoStatus.Information = 0;
    switch (ControlCode) {
    case IOCTL_GET_SYSTEM_MODULES:
    {
        ULONG bytes = 0;
        PRTL_PROCESS_MODULES pMods = NULL;
        DbgPrint ("[R2K]  IOCTL_GET_SYSTEM_MODULES\n");
        if (!Irp->AssociatedIrp.SystemBuffer) {
            DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: STATUS_INVALID_PARAMETER\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        pInBuf = Irp->AssociatedIrp.SystemBuffer;
        pOutBuf = Irp->AssociatedIrp.SystemBuffer;
        Status = ZwQuerySystemInformation (SystemModuleInformation, 0, bytes, &bytes);
        if (bytes == 0) {
            DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: Invalid SystemModuleInformation size\n");
            Status = STATUS_UNSUCCESSFUL;
            break;
        }
        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < bytes) {
            DbgPrint ("[R2K] IOCTL_GET_SYSTEM_MODULES ERROR: STATUS_BUFFER_TOO_SMALL\n");
            Status = STATUS_BUFFER_TOO_SMALL;
            break;
        }
        pMods = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag (NonPagedPool, bytes, 'domP');
        RtlZeroMemory(pMods, bytes);
        Status = ZwQuerySystemInformation (SystemModuleInformation, pMods, bytes, &bytes);
        RtlCopyMemory (pOutBuf, (void*)pMods, bytes);
        if (pMods)
            ExFreePoolWithTag (pMods, 'domP');
        dwBytesWritten = bytes;
        Status = STATUS_SUCCESS;
        break;
    }
    case IOCTL_READ_KERNEL_MEM:
    {
        UINT32 len = 0;
        LARGE_INTEGER virt_addr = { 0x0, 0x0 };
        if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) {
            DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: STATUS_INVALID_PARAMETER\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        pInBuf = Irp->AssociatedIrp.SystemBuffer;
        pOutBuf = Irp->AssociatedIrp.SystemBuffer;
        virt_addr.LowPart = ((UINT32*)pInBuf)[0];
        virt_addr.HighPart = ((UINT32*)pInBuf)[1];
        len = ((UINT32*)pInBuf)[2];
        if (!len)
            len = 4;
        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len) {
            DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM  ERROR: STATUS_BUFFER_TOO_SMALL\n");
            Status = STATUS_BUFFER_TOO_SMALL;
            break;
        }
        __try  {
            // is addres + len valid page?
            if (!MmIsAddressValid ((void*)(LONG_PTR)(virt_addr.QuadPart + len))) {
                DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Error page not valid at addres + len %p\n", (virt_addr.QuadPart + len));
                Status = STATUS_ACCESS_DENIED;
                break;
            }
            if (MmIsAddressValid ((void*)(LONG_PTR)virt_addr.QuadPart)) {
                DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Reading address: %p\n", virt_addr.QuadPart);
                DbgPrint ("                             Bytes to read  : %u\n", len);
                RtlCopyMemory (pOutBuf, (void*)(LONG_PTR)virt_addr.QuadPart, len);
                Status = STATUS_SUCCESS;
            }
            else {
                DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM: Error page not valid %p\n", virt_addr.QuadPart);
                Status = STATUS_ACCESS_DENIED;
                break;
            }
        } __except (EXCEPTION_EXECUTE_HANDLER) {
            Status = GetExceptionCode ();
            DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: exception code 0x%X\n", Status);
            break;
        }
        if (NT_SUCCESS (Status)) {
            dwBytesWritten = len;
        }
        break;
    }
    case IOCTL_WRITE_KERNEL_MEM:
    {
        UINT32 len = 0;
        LARGE_INTEGER virt_addr = { 0x0, 0x0 };
        unsigned char* buffer = 0;
        if (!Irp->AssociatedIrp.SystemBuffer || IrpSp->Parameters.DeviceIoControl.InputBufferLength < 4 * sizeof(UINT32)) {
            DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM ERROR: STATUS_INVALID_PARAMETER\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        pInBuf = Irp->AssociatedIrp.SystemBuffer;
        pOutBuf = Irp->AssociatedIrp.SystemBuffer;
        virt_addr.LowPart = ((UINT32*)pInBuf)[0];
        virt_addr.HighPart = ((UINT32*)pInBuf)[1];
        len = ((UINT32*)pInBuf)[2];
        buffer = (unsigned char *)&((UINT32*)pInBuf)[3];
        if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength - (4 * sizeof(UINT32))) < len) {
            DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM ERROR: buffer smaller than specified\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        __try {
            // is addres + len valid page?
            if (!MmIsAddressValid ((void*)(LONG_PTR)(virt_addr.QuadPart + len))) {
                DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Error page not valid at addres + len %p\n", (virt_addr.QuadPart + len));
                Status = STATUS_ACCESS_DENIED;
                break;
            }
            if (MmIsAddressValid ((void*)(LONG_PTR)virt_addr.QuadPart)) {
                DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Writing address: %p\n", virt_addr.QuadPart);
                DbgPrint ("                              Bytes to Write : %u\n", len);
                RtlCopyMemory ((void*)(LONG_PTR)virt_addr.QuadPart, (void*)buffer, len);
                Status = STATUS_SUCCESS;
            } else {
                DbgPrint ("[R2K] IOCTL_WRITE_KERNEL_MEM: Error page not valid %p\n", virt_addr.QuadPart);
                Status = STATUS_ACCESS_DENIED;
                break;
            }
        } __except (EXCEPTION_EXECUTE_HANDLER) {
            Status = GetExceptionCode ();
            DbgPrint ("[R2K] IOCTL_READ_KERNEL_MEM ERROR: exception code 0x%X\n", Status);
            break;
        }
        if (NT_SUCCESS(Status)) {
            dwBytesWritten = len;
        }
        break;
    }
    case IOCTL_READ_PHYS_MEM:
    {
        UINT32 len = 0;
        PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };
        DbgPrint ("[R2K]  IOCTL_READ_PHYS_MEM\n");
        if (!Irp->AssociatedIrp.SystemBuffer ||	IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) {
            DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        pInBuf = Irp->AssociatedIrp.SystemBuffer;
        pOutBuf = Irp->AssociatedIrp.SystemBuffer;
        phys_addr.LowPart = ((UINT32*)pInBuf)[0];
        phys_addr.HighPart = ((UINT32*)pInBuf)[1];
        len = ((UINT32*)pInBuf)[2];
        if (!len) len = 4;
        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < len) {
            DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM  ERROR: STATUS_BUFFER_TOO_SMALL\n");
            Status = STATUS_BUFFER_TOO_SMALL;
            break;
        }
        __try {
            void * va = MmMapIoSpace (phys_addr, len, MmCached);
            if (!va) {
                DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: no space for mapping\n");
                return STATUS_UNSUCCESSFUL;
            }
            DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM reading %d bytes from physical address 0x%08x_%08x (virtual = %p)", len, phys_addr.HighPart, phys_addr.LowPart, va);
            RtlCopyMemory (pOutBuf, va, len);
            MmUnmapIoSpace (va, len);
            Status = STATUS_SUCCESS;

        } __except (EXCEPTION_EXECUTE_HANDLER) {
            Status = GetExceptionCode ();
            DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM ERROR: exception code 0x%X\n", Status);
            break;
        }
        if (NT_SUCCESS(Status)) {
            DbgPrint ("[R2K] IOCTL_READ_PHYS_MEM Contents:\n");
            //DumpBuffer((unsigned char *)pOutBuf, min(len, 0x100));
            dwBytesWritten = len;
        }
        break;
    }
    case IOCTL_WRITE_PHYS_MEM:
    {
        UINT32 len = 0;
        PHYSICAL_ADDRESS phys_addr = { 0x0, 0x0 };
        DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM\n");
        if (Irp->AssociatedIrp.SystemBuffer) {
            pInBuf = Irp->AssociatedIrp.SystemBuffer;
            pOutBuf = Irp->AssociatedIrp.SystemBuffer;
            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 3 * sizeof(UINT32)) {
                DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n");
                Status = STATUS_INVALID_PARAMETER;
                break;
            }
            phys_addr.LowPart = ((UINT32*)pInBuf)[0];
            phys_addr.HighPart = ((UINT32*)pInBuf)[1];
            len = ((UINT32*)pInBuf)[2];
            pInBuf = (PCHAR)(((UINT32*)pInBuf) + 3);
            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < len + 3 * sizeof(UINT32)) {
                DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: STATUS_INVALID_PARAMETER\n");
                Status = STATUS_INVALID_PARAMETER;
                break;
            }
            __try {
                void * va = MmMapIoSpace (phys_addr, len, MmCached);
                if (!va) {
                    DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: no space for mapping\n");
                    return STATUS_UNSUCCESSFUL;
                }
                //DbgPrint("[R2K] IOCTL_WRITE_PHYS_MEM writing %d bytes to physical address 0x%08x_%08x (virtual = %#010x)", len, phys_addr.HighPart, phys_addr.LowPart, (unsigned int)va);
                RtlCopyMemory (va, pInBuf, len);
                MmUnmapIoSpace (va, len);
                Status = STATUS_SUCCESS;
            } __except (EXCEPTION_EXECUTE_HANDLER) {
                Status = GetExceptionCode ();
                DbgPrint ("[R2K] IOCTL_WRITE_PHYS_MEM ERROR: exception code 0x%X\n", Status);
            }
        }
        break;
    }
    case IOCTL_GET_PHYSADDR:
    {
        UINT64 va = 0x0;
        PHYSICAL_ADDRESS pa = { 0x0, 0x0 };
        pInBuf = Irp->AssociatedIrp.SystemBuffer;
        pOutBuf = Irp->AssociatedIrp.SystemBuffer;
        DbgPrint ("[R2K] IOCTL_GET_PHYSADDR\n");
        if (!Irp->AssociatedIrp.SystemBuffer ||
                IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(UINT64)) {
            DbgPrint ("[R2K] IOCTL_GET_PHYSADDR ERROR: STATUS_INVALID_PARAMETER\n");
            Status = STATUS_INVALID_PARAMETER;
            break;
        }
        if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT64)) {
            DbgPrint ("[R2K] IOCTL_GET_PHYSADDR ERROR: STATUS_BUFFER_TOO_SMALL\n");
            Status = STATUS_BUFFER_TOO_SMALL;
            break;
        }
        RtlCopyBytes (&va, (unsigned char*)Irp->AssociatedIrp.SystemBuffer, sizeof(UINT64));
        pa = MmGetPhysicalAddress ((PVOID)(ULONG_PTR)va);
        DbgPrint ("[R2K] IOCTL_GET_PHYSADDR Traslated virtual address 0x%I64X to physical: 0x%I64X\n", va, pa.QuadPart, pa.LowPart);
        RtlCopyBytes (Irp->AssociatedIrp.SystemBuffer, (void*)&pa, sizeof(UINT64));
        IrpSp->Parameters.Read.Length = sizeof(UINT64);
        dwBytesWritten = IrpSp->Parameters.Read.Length;
        Status = STATUS_SUCCESS;
        break;
    }
    default:
        Status = STATUS_NOT_SUPPORTED;
        break;
    }
Example #11
0
NTSTATUS RegistryCallback(IN PVOID CallbackContext, 
IN PVOID Argument1, 
IN PVOID Argument2)
{  
	NTSTATUS st=STATUS_SUCCESS;
    BOOLEAN exception = FALSE;  
	BOOLEAN flag;
    int type;
    UNICODE_STRING registryPath;
    UCHAR* registryData = NULL;
    ULONG registryDataLength = 0;
    ULONG registryDataType = 0;
    /* Allocate a large 64kb string ... maximum path name allowed in windows */
    registryPath.Length = 0;
    registryPath.MaximumLength = NTSTRSAFE_UNICODE_STRING_MAX_CCH * sizeof(WCHAR);
    registryPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, registryPath.MaximumLength, REGISTRY_POOL_TAG); 
    if(registryPath.Buffer == NULL)
	{
     return STATUS_SUCCESS;
	}

    //registryEvent.eventType = (REG_NOTIFY_CLASS)Argument1;
    type = (REG_NOTIFY_CLASS)Argument1;
    try
	{
       /* Large switch statement for all registry events ... fairly easy to understand */
       switch(type)
	   {
		  case RegNtPreDeleteKey:
		{
			PREG_DELETE_KEY_INFORMATION deleteKey = (PREG_DELETE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteKey->Object;
		   GetProcessName(aProcessName);
			flag=GetRegistryObjectCompleteName(&registryPath, NULL, deleteKey->Object);
			if(flag) 
			{
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				st=WaitForUserAnswer();
				if (!NT_SUCCESS(st))
					return STATUS_INVALID_PARAMETER;
				RtlFreeAnsiString(&astr);
			}
		    break;		 
		}
		  case RegNtPreDeleteValueKey:
		{
			
			PREG_DELETE_VALUE_KEY_INFORMATION deleteValueKey = (PREG_DELETE_VALUE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)deleteValueKey->Object;
			GetProcessName(aProcessName);
			flag=GetRegistryObjectCompleteName(&registryPath, NULL, deleteValueKey->Object);
			if((flag) && (deleteValueKey->ValueName->Length > 0)) 
			{
				RtlUnicodeStringCatString(&registryPath,L"\\");
				RtlUnicodeStringCat(&registryPath, deleteValueKey->ValueName);
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				st=WaitForUserAnswer();
				if (!NT_SUCCESS(st))
				       return STATUS_INVALID_PARAMETER;
				RtlFreeAnsiString(&astr);
			}
				  break;
		}
		  case RegNtPreSetValueKey:
		{
			PREG_SET_VALUE_KEY_INFORMATION setValueKey = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
			PCM_KEY_BODY my_CM_KEY_BODY=(PCM_KEY_BODY)setValueKey->Object;
		    GetProcessName(aProcessName);
			flag = GetRegistryObjectCompleteName(&registryPath, NULL, setValueKey->Object);
			if((flag) && (setValueKey->ValueName->Length > 0)) 
			{
				registryDataType = setValueKey->Type;
				registryDataLength = setValueKey->DataSize;
				registryData = ExAllocatePoolWithTag(NonPagedPool, registryDataLength, REGISTRY_POOL_TAG);
				if(registryData != NULL)
				{
					RtlCopyBytes(registryData,setValueKey->Data,setValueKey->DataSize);
				} else {
					DbgPrint("RegistryMonitor: ERROR can't allocate memory for setvalue data\n");
				}
				RtlUnicodeStringCatString(&registryPath,L"\\");
				RtlUnicodeStringCat(&registryPath, setValueKey->ValueName);
				RtlUnicodeStringToAnsiString(&astr,&registryPath,TRUE);
				DbgPrint("[RegCreated]ProcessID %d KeyName %s!\n",PID,astr.Buffer);
				  if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					   st=WaitForUserAnswer();
				       if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServices"))
				  {
                      st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				           return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunServicesOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				  else if (strstr(astr.Buffer," \\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
                  else if (strstr(astr.Buffer,"\\REGISTRY\\MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"))
				  {
					  st=WaitForUserAnswer();
					  if (!NT_SUCCESS(st))
				            return STATUS_INVALID_PARAMETER;
				  }
				   RtlFreeAnsiString(&astr);
			}
				  break;		 
		}
	    
		  default:
			  break;
	   }
	   } except( EXCEPTION_EXECUTE_HANDLER ) {
		   /* Do nothing if an exception occured ... event won't be queued */
		   exception = TRUE;
	   }
	  
	   if(registryPath.Buffer != NULL)
	   {
		   ExFreePoolWithTag(registryPath.Buffer, REGISTRY_POOL_TAG);
	   }
       /* Always return a success ... we aren't doing any filtering, just monitoring */
       return STATUS_SUCCESS;
}
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP IRP) 
{
	KdPrint(("==>DriverDeviceControl\n"));

	NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
	ULONG tmpLen=0;
	PIO_STACK_LOCATION pIoStackIrp = IoGetCurrentIrpStackLocation(IRP);

	switch (pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) 
	{
		case IOCTL_SET_PROTECT_PID:
			KdPrint(("IOCTL_SET_PROTECT_PID\n"));

			{
				unsigned char pUnPack[256];
				int unPackLength;

				unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);

				if (unPackLength>0)
				{
					PPID_INFO pInputBuffer = (PPID_INFO)pUnPack;
					int iStringLength = unPackLength;

					if(iStringLength != sizeof(PID_INFO)) // The PID should contain exactly 1 member.
						break;

					__int64 elapsedTime = __rdtsc() - pInputBuffer->currentTime;

					KdPrint(("IOCTL_SET_PROTECT_PID elapsed time: %I64d.\n", elapsedTime));

					if((elapsedTime > COMMUNICATE_TIME_LIMIT)||(elapsedTime <=COMMUNICATE_TIME_DOWN))
					{
						KdPrint(("IOCTL_SET_PROTECT_PID exceeds time limit.\n"));
					} else {
					
					// 加入进程 ID
						AddProtectPID(pInputBuffer->PID[0]);
					}

					ntStatus = STATUS_SUCCESS;
				}
			}
			break;

		case IOCTL_GET_PROTECT_PIDS:
			KdPrint(("IOCTL_GET_PROTECT_PIDS\n"));

			if (IRP->MdlAddress) 
			{
				PPID_INFO pUserBuffer = (PPID_INFO)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority);
				ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength;
	
				ULONG PIDLength = OutputLength - sizeof(PID_INFO) + sizeof(UINT32);//1025*sizeof(unsigned int),last one for another

				// add by bh
				PPID_INFO tmpBuf=(PPID_INFO)ExAllocatePoolWithTag(PagedPool,OutputLength-sizeof(UINT32),'bnak');
				if(!tmpBuf)
					return ntStatus;
				
				///judge safe
				KdPrint(("entry check hook safe!\n"));
				if(checkHookSafe())
				{
					KdPrint(("              safe!\n"));
					tmpBuf->count = GetPIDs(tmpBuf->PID, PIDLength / sizeof(UINT32));
					tmpBuf->currentTime = __rdtsc();
					ULONG bufLength=sizeof(PID_INFO)+tmpBuf->count*sizeof(UINT32);
					tmpLen = UploadPack((PUCHAR)tmpBuf , bufLength , (PUCHAR)pUserBuffer);
				}
				else
				{
					KdPrint( ("           unfalse\n"));
					RtlZeroMemory(tmpBuf,OutputLength-sizeof(UINT32));
					tmpLen=0;
				}
				///
				//pUserBuffer->count = GetPIDs(pUserBuffer->PID, PIDLength / sizeof(UINT32));
			    //pUserBuffer->currentTime = __rdtsc();
				ExFreePoolWithTag(tmpBuf,'bnak');
				/////  end 

				ntStatus = STATUS_SUCCESS;
			}
			break;

		case IOCTL_SET_SECU_PATHS:
			KdPrint(("IOCTL_SET_SECU_PATHS\n"));
			{
				/////////////////add by bh
				if(!g_tmpB)
					setStartTime();
				////////////////end 

				/*PUCHAR pInputBuffer = (PUCHAR)IRP->AssociatedIrp.SystemBuffer;
				int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength;

				ClearSecurePaths();

				ULONG index = 0;
				while(index < iStringLength)
				{
					ULONG length = *(PULONG)((ULONG)pInputBuffer + index);
					index += 4;
					if(index + length >= iStringLength)
						break;

					AddSecurePath((WCHAR*)((ULONG)pInputBuffer + index), length);

					index += length * 2 + 2;
				}*/

				ntStatus = STATUS_SUCCESS;
			}
			break;

		case IOCTL_SET_SECU_MD5:
			KdPrint(("IOCTL_SET_SECU_MD5\n"));
			{
				PUCHAR pInputBuffer;
				int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength;

				unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab');
				int unPackLength;

				unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);
	
				//add by bh
				//iStringLength=*((ULONG*)pUnPack );
				RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) );
				pInputBuffer=pUnPack+sizeof(ULONG);

				//if(!g_globalTime)
				//g_globalTime=*((__int64 *)(pInputBuffer+iStringLength) );
				RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer+iStringLength),8 );


				__int64 elapseTime=__rdtsc()-g_globalTime;
	
				if( (elapseTime<COMMUNICATE_TIME_LIMIT) && (elapseTime>=COMMUNICATE_TIME_DOWN)  )
				{
					KdPrint( ("entry elapse check!           ") );
					if (unPackLength>0)
					{KdPrint( ("entry length check!           ") );
						ClearHash();
						
						for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE)
							AddSecureHash(pInputBuffer + i);

						ntStatus = STATUS_SUCCESS;
					}
				}
			
				ExFreePoolWithTag(pUnPack,'knab');
				//
			}
			break;

		case IOCTL_SET_UP_UNLOAD:
			KdPrint(("IOCTL_SET_UP_UNLOAD\n"));
			DeviceObject->DriverObject->DriverUnload = DriverUnload;
			ntStatus = STATUS_SUCCESS;
			break;
	}

	IRP->IoStatus.Status = 0;
	IRP->IoStatus.Information = tmpLen ;
	IoCompleteRequest(IRP, IO_NO_INCREMENT);
	KdPrint(("<==DriverDeviceControl\n"));
	return ntStatus;
}
NTSTATUS DispatchDeviceIoControl( PDEVICE_OBJECT fdo, PIRP Irp )
{
    ULONG    info;
    NTSTATUS status = STATUS_SUCCESS;
    
    PDEVICE_EXTENSION  pdx = (PDEVICE_EXTENSION) fdo->DeviceExtension;
    PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);

    status = IoAcquireRemoveLock( &pdx->RemoveLock, Irp );
    
    if(!NT_SUCCESS(status))
    {
        return CompleteRequest(Irp, status, 0);
    }

    info = 0;
    
    switch(stack->Parameters.DeviceIoControl.IoControlCode)
    {
        case IOCTL_MFUSB_PORT_NAME:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->operationsInterfaceName.Length)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->operationsInterfaceName.Length;

                    if(pdx->operationsInterfaceName.Buffer != NULL)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->operationsInterfaceName.Buffer, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_MANUFACTURER:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->manufacturer.Length)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->manufacturer.Length;

                    if(pdx->manufacturer.Buffer != NULL)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->manufacturer.Buffer, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_PRODUCT:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->product.Length)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->product.Length;
                    
                    if(pdx->product.Buffer != NULL)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->product.Buffer, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_SERIAL_NUMBER:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->serialNumber.Length)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->serialNumber.Length;

                    if(pdx->serialNumber.Buffer != NULL)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->serialNumber.Buffer, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_DISPLAY_NAME:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->displayName.Length)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->displayName.Length;

                    if(pdx->displayName.Buffer != NULL)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, pdx->displayName.Buffer, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_DEVICE_HASH:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < pdx->devHash->bLength)
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = pdx->devHash->bLength;

                    if(info > 0)
                    {
                        RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->devHash->bString, info);
                    }
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_READ_AVAILABLE:
            {
                ULONG available = FifoAvailable(pdx);
                
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = sizeof(ULONG);
                    
                    RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &available, sizeof(ULONG));
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_VENDOR_ID:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USHORT))
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = sizeof(USHORT);
                    
                    RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->dd.idVendor, info);
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        case IOCTL_MFUSB_PRODUCT_ID:
            {
                if(stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(USHORT))
                {
                    status = STATUS_BUFFER_TOO_SMALL;
                } 
                else 
                {
                    info = sizeof(USHORT);
                    
                    RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &pdx->dd.idProduct, info);
                    
                    status = STATUS_SUCCESS;
                }
            }
            break;
            
        default:
            KdPrint((DRIVERNAME " - Unrecognized IOCTL\n"));
            
            status = STATUS_INVALID_PARAMETER;
            
            break;
    }

    IoReleaseRemoveLock( &pdx->RemoveLock, Irp );

    if(!NT_SUCCESS(status))
    {
        info = 0;
    }

    return CompleteRequest( Irp, status, info );
}
Example #14
0
NTSTATUS
PeachDeviceControl(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp
    )

/*++

Routine Description:

    This routine is called by the I/O system to perform a device I/O
    control function.

Arguments:

    DeviceObject - a pointer to the object that represents the device
        that I/O is to be done on.

    Irp - a pointer to the I/O Request Packet for this request.

Return Value:

    NT status code

--*/

{
    PIO_STACK_LOCATION  irpSp;// Pointer to current stack location
    NTSTATUS            ntStatus = STATUS_SUCCESS;// Assume success
    ULONG               inBufLength; // Input buffer length
    ULONG               outBufLength; // Output buffer length
	char				ret;

    UNREFERENCED_PARAMETER(DeviceObject);

    PAGED_CODE();

    irpSp = IoGetCurrentIrpStackLocation( Irp );
    inBufLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
    outBufLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;

    if (!inBufLength || !outBufLength)
    {
        ntStatus = STATUS_INVALID_PARAMETER;
        goto End;
    }

    //
    // Determine which I/O control code was specified.
    //

    switch ( irpSp->Parameters.DeviceIoControl.IoControlCode )
    {
	/* Sent by Peach to say "Starting iteration" */
	case IOCTL_PEACH_METHOD_START:

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_START\n"));

		started = TRUE;

		// TODO: Put any code here that runs on start.

		break;

	/* Sent by Peach to say "Stopping iteration" */
	case IOCTL_PEACH_METHOD_STOP:

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_STOP\n"));

		started = FALSE;

		// TODO: Put any code here that runs on STOP

		break;

	/* Sent by Peach to indicate a "call" data is "method name".
	 * This will be followed by one or more DATA ioctls to deliver
	 * each parameter's data.
	 */
	case IOCTL_PEACH_METHOD_CALL:

		if(methodName != NULL)
		{
			ExFreePoolWithTag(methodName, TAG);
			methodName = NULL;
		}

		methodName = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG);
		RtlCopyBytes(methodName, Irp->AssociatedIrp.SystemBuffer, inBufLength);

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_CALL: [%s]\nh", methodName));

		break;

	/* Sent by Peach to indicate a "property" set, data is "property name".
	 * This will be followed by a single DATA ioctl. */
	case IOCTL_PEACH_METHOD_PROPERTY:

		if(propertyName != NULL)
		{
			ExFreePoolWithTag(propertyName, TAG);
			propertyName = NULL;
		}

		propertyName = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG);
		RtlCopyBytes(propertyName, Irp->AssociatedIrp.SystemBuffer, inBufLength);

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_PROPERTY: [%s]\n", propertyName));

		break;

	/* Sent by Peach to query if driver is ready for next test.  Driver
	 * should send back TRUE (1) or FALSE (0) */
	case IOCTL_PEACH_METHOD_NEXT:

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_NEXT\n"));

		// TODO: Change ret based on our status
		ret = 1;

		RtlCopyBytes(Irp->AssociatedIrp.SystemBuffer, &ret, 1);
        Irp->IoStatus.Information = 1;

		break;

	/* Sent by Peach to deliver DATA to Kernel */
    case IOCTL_PEACH_METHOD_DATA:

		PEACH_KDPRINT(("IOCTL_PEACH_METHOD_DATA: Length: %d\n", inBufLength));

		if(data != NULL)
		{
			ExFreePoolWithTag(data, TAG);
			data = NULL;
		}

		data = ExAllocatePoolWithTag(NonPagedPool, inBufLength, TAG);
		RtlCopyBytes(data, Irp->AssociatedIrp.SystemBuffer, inBufLength);

		// TODO: Place code here to fuzz something!!

		break;

    default:

        //
        // The specified I/O control code is unrecognized by this driver.
        //

        ntStatus = STATUS_INVALID_DEVICE_REQUEST;
        PEACH_KDPRINT(("ERROR: unrecognized IOCTL %x\n",
            irpSp->Parameters.DeviceIoControl.IoControlCode));
        break;
    }

End:
    //
    // Finish the I/O operation by simply completing the packet and returning
    // the same status as in the packet itself.
    //

    Irp->IoStatus.Status = ntStatus;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return ntStatus;
}
Example #15
0
/**
*  驱动分发函数,相应上层应用的各种操作命令
*
*/
NTSTATUS DispatchDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP IRP) 
{
	::KeWaitForSingleObject(&g_DispatchMutex,Executive,KernelMode,FALSE,NULL);

	NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
	ULONG tmpLen = 0;
	PIO_STACK_LOCATION pIoStackIrp = IoGetCurrentIrpStackLocation(IRP);

	switch (pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) 
	{
		case IOCTL_SET_PROTECT_PID://设置保护PID
			KdPrint(("IOCTL_SET_PROTECT_PID\n"));

			{
				unsigned char pUnPack[256];
				int unPackLength;

				unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);

				if (unPackLength > 0)
				{
					PPID_INFO pInputBuffer = (PPID_INFO)pUnPack;
					int iStringLength = unPackLength;

					if(iStringLength != sizeof(PID_INFO)) 
						break;

					__int64 elapsedTime = __rdtsc() - pInputBuffer->currentTime;

					KdPrint(("IOCTL_SET_PROTECT_PID elapsed time: %I64d.\n", elapsedTime));

					if((elapsedTime > COMMUNICATE_TIME_LIMIT)||(elapsedTime <=COMMUNICATE_TIME_DOWN))
					{
						KdPrint(("IOCTL_SET_PROTECT_PID exceeds time limit.\n"));
					} 
					else 
					{					
					// 加入进程 ID
						AddProtectPID(pInputBuffer->PID[0]);
					}

					ntStatus = STATUS_SUCCESS;
				}
			}
			break;

		case IOCTL_GET_PROTECT_PIDS:///判断驱动是否在正常工作
			KdPrint(("IOCTL_GET_PROTECT_PIDS\n"));

			if (IRP->MdlAddress) 
			{
				PPID_INFO pUserBuffer = (PPID_INFO)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority);
				if(pUserBuffer == NULL)
					return ntStatus;
				ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength;
	
				ULONG PIDLength = OutputLength - sizeof(PID_INFO) + sizeof(UINT32);

				PPID_INFO tmpBuf=(PPID_INFO)ExAllocatePoolWithTag(PagedPool,OutputLength-sizeof(UINT32),'bak');
				if(!tmpBuf)
					return ntStatus;
				
				
				KdPrint(("entry check hook safe!\n"));
				if(checkHookSafe())
				{
					tmpBuf->count = GetKernelPIDs(tmpBuf->PID, PIDLength / sizeof(UINT32));
					tmpBuf->currentTime = __rdtsc();
					ULONG bufLength = sizeof(PID_INFO) + tmpBuf->count*sizeof(UINT32);
					tmpLen = UploadPack((PUCHAR)tmpBuf , bufLength , (PUCHAR)pUserBuffer);
				}
				else
				{
					RtlZeroMemory(tmpBuf,OutputLength-sizeof(UINT32));
					tmpLen = 0;
				}

				ExFreePoolWithTag(tmpBuf,'bak');

				ntStatus = STATUS_SUCCESS;
			}
			break;

		case IOCTL_SET_SECU_PATHS://无效
			KdPrint(("IOCTL_SET_SECU_PATHS\n"));
			{
				ntStatus = STATUS_SUCCESS;
			}
			break;

		case IOCTL_SET_SECU_MD5://设置白名单哈希列表
			KdPrint(("IOCTL_SET_SECU_MD5\n"));
			{
				PUCHAR pInputBuffer;
				int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength;

				unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab');
				int unPackLength;

				unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);
	
				RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) );
				pInputBuffer = pUnPack + sizeof(ULONG);
				RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer + iStringLength),8 );


				__int64 elapseTime = __rdtsc() - g_globalTime;

				if( (elapseTime < COMMUNICATE_TIME_LIMIT) && (elapseTime >= COMMUNICATE_TIME_DOWN)  )
				{
					if (unPackLength > 0)
					{
						for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE)
							AddSecureHash(pInputBuffer + i);

						getSecuTable();
						ClearHash();

						ntStatus = STATUS_SUCCESS;
					}
				}
			
				ExFreePoolWithTag(pUnPack,'knab');
				//
			}
			break;
			/////////////
		case IOCTL_SET_BLACK_MD5://设置黑名单哈希列表
			KdPrint(("IOCTL_SET_SECU_MD5\n"));
			{
				PUCHAR pInputBuffer;
				int iStringLength = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength;

				unsigned char * pUnPack=(UCHAR *)ExAllocatePoolWithTag(PagedPool,iStringLength,'knab');
				int unPackLength;

				unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);

				RtlCopyBytes((PVOID)&iStringLength,(PVOID)pUnPack,sizeof(ULONG) );
				pInputBuffer = pUnPack + sizeof(ULONG);
				RtlCopyBytes((PVOID)&g_globalTime,(PVOID)(pInputBuffer + iStringLength),8 );

				__int64 elapseTime = __rdtsc() - g_globalTime;

				if( (elapseTime < COMMUNICATE_TIME_LIMIT) && (elapseTime >= COMMUNICATE_TIME_DOWN)  )
				{
					if (unPackLength > 0)
					{
						for(int i = 0; i <= iStringLength - HASH_SIZE; i += HASH_SIZE)
							AddBlackHash(pInputBuffer + i);

						getBlackTable();
						ClearBlackHash();

						ntStatus = STATUS_SUCCESS;
					}
				}

				ExFreePoolWithTag(pUnPack,'knab');
				//
			}
			break;
			/////////////

		case IOCTL_SET_UP_UNLOAD://设置卸载驱动函数
			KdPrint(("IOCTL_SET_UP_UNLOAD\n"));
			while(g_bBusy)
			{
				LARGE_INTEGER interval;
				interval.QuadPart = -3 * 1000 * 1000;//滞后3秒进行卸载
				KeDelayExecutionThread(KernelMode, FALSE, &interval);
			}
			DeviceObject->DriverObject->DriverUnload= DDKUnload;	
			ntStatus = STATUS_SUCCESS;
			break;

		case IOCTL_GET_DRIVER_STATUS://得到驱动接受白名单状态
			{
			//////////////////////////////////////////////////////
				unsigned char pUnPack[256];
				int unPackLength;

				unPackLength = DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,pUnPack);

				if (unPackLength > 0)
				{
					MYDRIVERSTATUS type = *(MYDRIVERSTATUS *)pUnPack;

					PUCHAR pUserBuffer = (PUCHAR)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority);// 在虚拟内存紧张时会返回NULL
					if(pUserBuffer == NULL)
						return ntStatus;

					ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength;

					ULONG * tmpBuf=(ULONG *)ExAllocatePoolWithTag(PagedPool,4,'bnak');
					if(!tmpBuf)
						return ntStatus;

					if(type == DRIVER_RECEIVED)//是否接受到白名单
					{
						if(!isRestart())  g_isReceive=false;
						*tmpBuf = g_isReceive ? 1 : 0;
						tmpLen = UploadPack((PUCHAR)tmpBuf , 4 , (PUCHAR)pUserBuffer);
					}
		
					ExFreePoolWithTag(tmpBuf,'bnak');
				}		

				ntStatus = STATUS_SUCCESS;
			//////////////////////////////////////////////////////
			}
			break;

			case IOCTL_SET_HANDLE://得到同步句柄
				{
					if(pEvent)
						ObDereferenceObject(pEvent);

					HANDLE hEvent = NULL; 
					int unPackLength;

					unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,(unsigned char *)&hEvent);

					if (unPackLength>0)
					{
						ObReferenceObjectByHandle(hEvent , EVENT_MODIFY_STATE, *ExEventObjectType, KernelMode, (PVOID *)&pEvent, NULL);
	
						ntStatus = STATUS_SUCCESS;
					}
				}
				break;
			case IOCTL_RETURN_DATA://返回灰名单
				{	
					if (IRP->MdlAddress) 
					{
						wchar_t fName[260] = {0};
						unsigned char cHash[16] = {0};
						
						getData(fName,cHash);

						unsigned char dataBuf[260*sizeof(wchar_t) + 16 + 4*4] = {0};
						*(DWORD*)(dataBuf) = 1;
						RtlCopyMemory(dataBuf+4,fName,DATAPATHLEN);
						*(wchar_t*)(dataBuf + DATAPATHLEN -2) = L'\0';
						RtlCopyMemory(dataBuf+4+DATAPATHLEN,cHash,DATAHASHLEN);

						wchar_t * pUserBuffer = (wchar_t *)MmGetSystemAddressForMdlSafe(IRP->MdlAddress, NormalPagePriority);
						ULONG OutputLength = pIoStackIrp->Parameters.DeviceIoControl.OutputBufferLength;
		
						tmpLen = UploadPack((PUCHAR)dataBuf, 260*sizeof(wchar_t) + 16 + 4*4, (PUCHAR)pUserBuffer);
					}

					ntStatus = STATUS_SUCCESS;
				}

				break;

			case IOCTL_SET_FILTERRESULT://验证结果
				{
					char rResult;
					//bool bResult = false;
					//rResult = (*(unsigned char *)(IRP->AssociatedIrp.SystemBuffer));
					WriteSysLog(LOG_TYPE_INFO,L" IOCTL GET");
					
					int unPackLength=DownloadUnPack((unsigned char *)IRP->AssociatedIrp.SystemBuffer,pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength,(unsigned char *)&rResult);

					//g_bPassFilter = (rResult == 1) ? true : false;
					if (unPackLength>0)
					{
						g_bPassFilter = (rResult == 1) ? true : false;
					}
					else
					{
						WriteSysLog(LOG_TYPE_INFO,L" IOCTL LError");
						g_bPassFilter = false;
					}
					WriteSysLog(LOG_TYPE_INFO,L" IOCTL SET");
					KeSetEvent(g_pEventFilterGo, IO_NO_INCREMENT, FALSE);
					ntStatus = STATUS_SUCCESS;
				}

				break;
	}

	IRP->IoStatus.Status = 0;
	IRP->IoStatus.Information = tmpLen ;
	IoCompleteRequest(IRP, IO_NO_INCREMENT);

	::KeReleaseMutex(&g_DispatchMutex,FALSE);

	return ntStatus;
}