Пример #1
0
NTSTATUS
DokanDispatchLock(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp) {
  PIO_STACK_LOCATION irpSp;
  NTSTATUS status = STATUS_INVALID_PARAMETER;
  PFILE_OBJECT fileObject;
  PDokanCCB ccb;
  PDokanFCB fcb = NULL;
  PDokanVCB vcb;
  PDokanDCB dcb;
  PEVENT_CONTEXT eventContext = NULL;
  ULONG eventLength;
  BOOLEAN completeIrp = TRUE;

  __try {
    DDbgPrint("==> DokanLock\n");

    irpSp = IoGetCurrentIrpStackLocation(Irp);
    fileObject = irpSp->FileObject;

    if (fileObject == NULL) {
      DDbgPrint("  fileObject == NULL\n");
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }

    vcb = DeviceObject->DeviceExtension;
    if (GetIdentifierType(vcb) != VCB ||
        !DokanCheckCCB(vcb->Dcb, fileObject->FsContext2)) {
      status = STATUS_INVALID_PARAMETER;
      __leave;
    }
    dcb = vcb->Dcb;

    DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
    DokanPrintFileName(fileObject);

    switch (irpSp->MinorFunction) {
    case IRP_MN_LOCK:
      DDbgPrint("  IRP_MN_LOCK\n");
      break;
    case IRP_MN_UNLOCK_ALL:
      DDbgPrint("  IRP_MN_UNLOCK_ALL\n");
      break;
    case IRP_MN_UNLOCK_ALL_BY_KEY:
      DDbgPrint("  IRP_MN_UNLOCK_ALL_BY_KEY\n");
      break;
    case IRP_MN_UNLOCK_SINGLE:
      DDbgPrint("  IRP_MN_UNLOCK_SINGLE\n");
      break;
    default:
      DDbgPrint("  unknown function : %d\n", irpSp->MinorFunction);
      break;
    }

    ccb = fileObject->FsContext2;
    ASSERT(ccb != NULL);

    fcb = ccb->Fcb;
    ASSERT(fcb != NULL);
    DokanFCBLockRW(fcb);

    if (dcb->FileLockInUserMode) {

      eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
      eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);

      if (eventContext == NULL) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        __leave;
      }

      eventContext->Context = ccb->UserContext;
      DDbgPrint("   get Context %X\n", (ULONG)ccb->UserContext);

      // copy file name to be locked
      eventContext->Operation.Lock.FileNameLength = fcb->FileName.Length;
      RtlCopyMemory(eventContext->Operation.Lock.FileName, fcb->FileName.Buffer,
                    fcb->FileName.Length);

      // parameters of Lock
      eventContext->Operation.Lock.ByteOffset =
          irpSp->Parameters.LockControl.ByteOffset;
      if (irpSp->Parameters.LockControl.Length != NULL) {
        eventContext->Operation.Lock.Length.QuadPart =
            irpSp->Parameters.LockControl.Length->QuadPart;
      } else {
        DDbgPrint("  LockControl.Length = NULL\n");
      }
      eventContext->Operation.Lock.Key = irpSp->Parameters.LockControl.Key;

      // register this IRP to waiting IRP list and make it pending status
      status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);
    } else {
      status = DokanCommonLockControl(Irp);
      completeIrp = FALSE;
    }

  } __finally {
    if(fcb)
      DokanFCBUnlock(fcb);

    if (completeIrp) {
      DokanCompleteIrpRequest(Irp, status, 0);
    }

    DDbgPrint("<== DokanLock\n");
  }

  return status;
}
Пример #2
0
VOID VIOSerialPortWrite(IN WDFQUEUE Queue,
                        IN WDFREQUEST Request,
                        IN size_t Length)
{
    NTSTATUS status;
    PVOID InBuf;
    PVOID buffer;
    PVIOSERIAL_PORT Port;
    PWRITE_BUFFER_ENTRY entry;
    WDFDEVICE Device;
    PDRIVER_CONTEXT Context;
    WDFMEMORY EntryHandle;

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,
        "--> %s Request: %p Length: %d\n", __FUNCTION__, Request, Length);

    PAGED_CODE();

    Device = WdfIoQueueGetDevice(Queue);
    Port = RawPdoSerialPortGetData(Device)->port;
    if (Port->Removed)
    {
        TraceEvents(TRACE_LEVEL_WARNING, DBG_WRITE,
            "Write request on a removed port %d\n", Port->PortId);
        WdfRequestComplete(Request, STATUS_OBJECT_NO_LONGER_EXISTS);
        return;
    }

    status = WdfRequestRetrieveInputBuffer(Request, Length, &InBuf, NULL);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to retrieve input buffer: %x\n", status);
        WdfRequestComplete(Request, status);
        return;
    }

    if (VIOSerialWillWriteBlock(Port))
    {
        WdfRequestComplete(Request, STATUS_CANT_WAIT);
        return;
    }

    buffer = ExAllocatePoolWithTag(NonPagedPool, Length,
        VIOSERIAL_DRIVER_MEMORY_TAG);

    if (buffer == NULL)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE, "Failed to allocate.\n");
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }

    Context = GetDriverContext(WdfDeviceGetDriver(Device));
    status = WdfMemoryCreateFromLookaside(Context->WriteBufferLookaside, &EntryHandle);
    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to allocate write buffer entry: %x.\n", status);
        ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        WdfRequestComplete(Request, STATUS_INSUFFICIENT_RESOURCES);
        return;
    }

    status = WdfRequestMarkCancelableEx(Request,
        VIOSerialPortWriteRequestCancel);

    if (!NT_SUCCESS(status))
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to mark request as cancelable: %x\n", status);
        ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        WdfObjectDelete(EntryHandle);
        WdfRequestComplete(Request, status);
        return;
    }

    RtlCopyMemory(buffer, InBuf, Length);
    WdfRequestSetInformation(Request, (ULONG_PTR)Length);

    entry = (PWRITE_BUFFER_ENTRY)WdfMemoryGetBuffer(EntryHandle, NULL);
    entry->EntryHandle = EntryHandle;
    entry->Buffer = buffer;
    entry->Request = Request;

    if (VIOSerialSendBuffers(Port, entry, Length) <= 0)
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_WRITE,
            "Failed to send user's buffer.\n");

        ExFreePoolWithTag(buffer, VIOSERIAL_DRIVER_MEMORY_TAG);
        WdfObjectDelete(EntryHandle);

        if (WdfRequestUnmarkCancelable(Request) != STATUS_CANCELLED)
        {
            WdfRequestComplete(Request, Port->Removed ?
                STATUS_INVALID_DEVICE_STATE : STATUS_INSUFFICIENT_RESOURCES);
        }
    }

    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_WRITE,"<-- %s\n", __FUNCTION__);
}
Пример #3
0
static
LRESULT
FASTCALL
co_IntCallLowLevelHook(PHOOK Hook,
                     INT Code,
                     WPARAM wParam,
                     LPARAM lParam)
{
    NTSTATUS Status;
    PTHREADINFO pti;
    PHOOKPACK pHP;
    INT Size = 0;
    UINT uTimeout = 300;
    BOOL Block = FALSE;
    ULONG_PTR uResult = 0;

    if (Hook->ptiHooked)
       pti = Hook->ptiHooked;
    else
       pti = Hook->head.pti;

    pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK);
    if (!pHP) return 0;

    pHP->pHk = Hook;
    pHP->lParam = lParam;
    pHP->pHookStructs = NULL;

// This prevents stack corruption from the caller.
    switch(Hook->HookId)
    {
       case WH_JOURNALPLAYBACK:
       case WH_JOURNALRECORD:
          uTimeout = 0;
          Size = sizeof(EVENTMSG);
          break;
       case WH_KEYBOARD_LL:
          Size = sizeof(KBDLLHOOKSTRUCT);
          break;
       case WH_MOUSE_LL:
          Size = sizeof(MSLLHOOKSTRUCT);
          break;
       case WH_MOUSE:
          uTimeout = 200;
          Block = TRUE;
          Size = sizeof(MOUSEHOOKSTRUCT);
          break;
       case WH_KEYBOARD:
          uTimeout = 200;
          Block = TRUE;
          break;
    }

    if (Size)
    {
       pHP->pHookStructs = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HOOK);
       if (pHP->pHookStructs) RtlCopyMemory(pHP->pHookStructs, (PVOID)lParam, Size);
    }

    /* FIXME: Should get timeout from
     * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
    Status = co_MsqSendMessage( pti,
                                IntToPtr(Code), // hWnd
                                Hook->HookId,   // Msg
                                wParam,
                               (LPARAM)pHP,
                                uTimeout,
                                Block,
                                MSQ_ISHOOK,
                               &uResult);
    if (!NT_SUCCESS(Status))
    {
       ERR("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status);
       if (pHP->pHookStructs) ExFreePoolWithTag(pHP->pHookStructs, TAG_HOOK);
       ExFreePoolWithTag(pHP, TAG_HOOK);
    }
    return NT_SUCCESS(Status) ? uResult : 0;
}
Пример #4
0
NTSTATUS
LSMPSendIoctlSrb(
		IN PDEVICE_OBJECT	DeviceObject,
		IN ULONG			IoctlCode,
		IN PVOID			InputBuffer,
		IN LONG				InputBufferLength,
		OUT PVOID			OutputBuffer,
		IN LONG				OutputBufferLength
	) {

    PIRP				irp;
    KEVENT				event;
	PSRB_IO_CONTROL		psrbIoctl;
	LONG				srbIoctlLength;
	PVOID				srbIoctlBuffer;
	LONG				srbIoctlBufferLength;
    NTSTATUS			status;
    PIO_STACK_LOCATION	irpStack;
    SCSI_REQUEST_BLOCK	srb;
    LARGE_INTEGER		startingOffset;
    IO_STATUS_BLOCK		ioStatusBlock;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	psrbIoctl	= NULL;
	irp = NULL;

	//
	//	build an SRB for the miniport
	//
	srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength;
	srbIoctlLength = sizeof(SRB_IO_CONTROL) +  srbIoctlBufferLength;

	psrbIoctl = (PSRB_IO_CONTROL)ExAllocatePoolWithTag(NonPagedPool , srbIoctlLength, LSMP_PTAG_SRB);
	if(psrbIoctl == NULL) {
		KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	RtlZeroMemory(psrbIoctl, srbIoctlLength);
	psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(psrbIoctl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8);
	psrbIoctl->Timeout = 10;
	psrbIoctl->ControlCode = IoctlCode;
	psrbIoctl->Length = srbIoctlBufferLength;

	srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength);

    //
    // Initialize the notification event.
    //

    KeInitializeEvent(&event,
                        NotificationEvent,
                        FALSE);
	startingOffset.QuadPart = 1;

    //
    // Build IRP for this request.
    // Note we do this synchronously for two reasons.  If it was done
    // asynchonously then the completion code would have to make a special
    // check to deallocate the buffer.  Second if a completion routine were
    // used then an additional IRP stack location would be needed.
    //

    irp = IoBuildSynchronousFsdRequest(
                IRP_MJ_SCSI,
                DeviceObject,
                psrbIoctl,
                srbIoctlLength,
                &startingOffset,
                &event,
                &ioStatusBlock);

    irpStack = IoGetNextIrpStackLocation(irp);

    if (irp == NULL) {
        KDPrint(1,("STATUS_INSUFFICIENT_RESOURCES\n"));

		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
    }

    //
    // Set major and minor codes.
    //

    irpStack->MajorFunction = IRP_MJ_SCSI;
    irpStack->MinorFunction = 1;

    //
    // Fill in SRB fields.
    //

    irpStack->Parameters.Others.Argument1 = &srb;

    //
    // Zero out the srb.
    //

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    srb.PathId = 0;
    srb.TargetId = 0;
    srb.Lun = 0;

    srb.Function = SRB_FUNCTION_IO_CONTROL;
    srb.Length = sizeof(SCSI_REQUEST_BLOCK);

    srb.SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;

	srb.QueueAction = SRB_SIMPLE_TAG_REQUEST;
	srb.QueueTag = SP_UNTAGGED;

    srb.OriginalRequest = irp;

    //
    // Set timeout to requested value.
    //

    srb.TimeOutValue = psrbIoctl->Timeout;

    //
    // Set the data buffer.
    //

    srb.DataBuffer = psrbIoctl;
    srb.DataTransferLength = srbIoctlLength;

    //
    // Flush the data buffer for output. This will insure that the data is
    // written back to memory.  Since the data-in flag is the the port driver
    // will flush the data again for input which will ensure the data is not
    // in the cache.
    //
/*
    KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
*/
    status = IoCallDriver( DeviceObject, irp );

    //
    // Wait for request to complete.
    //
    if (status == STATUS_PENDING) {

        (VOID)KeWaitForSingleObject( 
									&event,
                                     Executive,
                                     KernelMode,
                                     FALSE,
                                     (PLARGE_INTEGER)NULL 
									 );

        status = ioStatusBlock.Status;
    }

	//
	//	get the result
	//
	if(status == STATUS_SUCCESS) {
		if(OutputBuffer && OutputBufferLength)
			RtlCopyMemory(OutputBuffer, srbIoctlBuffer, OutputBufferLength);
			KDPrint(1,("Ioctl(%08lx) succeeded!\n", IoctlCode));
	}

cleanup:
	if(psrbIoctl)
		ExFreePool(psrbIoctl);

    return status;
}
Пример #5
0
NTSTATUS
MiniSrbControl(
	   IN PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
	   IN PMINIPORT_LU_EXTENSION		LuExtension,
	   IN PSCSI_REQUEST_BLOCK			Srb,
	   IN ULONG							CurSrbSequence
	)
/*++

Routine Description:

    This is the SRB_IO_CONTROL handler for this driver. These requests come from
    the management driver.
    
Arguments:

    DeviceExtension - Context
    Srb - The request to process.
    
Return Value:

    Value from the helper routines, or if handled in-line, SUCCESS or INVALID_REQUEST. 
    
--*/
{
    PSRB_IO_CONTROL	srbIoControl;
    PUCHAR			srbIoctlBuffer;
	LONG			srbIoctlBufferLength;
    ULONG			controlCode;
    ULONG			transferPages = 0;
    NTSTATUS		status;
    UCHAR			srbStatus;

    //
    // Start off being paranoid.
    //
    if (Srb->DataBuffer == NULL) {
		KDPrint(1,("DataBuffer is NULL\n"));
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        return STATUS_INVALID_PARAMETER;
    }
	status = STATUS_MORE_PROCESSING_REQUIRED;
	srbStatus = SRB_STATUS_SUCCESS;

	//
    // Extract the io_control
    //
    srbIoControl = (PSRB_IO_CONTROL)Srb->DataBuffer;

    //
    // Ensure the signature is correct.
    //
    if (strncmp(srbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8) != 0) {

		KDPrint(1,("Signature mismatch %8s, %8s\n", srbIoControl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE));
		Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        return STATUS_INVALID_PARAMETER;
    }

    //
    // Get the control code.
    // 
    controlCode = srbIoControl->ControlCode;

    //
    // Get the Ioctl buffer. If this is a send message request, it gets
    // fixed up to be an I2O message later.
    //
    srbIoctlBuffer = ((PUCHAR)Srb->DataBuffer) + sizeof(SRB_IO_CONTROL);
	srbIoctlBufferLength = srbIoControl->Length;

    //
    // Based on the control code, figure out what to do.
    //
    switch (controlCode) {
		case LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS:
			{
				srbStatus = SrbIoctlGetDVDSTatus(
								HwDeviceExtension,
								LuExtension,
								srbIoctlBufferLength,
								srbIoctlBuffer,
								&srbIoControl->ReturnCode,
								CurSrbSequence
								);
				if(srbStatus == SRB_STATUS_SUCCESS) {
					KDPrint(4,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: Successful.\n"));
					status = STATUS_SUCCESS;
				} else {
					status = STATUS_UNSUCCESSFUL;
				}								
			}
			break;
		case LANSCSIMINIPORT_IOCTL_GET_SLOT_NO:
            KDPrint(2,("Get Slot No. Slot number is %d\n", HwDeviceExtension->SlotNumber));

			*(PULONG)srbIoctlBuffer = HwDeviceExtension->SlotNumber;
			srbIoControl->ReturnCode = 0;

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_SUCCESS;
            break;

		case LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: {
			PLSMPIOCTL_QUERYINFO	QueryInfo;
			PUCHAR tmpBuffer;
            KDPrint(5, ("Query information EX.\n"));

			QueryInfo = (PLSMPIOCTL_QUERYINFO)srbIoctlBuffer;

			tmpBuffer = ExAllocatePoolWithTag(NonPagedPool, srbIoctlBufferLength, LSMP_PTAG_IOCTL);
			if(tmpBuffer == NULL) {
				ASSERT(FALSE);
	            KDPrint(1,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: SRB_STATUS_DATA_OVERRUN. BufferLength:%d\n", srbIoctlBufferLength));
				srbStatus = SRB_STATUS_DATA_OVERRUN;
				break;
			}

			srbStatus = SrbIoctlQueryInfo(
							HwDeviceExtension,
							LuExtension,
							QueryInfo,
							srbIoctlBufferLength,
							tmpBuffer,
							&srbIoControl->ReturnCode,
							CurSrbSequence
						);
			if(srbStatus == SRB_STATUS_SUCCESS) {
	            KDPrint(4,("LANSCSIMINIPORT_IOCTL_QUERYINFO_EX: Successful.\n"));
				RtlCopyMemory(srbIoctlBuffer, tmpBuffer, srbIoctlBufferLength);
				status = STATUS_SUCCESS;
			} else {
				status = STATUS_UNSUCCESSFUL;
			}

			ExFreePoolWithTag(tmpBuffer, LSMP_PTAG_IOCTL);
			break;
		}
		case LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: {
			PLURN_UPDATE		LurnUpdate;
			PCCB				Ccb;

			//
			//	Set a CCB
			//
			status = LSCcbAllocate(&Ccb);
			if(!NT_SUCCESS(status)) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: LSCcbAllocate() failed.\n"));
				break;
			}
			LurnUpdate = (PLURN_UPDATE)ExAllocatePoolWithTag(NonPagedPool, sizeof(LURN_UPDATE), LSMP_PTAG_IOCTL);
			if(!LurnUpdate) {
				srbStatus = SRB_STATUS_INVALID_REQUEST;
				KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE: ExAllocatePoolWithTag() failed.\n"));
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}

			LSCCB_INITIALIZE(Ccb, CurSrbSequence);
			Ccb->OperationCode = CCB_OPCODE_UPDATE;
			Ccb->DataBuffer = LurnUpdate;
			Ccb->DataBufferLength = sizeof(LURN_UPDATE);
			LSCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED|CCB_FLAG_DATABUF_ALLOCATED);

			//	Ioctl Srb will complete asynchronously.
			Ccb->Srb = Srb;
			InterlockedIncrement(&HwDeviceExtension->RequestExecuting);
			LsuIncrementTdiClientInProgress();
			LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension);

			LurnUpdate->UpdateClass = LURN_UPDATECLASS_WRITEACCESS_USERID;

			KDPrint(3,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE:  going to default LuExtention 0.\n"));
			status = LurRequest(
								HwDeviceExtension->LURs[0],	// default: 0.
								Ccb
							);
			if(!NT_SUCCESS(status)) {
				KDPrint(1,("LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE:  LurnRequest() failed.\n"));

				NDScsiLogError(
						HwDeviceExtension,
						Srb,
						Srb->PathId,
						Srb->TargetId,
						Srb->Lun,
						NDASSCSI_IO_UPGRADEIOCTL_FAIL,
						EVTLOG_UNIQUEID(EVTLOG_MODULE_IOCTL, EVTLOG_FAIL_UPGRADEIOCTL, 0)
					);
				LSCcbFree(Ccb);
				ExFreePoolWithTag(LurnUpdate, LSMP_PTAG_IOCTL);
				status = STATUS_SUCCESS;
				srbStatus = SRB_STATUS_INVALID_REQUEST;
			} else {
				status = STATUS_PENDING;
			}
			break;
		}

		case LANSCSIMINIPORT_IOCTL_ADD_TARGET: {
			PLANSCSI_ADD_TARGET_DATA	AddTargetData;
			PLURELATION_DESC			LurDesc;
			LONG						LurDescLength;
			LONG						LurnCnt;

			AddTargetData	= (PLANSCSI_ADD_TARGET_DATA)srbIoctlBuffer;
			LurnCnt			=	AddTargetData->ulNumberOfUnitDiskList;
			LurDescLength	=	sizeof(LURELATION_DESC) +											// LURELATION_DESC
								(sizeof(LURELATION_NODE_DESC) + sizeof(LONG) * (LurnCnt-1)) *		// LURELATION_NODE_DESC
								(LurnCnt - 1);
			//
			//	Allocate LUR Descriptor
			//	It will be freed in the worker routine.
			//
			LurDesc = (PLURELATION_DESC)ExAllocatePoolWithTag(NonPagedPool,  LurDescLength, LSMP_PTAG_IOCTL);
			if(LurDesc == NULL) {
				srbStatus = SRB_STATUS_ERROR;
				status = STATUS_SUCCESS;
				break;
			}

			//	Pass Adapter max request block as LUR max request blocks 
			status = LurTranslateAddTargetDataToLURDesc(
									AddTargetData,
									HwDeviceExtension->AdapterMaxBlocksPerRequest,
									LurDescLength,
									LurDesc
								);
			if(NT_SUCCESS(status)) {
				ASSERT(LurDescLength>0);
				status = AddNewDeviceToMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence, LurDesc);
			}
		}
		case LANSCSIMINIPORT_IOCTL_ADD_DEVICE: {
			PLURELATION_DESC			LurDesc;

			LurDesc = (PLURELATION_DESC)srbIoctlBuffer;

			status = AddNewDeviceToMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence, LurDesc);
			break;
		}
		case LANSCSIMINIPORT_IOCTL_REMOVE_DEVICE: {
			status = RemoveDeviceFromMiniport(HwDeviceExtension, LuExtension, Srb, CurSrbSequence);
			break;
		}

		case LANSCSIMINIPORT_IOCTL_REMOVE_TARGET: {
			PLANSCSI_REMOVE_TARGET_DATA	RemoveTargetData;

			RemoveTargetData = (PLANSCSI_REMOVE_TARGET_DATA)srbIoctlBuffer;
			status = RemoveDeviceFromMiniport(HwDeviceExtension, NULL, Srb, CurSrbSequence);
			break;
		}
		case LANSCSIMINIPORT_IOCTL_NOOP: {
			PCCB	Ccb;

			//
			//	Query to the LUR
			//
			status = LSCcbAllocate(&Ccb);
			if(!NT_SUCCESS(status)) {
				srbStatus = SRB_STATUS_ERROR;
				status = STATUS_SUCCESS;
				KDPrint(1,("LSCcbAllocate() failed.\n"));
				break;
			}

			LSCCB_INITIALIZE(Ccb, CurSrbSequence);
			Ccb->OperationCode = CCB_OPCODE_NOOP;
			LSCcbSetFlag(Ccb, CCB_FLAG_ALLOCATED);
			Ccb->Srb = Srb;
			LSCcbSetCompletionRoutine(Ccb, NdscAdapterCompletion, HwDeviceExtension);

			KDPrint(3,("going to default LuExtention 0.\n"));
			InterlockedIncrement(&HwDeviceExtension->RequestExecuting);
			LsuIncrementTdiClientInProgress();
			status = LurRequest(
								HwDeviceExtension->LURs[0],	// default: 0.
								Ccb
							);
			if(!NT_SUCCESS(status)) {
				srbStatus = SRB_STATUS_ERROR;
				status = STATUS_SUCCESS;
				KDPrint(1,("LurRequest() failed.\n"));
				break;
			}

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_PENDING;
		break;
		}
		case LANSCSIMINIPORT_IOCTL_GET_VERSION: {
			PLSMPIOCTL_DRVVER	version = (PLSMPIOCTL_DRVVER)srbIoctlBuffer;

			version->VersionMajor = VER_FILEMAJORVERSION;
			version->VersionMinor = VER_FILEMINORVERSION;
			version->VersionBuild = VER_FILEBUILD;
			version->VersionPrivate = VER_FILEBUILD_QFE;

			srbStatus = SRB_STATUS_SUCCESS;
			status = STATUS_SUCCESS;

		break;
		}
        default:

            KDPrint(2,("Control Code (%x)\n", controlCode));
            srbStatus = SRB_STATUS_INVALID_REQUEST;
			status = STATUS_MORE_PROCESSING_REQUIRED;
    }

	Srb->SrbStatus = srbStatus;

    return status;
}
Пример #6
0
/*
 * @implemented
 */
NTSTATUS
MountMgrCreatePointWorker(IN PDEVICE_EXTENSION DeviceExtension,
                          IN PUNICODE_STRING SymbolicLinkName,
                          IN PUNICODE_STRING DeviceName)
{
    NTSTATUS Status;
    PLIST_ENTRY DeviceEntry;
    PMOUNTDEV_UNIQUE_ID UniqueId;
    PSYMLINK_INFORMATION SymlinkInformation;
    UNICODE_STRING SymLink, TargetDeviceName;
    PDEVICE_INFORMATION DeviceInformation = NULL, DeviceInfo;

    /* Get device name */
    Status = QueryDeviceInformation(SymbolicLinkName,
                                    &TargetDeviceName,
                                    NULL, NULL, NULL,
                                    NULL, NULL, NULL);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* First of all, try to find device */
    for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
         DeviceEntry != &(DeviceExtension->DeviceListHead);
         DeviceEntry = DeviceEntry->Flink)
    {
        DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

        if (RtlCompareUnicodeString(&TargetDeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
        {
            break;
        }
    }

    /* Copy symbolic link name and null terminate it */
    SymLink.Buffer = AllocatePool(SymbolicLinkName->Length + sizeof(UNICODE_NULL));
    if (!SymLink.Buffer)
    {
        FreePool(TargetDeviceName.Buffer);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyMemory(SymLink.Buffer, SymbolicLinkName->Buffer, SymbolicLinkName->Length);
    SymLink.Buffer[SymbolicLinkName->Length / sizeof(WCHAR)] = UNICODE_NULL;
    SymLink.Length = SymbolicLinkName->Length;
    SymLink.MaximumLength = SymbolicLinkName->Length + sizeof(UNICODE_NULL);

    /* If we didn't find device */
    if (DeviceEntry == &(DeviceExtension->DeviceListHead))
    {
        /* Then, try with unique ID */
        Status = QueryDeviceInformation(SymbolicLinkName,
                                        NULL, &UniqueId,
                                        NULL, NULL, NULL,
                                        NULL, NULL);
        if (!NT_SUCCESS(Status))
        {
            FreePool(TargetDeviceName.Buffer);
            FreePool(SymLink.Buffer);
            return Status;
        }

        /* Create a link to the device */
        Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
        if (!NT_SUCCESS(Status))
        {
            FreePool(UniqueId);
            FreePool(TargetDeviceName.Buffer);
            FreePool(SymLink.Buffer);
            return Status;
        }

        /* If caller provided driver letter, delete it */
        if (IsDriveLetter(&SymLink))
        {
            DeleteRegistryDriveLetter(UniqueId);
        }

        /* Device will be identified with its unique ID */
        Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
                                       DatabasePath,
                                       SymLink.Buffer,
                                       REG_BINARY,
                                       UniqueId->UniqueId,
                                       UniqueId->UniqueIdLength);

        FreePool(UniqueId);
        FreePool(TargetDeviceName.Buffer);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* If call provided a driver letter whereas device already has one
     * fail, this is not doable
     */
    if (IsDriveLetter(&SymLink) && HasDriveLetter(DeviceInformation))
    {
        FreePool(TargetDeviceName.Buffer);
        FreePool(SymLink.Buffer);
        return STATUS_INVALID_PARAMETER;
    }

    /* Now, create a link */
    Status = GlobalCreateSymbolicLink(&SymLink, &TargetDeviceName);
    FreePool(TargetDeviceName.Buffer);
    if (!NT_SUCCESS(Status))
    {
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Associate Unique ID <-> symbolic name */
    UniqueId = DeviceInformation->UniqueId;
    Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE,
                                   DatabasePath,
                                   SymLink.Buffer,
                                   REG_BINARY,
                                   UniqueId->UniqueId,
                                   UniqueId->UniqueIdLength);
    if (!NT_SUCCESS(Status))
    {
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Now, prepare to save the link with the device */
    SymlinkInformation = AllocatePool(sizeof(SYMLINK_INFORMATION));
    if (!SymlinkInformation)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    SymlinkInformation->Name.Length = SymLink.Length;
    SymlinkInformation->Name.MaximumLength = SymLink.Length + sizeof(UNICODE_NULL);
    SymlinkInformation->Name.Buffer = AllocatePool(SymlinkInformation->Name.MaximumLength);
    if (!SymlinkInformation->Name.Buffer)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
        FreePool(SymlinkInformation);
        GlobalDeleteSymbolicLink(&SymLink);
        FreePool(SymLink.Buffer);
        return Status;
    }

    /* Save the link and mark it online */
    RtlCopyMemory(SymlinkInformation->Name.Buffer, SymLink.Buffer, SymlinkInformation->Name.Length);
    SymlinkInformation->Name.Buffer[SymlinkInformation->Name.Length / sizeof(WCHAR)] = UNICODE_NULL;
    SymlinkInformation->Online = TRUE;
    InsertTailList(&DeviceInformation->SymbolicLinksListHead, &SymlinkInformation->SymbolicLinksListEntry);
    SendLinkCreated(&(SymlinkInformation->Name));

    /* If we have a drive letter */
    if (IsDriveLetter(&SymLink))
    {
        /* Then, delete the no drive letter entry */
        DeleteNoDriveLetterEntry(UniqueId);

        /* And post online notification if asked */
        if (!DeviceInformation->SkipNotifications)
        {
            PostOnlineNotification(DeviceExtension, &DeviceInformation->SymbolicName);
        }
    }

    /* If that's a volume with automatic drive letter, it's now time to resync databases */
    if (MOUNTMGR_IS_VOLUME_NAME(&SymLink) && DeviceExtension->AutomaticDriveLetter)
    {
        for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
             DeviceEntry != &(DeviceExtension->DeviceListHead);
             DeviceEntry = DeviceEntry->Flink)
        {
            DeviceInfo = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

            /* If there's one, ofc! */
            if (!DeviceInfo->NoDatabase)
            {
                ReconcileThisDatabaseWithMaster(DeviceExtension, DeviceInfo);
            }
        }
    }

    /* Notify & quit */
    FreePool(SymLink.Buffer);
    MountMgrNotify(DeviceExtension);

    if (!DeviceInformation->Volume)
    {
        MountMgrNotifyNameChange(DeviceExtension, DeviceName, FALSE);
    }

    return Status;
}
Пример #7
0
NTSTATUS
SpWmiIrpRegisterRequest(
    IN     PDEVICE_OBJECT  DeviceObject,
    IN OUT PWMI_PARAMETERS WmiParameters
    )

/*++

Routine Description:

   Process an IRP_MJ_SYSTEM_CONTROL registration request.

Arguments:

   DeviceObject  - Pointer to the functional or physical device object.

   WmiParameters - Pointer to the WMI request parameters.

Return Value:

   NTSTATUS result code to complete the WMI IRP with.

Notes:

   If this WMI request is completed with STATUS_SUCCESS, the WmiParameters
   BufferSize field will reflect the actual size of the WMI return buffer.

--*/

{
    PCOMMON_EXTENSION   commonExtension = DeviceObject->DeviceExtension;
    PSCSIPORT_DRIVER_EXTENSION driverExtension = NULL;

    ULONG                      countedRegistryPathSize = 0;
    ULONG                      retSz;
    PWMIREGINFO                spWmiRegInfoBuf;
    ULONG                      spWmiRegInfoBufSize;
    NTSTATUS                   status = STATUS_SUCCESS;
    BOOLEAN                    wmiUpdateRequest;
    ULONG                      i;
    PDEVICE_OBJECT             pDO;

    WMI_PARAMETERS  paranoidBackup = *WmiParameters;

    PAGED_CODE();

    //
    // Validate our assumptions for this function's code.
    //
    ASSERT(WmiParameters->BufferSize >= sizeof(ULONG));

    //
    // Validate the registration mode.
    //
    switch ( (ULONG)(ULONG_PTR)WmiParameters->DataPath ) {
        case WMIUPDATE:
            //
            // No SCSIPORT registration information will be piggybacked
            // on behalf of the miniport for a WMIUPDATE request.
            //
            wmiUpdateRequest = TRUE;
            break;

        case WMIREGISTER:
            wmiUpdateRequest = FALSE;
            break;

        default:
            //
            // Unsupported registration mode.
            //
            ASSERT(FALSE);
            return STATUS_INVALID_PARAMETER;
    }

    //
    // Obtain the driver extension for this miniport (FDO/PDO).
    //
    driverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject,
                                                 ScsiPortInitialize);

    ASSERT(driverExtension != NULL);

    //
    // Obtain a pointer to the SCSIPORT WMI registration information
    // buffer, which is registered on behalf of the miniport driver.
    //
    SpWmiGetSpRegInfo(DeviceObject, &spWmiRegInfoBuf,
                      &spWmiRegInfoBufSize);

    //
    // Pass the WMI registration request to the miniport.  This is not
    // necessary if we know the miniport driver does not support WMI.
    //
    if (commonExtension->WmiMiniPortSupport) {
        //
        // Note that we shrink the buffer size by the size necessary
        // to hold SCSIPORT's own registration information, which we
        // register on behalf of the miniport.   This information is
        // piggybacked into the WMI return buffer after the call  to
        // the miniport.  We ensure that the BufferSize passed to the
        // miniport is no smaller than "sizeof(ULONG)" so that it can
        // tell us the required buffer size should the buffer be too
        // small [by filling in this ULONG].
        //
        // Note that we must also make enough room for a copy of the
        // miniport registry path in the buffer, since the WMIREGINFO
        // structures from the miniport DO NOT set their registry
        // path fields.
        //
        ASSERT(WmiParameters->BufferSize >= sizeof(ULONG));

        //
        // Calculate size of required miniport registry path.
        //
        countedRegistryPathSize = driverExtension->RegistryPath.Length
                                  + sizeof(USHORT);

        //
        // Shrink buffer by the appropriate size. Note that the extra
        // 7 bytes (possibly extraneous) is subtracted to ensure that
        // the piggybacked data added later on is 8-byte aligned (if
        // any).
        //
        if (spWmiRegInfoBufSize && !wmiUpdateRequest) {
            WmiParameters->BufferSize =
                (WmiParameters->BufferSize > spWmiRegInfoBufSize + countedRegistryPathSize + 7 + sizeof(ULONG)) ?
                WmiParameters->BufferSize - spWmiRegInfoBufSize - countedRegistryPathSize - 7 :
            sizeof(ULONG);
        } else { // no data to piggyback
            WmiParameters->BufferSize =
                (WmiParameters->BufferSize > countedRegistryPathSize + sizeof(ULONG)) ?
                WmiParameters->BufferSize - countedRegistryPathSize :
            sizeof(ULONG);
        }

        //
        // Call the minidriver.
        //
        status = SpWmiPassToMiniPort(DeviceObject,
                                     IRP_MN_REGINFO,
                                     WmiParameters);

        ASSERT(WmiParameters->ProviderId == paranoidBackup.ProviderId);
        ASSERT(WmiParameters->DataPath == paranoidBackup.DataPath);
        ASSERT(WmiParameters->Buffer == paranoidBackup.Buffer);
        ASSERT(WmiParameters->BufferSize <= paranoidBackup.BufferSize);

        //
        // Assign WmiParameters->BufferSize to retSz temporarily.
        //
        // Note that on return from the above call, the wmiParameters'
        // BufferSize field has been _modified_ to reflect the current
        // size of the return buffer.
        //
        retSz = WmiParameters->BufferSize;

    } else if (WmiParameters->BufferSize < spWmiRegInfoBufSize &&
               !wmiUpdateRequest) {

        //
        // Insufficient space to hold SCSIPORT WMI registration information
        // alone.  Inform WMI appropriately of the required buffer size.
        //
        *((ULONG*)WmiParameters->Buffer) = spWmiRegInfoBufSize;
        WmiParameters->BufferSize = sizeof(ULONG);
        return STATUS_SUCCESS;

    } else { // no miniport support for WMI, sufficient space for scsiport info

        //
        // Fake having the miniport return zero WMIREGINFO structures.
        //
        retSz = 0;
    }

    //
    // Piggyback SCSIPORT's registration information into the WMI
    // registration buffer.
    //
    if (status == STATUS_BUFFER_TOO_SMALL || retSz == sizeof(ULONG)) {
        //
        // Miniport could not fit registration information into the
        // pre-shrunk buffer.
        //
        // Buffer currently contains a ULONG specifying required buffer
        // size of miniport registration info, but does not include the
        // SCSIPORT registration info's size.  Add it in.
        //
        if (spWmiRegInfoBufSize && !wmiUpdateRequest) {

            *((ULONG*)WmiParameters->Buffer) += spWmiRegInfoBufSize;

            //
            // Add an extra 7 bytes (possibly extraneous) which is used to
            // ensure that the piggybacked data structure 8-byte aligned.
            //
            *((ULONG*)WmiParameters->Buffer) += 7;
        }

        //
        // Add in size of the miniport registry path.
        //
        *((ULONG*)WmiParameters->Buffer) += countedRegistryPathSize;

        //
        // Return STATUS_SUCCESS, even though this is a BUFFER TOO
        // SMALL failure, while ensuring retSz = sizeof(ULONG), as
        // the WMI protocol calls us to do.
        //
        retSz  = sizeof(ULONG);
        status = STATUS_SUCCESS;

    } else if ( NT_SUCCESS(status) ) {
        //
        // Zero or more WMIREGINFOs exist in buffer from miniport.
        //

        //
        // Piggyback the miniport registry path transparently, if at least one
        // WMIREGINFO was returned by the minport.
        //
        if (retSz) {

            ULONG offsetToRegPath  = retSz;
            PWMIREGINFO wmiRegInfo = WmiParameters->Buffer;

            //
            // Build a counted wide-character string, containing the
            // registry path, into the WMI buffer.
            //
            *( (PUSHORT)( (PUCHAR)WmiParameters->Buffer + retSz ) ) =
                driverExtension->RegistryPath.Length,
            RtlCopyMemory( (PUCHAR)WmiParameters->Buffer + retSz + sizeof(USHORT),
                           driverExtension->RegistryPath.Buffer,
                           driverExtension->RegistryPath.Length);

            //
            // Traverse the WMIREGINFO structures returned by the mini-
            // driver and set the missing RegistryPath fields to point
            // to our registry path location. We also jam in the PDO for
            // the device stack so that the device instance name is used for
            // the wmi instance names.
            //
            pDO = commonExtension->IsPdo ? DeviceObject :
                            ((PADAPTER_EXTENSION)commonExtension)->LowerPdo;

            while (1) {
                wmiRegInfo->RegistryPath = offsetToRegPath;

                for (i = 0; i < wmiRegInfo->GuidCount; i++)
                {
                    wmiRegInfo->WmiRegGuid[i].InstanceInfo = (ULONG_PTR)pDO;
                    wmiRegInfo->WmiRegGuid[i].Flags &= ~(WMIREG_FLAG_INSTANCE_BASENAME |
                                                      WMIREG_FLAG_INSTANCE_LIST);
                    wmiRegInfo->WmiRegGuid[i].Flags |= WMIREG_FLAG_INSTANCE_PDO;
                }

                if (wmiRegInfo->NextWmiRegInfo == 0) {
                    break;
                }

                offsetToRegPath -= wmiRegInfo->NextWmiRegInfo;
                wmiRegInfo = (PWMIREGINFO)( (PUCHAR)wmiRegInfo +
                                            wmiRegInfo->NextWmiRegInfo );
            }

            //
            // Adjust retSz to reflect new size of the WMI buffer.
            //
            retSz += countedRegistryPathSize;
            wmiRegInfo->BufferSize = retSz;
        } // else, no WMIREGINFOs registered whatsoever, nothing to piggyback

        //
        // Do we have any SCSIPORT WMIREGINFOs to piggyback?
        //
        if (spWmiRegInfoBufSize && !wmiUpdateRequest) {

            //
            // Adjust retSz so that the data we piggyback is 8-byte aligned
            // (safe if retSz = 0).
            //
            retSz = (retSz + 7) & ~7;

            //
            // Piggyback SCSIPORT's registration info into the buffer.
            //
            RtlCopyMemory( (PUCHAR)WmiParameters->Buffer + retSz,
                           spWmiRegInfoBuf,
                           spWmiRegInfoBufSize);

            //
            // Was at least one WMIREGINFO returned by the minidriver?
            // Otherwise, we have nothing else to add to the WMI buffer.
            //
            if (retSz) { // at least one WMIREGINFO returned by minidriver
                PWMIREGINFO wmiRegInfo = WmiParameters->Buffer;

                //
                // Traverse to the end of the WMIREGINFO structures returned
                // by the miniport.
                //
                while (wmiRegInfo->NextWmiRegInfo) {
                    wmiRegInfo = (PWMIREGINFO)( (PUCHAR)wmiRegInfo +
                                                wmiRegInfo->NextWmiRegInfo );
                }

                //
                // Chain minidriver's WMIREGINFO structures to SCSIPORT's
                // WMIREGINFO structures.
                //
                wmiRegInfo->NextWmiRegInfo = retSz -
                                             (ULONG)((PUCHAR)wmiRegInfo - (PUCHAR)WmiParameters->Buffer);
            }

            //
            // Adjust retSz to reflect new size of the WMI buffer.
            //
            retSz += spWmiRegInfoBufSize;

        } // we had SCSIPORT REGINFO data to piggyback
    } // else, unknown error, complete IRP with this error status

    //
    // Save new buffer size to WmiParameters->BufferSize.
    //
    WmiParameters->BufferSize = retSz;

    return status;
}
UINT32 PrvScenarioFastStreamInjectionAddFwpmObjects(_In_ const FWPM_FILTER* pFilter)
{
   ASSERT(pFilter);

   UINT32 status = NO_ERROR;

   if(pFilter->layerKey == FWPM_LAYER_STREAM_V4 ||
      pFilter->layerKey == FWPM_LAYER_STREAM_V6)
   {
      HANDLE       engineHandle = 0;
      FWPM_CALLOUT callout      = {0};
      FWPM_FILTER  filter       = {0};

      RtlCopyMemory(&filter,
                    pFilter,
                    sizeof(FWPM_FILTER));

      callout.calloutKey              = WFPSAMPLER_CALLOUT_FAST_STREAM_INJECTION;
      callout.calloutKey.Data4[7]     = HlprFwpmLayerGetIDByKey(&(filter.layerKey));                /// Uniquely identifies the callout used
      callout.displayData.name        = L"WFPSampler's Fast Stream Injection Callout";
      callout.displayData.description = L"Causes callout invocation which blindly injects data back into the stream";
      callout.providerKey             = (GUID*)&WFPSAMPLER_PROVIDER;
      callout.applicableLayer         = filter.layerKey;

      status = HlprGUIDPopulate(&(filter.filterKey));
      HLPR_BAIL_ON_FAILURE(status);

      filter.providerKey        = (GUID*)&WFPSAMPLER_PROVIDER;
      filter.weight.type        = FWP_UINT8;
      filter.weight.uint8       = 0xF;
      filter.action.type        = FWP_ACTION_CALLOUT_TERMINATING;
      filter.action.calloutKey  = callout.calloutKey;

      if(filter.flags & FWPM_FILTER_FLAG_BOOTTIME ||
         filter.flags & FWPM_FILTER_FLAG_PERSISTENT)
         callout.flags = FWPM_CALLOUT_FLAG_PERSISTENT;
    
      status = HlprFwpmEngineOpen(&engineHandle);
      HLPR_BAIL_ON_FAILURE(status);

      status = HlprFwpmTransactionBegin(engineHandle);
      HLPR_BAIL_ON_FAILURE(status);

      status = HlprFwpmCalloutAdd(engineHandle,
                                  &callout);
      HLPR_BAIL_ON_FAILURE(status);

      status = HlprFwpmFilterAdd(engineHandle,
                                 &filter);
      HLPR_BAIL_ON_FAILURE(status);

      status = HlprFwpmTransactionCommit(engineHandle);
      HLPR_BAIL_ON_FAILURE(status);

      HLPR_BAIL_LABEL:

      if(engineHandle)
      {
         if(status != NO_ERROR)
            HlprFwpmTransactionAbort(engineHandle);

         HlprFwpmEngineClose(&engineHandle);
      }
   }
   else
      status = (UINT32) FWP_E_INCOMPATIBLE_LAYER;

   return status;
}
Пример #9
0
struct Send_Packet_Data*
Packet2PacketData(PNDIS_PACKET Packet) {

	UINT buffer_count;
	PNDIS_BUFFER buffer;
	UINT packet_len;
	UINT offset;
	PVOID addr;
	UINT len;
	struct Send_Packet_Data* packet_data;
	packet_data = NULL;
	
	NdisQueryPacket(Packet,
		NULL,
		&buffer_count,
		&buffer,
		&packet_len);
	if (!buffer_count ||
		!buffer)
		goto error_exit;

	if (buffer_count > 1) {
		packet_data = PreparePacketData(buffer_count,
			packet_len);
		if (!packet_data)
			goto error_exit;
		
		offset = 0;
		while(1) {
			NdisQueryBufferSafe(buffer,
				&addr,
				&len,
				NormalPagePriority);
			if (!addr ||
				!len)
				goto error_exit;
		
			RtlCopyMemory(packet_data->m_data+offset, 
				addr, 
				len);
			offset += len;
		
			NdisGetNextBuffer(buffer, 
				&buffer);
			if (!buffer)
				break;
		}
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;
	}
	else {
		packet_data = PreparePacketData(buffer_count,
			0);
		if (!packet_data)
			goto error_exit;

		NdisQueryBufferSafe(buffer,
			&addr,
			&len,
			NormalPagePriority);
		if (!addr ||
			!len)
			goto error_exit;
		
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;		
		packet_data->m_data = addr;
	}

	packet_data->m_mdl = IoAllocateMdl(packet_data->m_data,
		packet_data->m_len,
		FALSE,
		FALSE,
		NULL);
	if (!packet_data->m_mdl)
		goto error_exit;

	try {
		MmProbeAndLockPages(packet_data->m_mdl,
			KernelMode,
			IoReadAccess);
		packet_data->m_locked = 1;
	}
	except(EXCEPTION_EXECUTE_HANDLER) {
		packet_data->m_locked = 0;
	}

	packet_data->m_addr = MmMapLockedPagesSpecifyCache(packet_data->m_mdl,
		UserMode,
		MmCached,
		NULL,
		FALSE,
		NormalPagePriority);
	if (!packet_data->m_addr)
		goto error_exit;

	packet_data->m_map_process = PsGetCurrentProcessId();

	return packet_data;
	
error_exit:
	DbgPrint("Packet2PacketData failed, force to complete the lost packet\n");
	free_send_packet_data(packet_data);
	return NULL;
}
Пример #10
0
NTSTATUS
CHardwareSimulation::
FillScatterGatherBuffers (
    )

/*++

Routine Description:

    The hardware has synthesized a buffer in scratch space and we're to
    fill scatter / gather buffers.

Arguments:

    None

Return Value:

    Success / Failure

--*/

{

    //
    // We're using this list lock to protect our scatter / gather lists instead
    // of some hardware mechanism / KeSynchronizeExecution / whatever.
    //
    KeAcquireSpinLockAtDpcLevel (&m_ListLock);

    PUCHAR Buffer = reinterpret_cast <PUCHAR> (m_SynthesisBuffer);
    ULONG BufferRemaining = m_ImageSize;

    //
    // For simplification, if there aren't enough scatter / gather buffers
    // queued, we don't partially fill the ones that are available.  We just
    // skip the frame and consider it starvation.
    //
    // This could be enforced by only programming scatter / gather mappings
    // for a buffer if all of them fit in the table also...
    //
    while (BufferRemaining &&
        m_ScatterGatherMappingsQueued > 0 &&
        m_ScatterGatherBytesQueued >= BufferRemaining) {

        LIST_ENTRY *listEntry = RemoveHeadList (&m_ScatterGatherMappings);
        m_ScatterGatherMappingsQueued--;

        PSCATTER_GATHER_ENTRY SGEntry =  
            reinterpret_cast <PSCATTER_GATHER_ENTRY> (
                CONTAINING_RECORD (
                    listEntry,
                    SCATTER_GATHER_ENTRY,
                    ListEntry
                    )
                );

        //
        // Since we're software, we'll be accessing this by virtual address...
        //
        ULONG BytesToCopy = 
            (BufferRemaining < SGEntry -> ByteCount) ?
            BufferRemaining :
            SGEntry -> ByteCount;

        RtlCopyMemory (
            SGEntry -> Virtual,
            Buffer,
            BytesToCopy
            );

        BufferRemaining -= BytesToCopy;
        Buffer += BytesToCopy;
        m_NumMappingsCompleted++;
        m_ScatterGatherBytesQueued -= SGEntry -> ByteCount;

        //
        // Release the scatter / gather entry back to our lookaside.
        //
        ExFreeToNPagedLookasideList (
            &m_ScatterGatherLookaside,
            reinterpret_cast <PVOID> (SGEntry)
            );

    }
    
    KeReleaseSpinLockFromDpcLevel (&m_ListLock);

    if (BufferRemaining) return STATUS_INSUFFICIENT_RESOURCES;
    else return STATUS_SUCCESS;
    
}
NTSTATUS
DispatchRequest (
	IN PPRIMARY_SESSION	PrimarySession
	)
{
	NTSTATUS				status;
	IN PNDFS_REQUEST_HEADER	ndfsRequestHeader;


	ASSERT( NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2) < PrimarySession->SessionContext.SessionSlotCount );
	ASSERT( PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].State == SLOT_WAIT );
	ASSERT( PrimarySession->Thread.ReceiveOverlapped.Request[0].IoStatusBlock.Information == sizeof(NDFS_REQUEST_HEADER) );

	RtlCopyMemory( PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer,
				   &PrimarySession->Thread.NdfsRequestHeader,
				   sizeof(NDFS_REQUEST_HEADER) );

	ndfsRequestHeader = (PNDFS_REQUEST_HEADER)PrimarySession->Thread.SessionSlot[NTOHS(PrimarySession->Thread.NdfsRequestHeader.Mid2)].RequestMessageBuffer;
   
    DebugTrace( 0, Dbg,
				("DispatchRequest: ndfsRequestHeader->Command = %d\n", 
				ndfsRequestHeader->Command) );

	switch (ndfsRequestHeader->Command) {

	case NDFS_COMMAND_LOGOFF: {

		PNDFS_REQUEST_LOGOFF	ndfsRequestLogoff;
		PNDFS_REPLY_HEADER		ndfsReplyHeader;
		PNDFS_REPLY_LOGOFF		ndfsReplyLogoff;
		

		if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

			ASSERT(NDASNTFS_BUG);
			status = STATUS_UNSUCCESSFUL;
			break;
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT(NDASNTFS_BUG);
			status = STATUS_UNSUCCESSFUL;
			break;
		}
		
		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) == sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_REQUEST_LOGOFF) );

		ndfsRequestLogoff = (PNDFS_REQUEST_LOGOFF)(ndfsRequestHeader+1);
		
		status = RecvMessage( PrimarySession->ConnectionFileObject,
							 (UINT8 *)ndfsRequestLogoff,
							 sizeof(NDFS_REQUEST_LOGOFF),
							 NULL );
	
		if (status != STATUS_SUCCESS) {

			ASSERT(NDASNTFS_BUG);
			break;
		}

		ndfsReplyHeader = (PNDFS_REPLY_HEADER)(ndfsRequestLogoff+1);

		RtlCopyMemory( ndfsReplyHeader->Protocol, NDFS_PROTOCOL, sizeof(ndfsReplyHeader->Protocol) );
		ndfsReplyHeader->Status		= NDFS_SUCCESS;
		ndfsReplyHeader->Flags	    = 0;
		ndfsReplyHeader->Uid2		= HTONS(PrimarySession->SessionContext.Uid);
		ndfsReplyHeader->Tid2		= 0;
		ndfsReplyHeader->Mid2		= 0;
		ndfsReplyHeader->MessageSize4 = HTONL((UINT32)(sizeof(NDFS_REPLY_HEADER)+sizeof(NDFS_REPLY_LOGOFF)));

		ndfsReplyLogoff = (PNDFS_REPLY_LOGOFF)(ndfsReplyHeader+1);

		if (NTOHL(ndfsRequestLogoff->SessionKey4) != PrimarySession->SessionContext.SessionKey) {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_UNSUCCESSFUL;
		
		} else {

			ndfsReplyLogoff->Status = NDFS_LOGOFF_SUCCESS;
		}

		status = SendMessage( PrimarySession->ConnectionFileObject,
							  (UINT8 *)ndfsReplyHeader,
							  NTOHL(ndfsReplyHeader->MessageSize4),
							  NULL );

		if (status != STATUS_SUCCESS) {

			break;
		}

		PrimarySession->Thread.SessionState = SESSION_CLOSED;

		status = STATUS_SUCCESS;

		break;
	}

	case NDFS_COMMAND_EXECUTE: {

		UINT16	mid;

		if(PrimarySession->SessionContext.NdfsMinorVersion == NDFS_PROTOCOL_MINOR_0) {

			if (PrimarySession->Thread.SessionState != SESSION_TREE_CONNECT) {

				ASSERT( NDASNTFS_BUG );
				status = STATUS_UNSUCCESSFUL;
				break;
			}
		}

		if (!(NTOHS(ndfsRequestHeader->Uid2) == PrimarySession->SessionContext.Uid && 
			NTOHS(ndfsRequestHeader->Tid2) == PrimarySession->SessionContext.Tid)) {

			ASSERT( NDASNTFS_BUG );
			status = STATUS_UNSUCCESSFUL;

			break;
		}

		mid = NTOHS(ndfsRequestHeader->Mid2);

		PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength = sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) + DEFAULT_NDAS_MAX_DATA_SIZE;
		RtlZeroMemory( &PrimarySession->Thread.SessionSlot[mid].RequestMessageBuffer[sizeof(NDFS_REQUEST_HEADER)], 
					   PrimarySession->Thread.SessionSlot[mid].RequestMessageBufferLength - sizeof(NDFS_REQUEST_HEADER) );

		PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength = sizeof(NDFS_REPLY_HEADER) + sizeof(NDFS_WINXP_REPLY_HEADER) + DEFAULT_NDAS_MAX_DATA_SIZE;
		RtlZeroMemory( PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer, 
					   PrimarySession->Thread.SessionSlot[mid].ReplyMessageBufferLength );

		ASSERT( NTOHL(ndfsRequestHeader->MessageSize4) >= sizeof(NDFS_REQUEST_HEADER) + sizeof(NDFS_WINXP_REQUEST_HEADER) );
		status = ReceiveNdfsWinxpMessage( PrimarySession, mid );

		if (status != STATUS_SUCCESS)
			break;

		if (PrimarySession->Thread.SessionSlot[mid].State != SLOT_WAIT) {

			break;
		}
	
		PrimarySession->Thread.SessionSlot[mid].State = SLOT_EXECUTING;
		PrimarySession->Thread.IdleSlotCount --;

		if (PrimarySession->SessionContext.SessionSlotCount == 1) {

			ASSERT( mid == 0 );

			DispatchWinXpRequestWorker( PrimarySession, mid );

			PrimarySession->Thread.SessionSlot[mid].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount ++;

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_SUCCESS) {

				PNDFS_REPLY_HEADER		ndfsReplyHeader;

				ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[mid].ReplyMessageBuffer;
										
				PrimarySession->Thread.SessionSlot[mid].Status = 
					SendNdfsWinxpMessage( PrimarySession,
										  ndfsReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].NdfsWinxpReplyHeader,
										  PrimarySession->Thread.SessionSlot[mid].ReplyDataSize,
										  mid );

			}
	
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[mid].ExtendWinxpReplyMessagePoolLength = 0;
			}

			if (PrimarySession->Thread.SessionSlot[mid].Status == STATUS_PENDING) {

				NDAS_BUGON( FALSE );
			}
			
			if (PrimarySession->Thread.SessionSlot[mid].Status != STATUS_SUCCESS) {

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
										
				status = PrimarySession->Thread.SessionSlot[mid].Status;
				break;		
			}
				
			status = STATUS_SUCCESS;
			break;
		}

		if (mid == 0)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker0,
								  PrimarySession );
		
		if (mid == 1)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker1,
								  PrimarySession );
		
		if (mid == 2)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker2,
								  PrimarySession );

		
		if (mid == 3)
			ExInitializeWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem,
								  DispatchWinXpRequestWorker3,
								  PrimarySession );

		ExQueueWorkItem( &PrimarySession->Thread.SessionSlot[mid].WorkQueueItem, DelayedWorkQueue );	

		status = STATUS_PENDING;
		break;
	}

	default:

		NDAS_BUGON( FALSE );
		status = STATUS_UNSUCCESSFUL;
		
		break;
	}

	return status;
}
Пример #12
0
NTSTATUS
PerfInfoProcessRunDown (
    )
/*++

Routine Description:

    This routine does the Process and thread rundown in the kernel mode.
    Since this routine is called only by global logger (i.e., trace from boot),
    no Sid info is collected.

Arguments:

    None.

Return Value:

    Status

--*/
{
    NTSTATUS Status;
    PSYSTEM_PROCESS_INFORMATION ProcessInfo;
    PSYSTEM_EXTENDED_THREAD_INFORMATION ThreadInfo;
    PCHAR Buffer;
    ULONG BufferSize = 4096;
    ULONG ReturnLength;

retry:
    Buffer = ExAllocatePoolWithTag(NonPagedPool, BufferSize, PERFPOOLTAG);

    if (!Buffer) {
        return STATUS_NO_MEMORY;
    }
    Status = ZwQuerySystemInformation( SystemExtendedProcessInformation,
                                       Buffer,
                                       BufferSize,
                                       &ReturnLength
                                       );

    if (Status == STATUS_INFO_LENGTH_MISMATCH) {
        ExFreePool(Buffer);
        BufferSize = ReturnLength;
        goto retry;
    }

    if (NT_SUCCESS(Status)) {
        ULONG TotalOffset = 0;
        ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) Buffer;
        while (TRUE) {
            PWMI_PROCESS_INFORMATION WmiProcessInfo;
            PWMI_EXTENDED_THREAD_INFORMATION WmiThreadInfo;
            PERFINFO_HOOK_HANDLE Hook;
            ANSI_STRING ProcessName;
            PCHAR AuxPtr;
            ULONG NameLength;
            ULONG ByteCount;
            ULONG SidLength = sizeof(ULONG);
            ULONG TmpSid = 0;
            ULONG i;

            //
            // Process Information
            //
            if ( ProcessInfo->ImageName.Buffer  && ProcessInfo->ImageName.Length > 0 ) {
                NameLength = ProcessInfo->ImageName.Length / sizeof(WCHAR) + 1;
            }
            else {
                NameLength = 1;
            }
            ByteCount = FIELD_OFFSET(WMI_PROCESS_INFORMATION, Sid) + SidLength + NameLength;

            Status = PerfInfoReserveBytes(&Hook, 
                                          WMI_LOG_TYPE_PROCESS_DC_START, 
                                          ByteCount);

            if (NT_SUCCESS(Status)){
                WmiProcessInfo = PERFINFO_HOOK_HANDLE_TO_DATA(Hook, PWMI_PROCESS_INFORMATION);

                WmiProcessInfo->ProcessId = HandleToUlong(ProcessInfo->UniqueProcessId);
                WmiProcessInfo->ParentId = HandleToUlong(ProcessInfo->InheritedFromUniqueProcessId);
                WmiProcessInfo->SessionId = ProcessInfo->SessionId;
                WmiProcessInfo->PageDirectoryBase = ProcessInfo->PageDirectoryBase;

                AuxPtr = (PCHAR) &WmiProcessInfo->Sid;
                RtlCopyMemory(AuxPtr, &TmpSid, SidLength);

                AuxPtr += SidLength;
                if (NameLength > 1) {
    
                    ProcessName.Buffer = AuxPtr;
                    ProcessName.MaximumLength = (USHORT) NameLength;
    
                    RtlUnicodeStringToAnsiString( &ProcessName,
                                                (PUNICODE_STRING) &ProcessInfo->ImageName,
                                                FALSE);
                    AuxPtr += NameLength - 1; //point to the place for the '\0'
                }
                *AuxPtr = '\0';

                PERF_FINISH_HOOK(Hook);
            }

            //
            // Thread Information
            //
            ThreadInfo = (PSYSTEM_EXTENDED_THREAD_INFORMATION) (ProcessInfo + 1);

            for (i=0; i < ProcessInfo->NumberOfThreads; i++) {
                Status = PerfInfoReserveBytes(&Hook, 
                                              WMI_LOG_TYPE_THREAD_DC_START, 
                                              sizeof(WMI_EXTENDED_THREAD_INFORMATION));
                if (NT_SUCCESS(Status)){
                    WmiThreadInfo = PERFINFO_HOOK_HANDLE_TO_DATA(Hook, PWMI_EXTENDED_THREAD_INFORMATION);
                    WmiThreadInfo->ProcessId =  HandleToUlong(ThreadInfo->ThreadInfo.ClientId.UniqueProcess);
                    WmiThreadInfo->ThreadId =  HandleToUlong(ThreadInfo->ThreadInfo.ClientId.UniqueThread);
                    WmiThreadInfo->StackBase = ThreadInfo->StackBase;
                    WmiThreadInfo->StackLimit = ThreadInfo->StackLimit;

                    WmiThreadInfo->UserStackBase = NULL;
                    WmiThreadInfo->UserStackLimit = NULL;
                    WmiThreadInfo->StartAddr = ThreadInfo->ThreadInfo.StartAddress;
                    WmiThreadInfo->Win32StartAddr = ThreadInfo->Win32StartAddress;
                    WmiThreadInfo->WaitMode = -1;
                    PERF_FINISH_HOOK(Hook);
                }

                ThreadInfo  += 1;
            }

            if (ProcessInfo->NextEntryOffset == 0) {
                break;
            } else {
                TotalOffset += ProcessInfo->NextEntryOffset;
                ProcessInfo = (PSYSTEM_PROCESS_INFORMATION) &Buffer[TotalOffset];
            }
        }
    } 

    ExFreePool(Buffer);
    return Status;

}
Пример #13
0
NTSTATUS
PerfInfoLogBytesAndUnicodeString(
    USHORT HookId,
    PVOID SourceData,
    ULONG SourceByteCount,
    PUNICODE_STRING String
    )
/*++

Routine description:

    This routine logs data with UniCode string at the end of the hook.

Arguments:
    
    HookId - Hook Id.

    SourceData - Pointer to the data to be copied

    SourceByteCount - Number of bytes to be copied.
    
    String - The string to be logged.

Return Value:
    Status

--*/
{
    NTSTATUS Status;
    PERFINFO_HOOK_HANDLE Hook;
    ULONG ByteCount;
    ULONG StringBytes;

    if (String == NULL) {
        StringBytes = 0;
    } else {
        StringBytes = String->Length;
        if (StringBytes > MAX_FILENAME_TO_LOG) {
            StringBytes = MAX_FILENAME_TO_LOG;
        }
    }

    ByteCount = (SourceByteCount + StringBytes + sizeof(WCHAR));

    Status = PerfInfoReserveBytes(&Hook, HookId, ByteCount);
    if (NT_SUCCESS(Status))
    {
        const PVOID pvTemp = PERFINFO_HOOK_HANDLE_TO_DATA(Hook, PVOID);
        RtlCopyMemory(pvTemp, SourceData, SourceByteCount);
        if (StringBytes != 0) {
            RtlCopyMemory(PERFINFO_APPLY_OFFSET_GIVING_TYPE(pvTemp, SourceByteCount, PVOID),
                          String->Buffer,
                          StringBytes
                          );
        }
        (PERFINFO_APPLY_OFFSET_GIVING_TYPE(pvTemp, SourceByteCount, PWCHAR))[StringBytes / sizeof(WCHAR)] = UNICODE_NULL;
        PERF_FINISH_HOOK(Hook);

        Status = STATUS_SUCCESS;
    }
    return Status;
}
Пример #14
0
NTSTATUS
MacConnect(
    IN  PXENVIF_MAC     Mac
    )
{
    PXENVIF_FRONTEND    Frontend;
    PCHAR               Buffer;
    ULONG64             Mtu;
    NTSTATUS            status;

    Frontend = Mac->Frontend;

    Mac->StoreInterface = FrontendGetStoreInterface(Frontend);

    STORE(Acquire, Mac->StoreInterface);

    status = STORE(Read,
                   Mac->StoreInterface,
                   NULL,
                   FrontendGetPath(Frontend),
                   "mtu",
                   &Buffer);
    if (!NT_SUCCESS(status)) {
        Mtu = ETHERNET_MTU;
    } else {
        Mtu = strtol(Buffer, NULL, 10);

        STORE(Free,
              Mac->StoreInterface,
              Buffer);
    }

    status = STATUS_INVALID_PARAMETER;
    if (Mtu < ETHERNET_MIN)
        goto fail1;

    Mac->MaximumFrameSize = (ULONG)Mtu + sizeof (ETHERNET_TAGGED_HEADER);

    status = __MacSetPermanentAddress(Mac,
                                      FrontendGetPermanentMacAddress(Frontend));
    if (!NT_SUCCESS(status))
        goto fail2;

    status = __MacSetCurrentAddress(Mac,
                                    FrontendGetCurrentMacAddress(Frontend));
    if (!NT_SUCCESS(status))
        RtlCopyMemory(&Mac->CurrentAddress,
                      &Mac->PermanentAddress,
                      sizeof (ETHERNET_ADDRESS));

    RtlFillMemory(Mac->BroadcastAddress.Byte, ETHERNET_ADDRESS_LENGTH, 0xFF);

    Mac->DebugInterface = FrontendGetDebugInterface(Frontend);

    DEBUG(Acquire, Mac->DebugInterface);

    status = DEBUG(Register,
                   Mac->DebugInterface,
                   __MODULE__ "|MAC",
                   MacDebugCallback,
                   Mac,
                   &Mac->DebugCallback);
    if (!NT_SUCCESS(status))
        goto fail3;

    ASSERT(!Mac->Connected);
    Mac->Connected = TRUE;

    return STATUS_SUCCESS;

fail3:
    Error("fail3\n");

    DEBUG(Release, Mac->DebugInterface);
    Mac->DebugInterface = NULL;

    RtlZeroMemory(Mac->BroadcastAddress.Byte, ETHERNET_ADDRESS_LENGTH);
    RtlZeroMemory(Mac->CurrentAddress.Byte, ETHERNET_ADDRESS_LENGTH);
    RtlZeroMemory(Mac->PermanentAddress.Byte, ETHERNET_ADDRESS_LENGTH);

fail2:
    Error("fail2\n");

    Mac->MaximumFrameSize = 0;

fail1:
    Error("fail1 (%08x)\n");

    STORE(Release, Mac->StoreInterface);
    Mac->StoreInterface = NULL;

    return status;
}
Пример #15
0
VOID
NTAPI
Fati8dot3ToString(IN PCHAR FileName,
                  IN BOOLEAN DownCase,
                  OUT POEM_STRING OutString)
{
    ULONG BaseLen, ExtLen;
    CHAR  *cString = OutString->Buffer;
    ULONG i;

    /* Calc base and ext lens */
    for (BaseLen = 8; BaseLen > 0; BaseLen--)
    {
        if (FileName[BaseLen - 1] != ' ') break;
    }

    for (ExtLen = 3; ExtLen > 0; ExtLen--)
    {
        if (FileName[8 + ExtLen - 1] != ' ') break;
    }

    /* Process base name */
    if (BaseLen)
    {
        RtlCopyMemory(cString, FileName, BaseLen);

        /* Substitute the e5 thing */
        if (cString[0] == 0x05) cString[0] = 0xe5;

        /* Downcase if asked to */
        if (DownCase)
        {
            /* Do it manually */
            for (i = 0; i < BaseLen; i++)
            {
                if (cString[i] >= 'A' &&
                    cString[i] <= 'Z')
                {
                    /* Lowercase it */
                    cString[i] += 'a' - 'A';
                }

            }
        }
    }

    /* Process extension */
    if (ExtLen)
    {
        /* Add the dot */
        cString[BaseLen] = '.';
        BaseLen++;

        /* Copy the extension */
        for (i = 0; i < ExtLen; i++)
        {
            cString[BaseLen + i] = FileName[8 + i];
        }

        /* Lowercase the extension if asked to */
        if (DownCase)
        {
            /* Do it manually */
            for (i = BaseLen; i < BaseLen + ExtLen; i++)
            {
                if (cString[i] >= 'A' &&
                    cString[i] <= 'Z')
                {
                    /* Lowercase it */
                    cString[i] += 'a' - 'A';
                }
            }
        }
    }

    /* Set the length */
    OutString->Length = BaseLen + ExtLen;

    DPRINT("'%s', len %d\n", OutString->Buffer, OutString->Length);
}
Пример #16
0
int _tmain(int argc, _TCHAR* argv[])
{
	MessageBox(NULL, _T("Exe Withou CRT lib."), _T("OK"), MB_OK);

	TCHAR tszDllPath[] = _T("F:\\RtlExUpd.dll");

	MEM_MODULE sMemModule;
	RtlZeroMemory(&sMemModule, sizeof(sMemModule));
	sMemModule.RawFile.h = INVALID_HANDLE_VALUE;

	NTFUNCPTRSTABLE sNtFuncPtrsTable;

	sNtFuncPtrsTable.pfnCreateFileW = CreateFileW;
	sNtFuncPtrsTable.pfnGetFileSize = GetFileSize;
	sNtFuncPtrsTable.pfnCreateFileMappingW = CreateFileMappingW;
	sNtFuncPtrsTable.pfnMapViewOfFile = MapViewOfFile;
	sNtFuncPtrsTable.pfnUnmapViewOfFile = UnmapViewOfFile;
	sNtFuncPtrsTable.pfnCloseHandle = CloseHandle;
	sNtFuncPtrsTable.pfnGetModuleHandleA = GetModuleHandleA;
	sNtFuncPtrsTable.pfnLoadLibraryA = LoadLibraryA;
	sNtFuncPtrsTable.pfnGetProcAddress = GetProcAddress;
	sNtFuncPtrsTable.pfnVirtualAlloc = VirtualAlloc;
	sNtFuncPtrsTable.pfnVirtualFree = VirtualFree;
	sNtFuncPtrsTable.pfnVirtualProtect = VirtualProtect;

	sMemModule.pNtFuncptrsTable = &sNtFuncPtrsTable;

	TCHAR tszFormat[] = _T("Address of ShowLastError: %p");
	TCHAR tszText[MAX_PATH];
	RtlZeroMemory(tszText, sizeof(tszText));

	//////////////////////////////////////////////////////////////////////////
	// 先使用原始函数Test

	//if (LoadMemModule(&sMemModule, tszDllPath, FALSE))
	if (MemModuleHelper(&sMemModule, MHM_BOOL_LOAD, tszDllPath, NULL, FALSE))
	{
		//LPVOID lpAddr = (LPVOID)GetMemModuleProc(&sMemModule, "SetCDfmt");
		LPVOID lpAddr = (LPVOID)MemModuleHelper(&sMemModule, MHM_FARPROC_GETPROC, NULL, "SetCDfmt", FALSE);
		
		StringCchPrintf(tszText, _countof(tszText), tszFormat, lpAddr);

		MessageBox(NULL, tszText, NULL, MB_OK);

		//FreeMemModule(&sMemModule);
		MemModuleHelper(&sMemModule, MHM_VOID_FREE, NULL, NULL, FALSE);
	}


	// 把ShellCode 拷贝到任意内存地址再进行测试

	DWORD dwShellCodeLen = 0;
	dwShellCodeLen = (DWORD)mmLoaderSCEnd - (DWORD)mmLoaderSCStart;

	LPVOID lpShellCodeBase = VirtualAlloc(
		NULL, 
		dwShellCodeLen, 
		MEM_RESERVE | MEM_COMMIT, 
		PAGE_EXECUTE_READWRITE);

	if (NULL == lpShellCodeBase)
	{
		MessageBox(NULL, _T("为ShellCode分配内存空间失败!"), NULL, MB_OK);
		return FALSE;
	}

	RtlCopyMemory(lpShellCodeBase, mmLoaderSCStart, dwShellCodeLen);

	Type_MemModuleHelper pfnMemModuleHelper = (Type_MemModuleHelper)lpShellCodeBase;

	if (pfnMemModuleHelper(&sMemModule, MHM_BOOL_LOAD, tszDllPath, NULL, FALSE))
	{
		LPVOID lpAddr = (LPVOID)pfnMemModuleHelper(&sMemModule, MHM_FARPROC_GETPROC, NULL, "SetCDfmt", FALSE);

		StringCchPrintf(tszText, _countof(tszText), tszFormat, lpAddr);

		MessageBox(NULL, tszText, NULL, MB_OK);

		pfnMemModuleHelper(&sMemModule, MHM_VOID_FREE, NULL, NULL, FALSE);
	}

	VirtualFree(lpShellCodeBase, 0, MEM_RELEASE);


	// 直接使用提取出来的ShellCode测试!
	lpShellCodeBase = VirtualAlloc(
		NULL, 
		sizeof(mmLoaderShellCode), 
		MEM_RESERVE | MEM_COMMIT, 
		PAGE_EXECUTE_READWRITE);

	if (NULL == lpShellCodeBase)
	{
		MessageBox(NULL, _T("为ShellCode分配内存空间失败!"), NULL, MB_OK);
		return FALSE;
	}

	RtlCopyMemory(lpShellCodeBase, mmLoaderShellCode, sizeof(mmLoaderShellCode));

	pfnMemModuleHelper = (Type_MemModuleHelper)lpShellCodeBase;

	if (pfnMemModuleHelper(&sMemModule, MHM_BOOL_LOAD, tszDllPath, NULL, FALSE))
	{
		LPVOID lpAddr = (LPVOID)pfnMemModuleHelper(&sMemModule, MHM_FARPROC_GETPROC, NULL, "SetCDfmt", FALSE);

		StringCchPrintf(tszText, _countof(tszText), tszFormat, lpAddr);

		MessageBox(NULL, tszText, NULL, MB_OK);

		pfnMemModuleHelper(&sMemModule, MHM_VOID_FREE, NULL, NULL, FALSE);
	}

	VirtualFree(lpShellCodeBase, 0, MEM_RELEASE);

	return 0;
}
Пример #17
0
/*
 * @implemented
 */
NTSTATUS
QueryPointsFromMemory(IN PDEVICE_EXTENSION DeviceExtension,
                      IN PIRP Irp,
                      IN PMOUNTDEV_UNIQUE_ID UniqueId OPTIONAL,
                      IN PUNICODE_STRING SymbolicName OPTIONAL)
{
    NTSTATUS Status;
    PIO_STACK_LOCATION Stack;
    UNICODE_STRING DeviceName;
    ULONG TotalSize, TotalSymLinks;
    PMOUNTMGR_MOUNT_POINTS MountPoints;
    PDEVICE_INFORMATION DeviceInformation;
    PLIST_ENTRY DeviceEntry, SymlinksEntry;
    PSYMLINK_INFORMATION SymlinkInformation;

    /* If we got a symbolic link, query device */
    if (SymbolicName)
    {
        Status = QueryDeviceInformation(SymbolicName,
                                        &DeviceName,
                                        NULL, NULL,
                                        NULL, NULL,
                                        NULL, NULL);
        if (!NT_SUCCESS(Status))
        {
            return Status;
        }
    }

    /* Browse all the links to count number of links & size used */
    TotalSize = 0;
    TotalSymLinks = 0;
    for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
         DeviceEntry != &(DeviceExtension->DeviceListHead);
         DeviceEntry = DeviceEntry->Flink)
    {
        DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

        /* If we were given an unique ID, it has to match */
        if (UniqueId)
        {
            if (UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
            {
                continue;
            }

            if (RtlCompareMemory(UniqueId->UniqueId,
                                 DeviceInformation->UniqueId->UniqueId,
                                 UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
            {
                continue;
            }
        }
        /* Or, if we had a symlink, it has to match */
        else if (SymbolicName)
        {
            if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
            {
                continue;
            }
        }

        /* Once here, it matched, save device name & unique ID size */
        TotalSize += DeviceInformation->DeviceName.Length + DeviceInformation->UniqueId->UniqueIdLength;

        /* And count number of symlinks (and their size) */
        for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
             SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
             SymlinksEntry = SymlinksEntry->Flink)
        {
            SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);

            TotalSize += SymlinkInformation->Name.Length;
            TotalSymLinks++;
        }

        /* We had a specific item to find
         * if we reach that point, we found it, no need to continue
         */
        if (UniqueId || SymbolicName)
        {
            break;
        }
    }

    /* If we were looking for specific item, ensure we found it */
    if (UniqueId || SymbolicName)
    {
        if (DeviceEntry == &(DeviceExtension->DeviceListHead))
        {
            if (DeviceName.Buffer)
            {
                FreePool(DeviceName.Buffer);
            }

            return STATUS_INVALID_PARAMETER;
        }
    }

    /* Now, ensure output buffer can hold everything */
    Stack = IoGetNextIrpStackLocation(Irp);
    MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;

    /* Ensure we set output to let user reallocate! */
    MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalSize;
    MountPoints->NumberOfMountPoints = TotalSymLinks;

    if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
    {
        return STATUS_BUFFER_OVERFLOW;
    }

    /* Now, start putting mount points */
    TotalSymLinks = 0;
    TotalSize = 0;
    for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
         DeviceEntry != &(DeviceExtension->DeviceListHead);
         DeviceEntry = DeviceEntry->Flink)
    {
        DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

        /* Find back correct mount point */
        if (UniqueId)
        {
            if (!UniqueId->UniqueIdLength != DeviceInformation->UniqueId->UniqueIdLength)
            {
                continue;
            }

            if (RtlCompareMemory(UniqueId->UniqueId,
                                 DeviceInformation->UniqueId->UniqueId,
                                 UniqueId->UniqueIdLength) != UniqueId->UniqueIdLength)
            {
                continue;
            }
        }
        else if (SymbolicName)
        {
            if (!RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE))
            {
                continue;
            }
        }

        /* Now we've got it, but all the data */
        for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
             SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
             SymlinksEntry = SymlinksEntry->Flink)
        {
            SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);


            MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
                                                                             TotalSize;
            MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
            MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
                                                                     SymlinkInformation->Name.Length +
                                                                     TotalSize;
            MountPoints->MountPoints[TotalSymLinks].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
            MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
                                                                       SymlinkInformation->Name.Length +
                                                                       DeviceInformation->UniqueId->UniqueIdLength +
                                                                       TotalSize;
            MountPoints->MountPoints[TotalSymLinks].DeviceNameLength = DeviceInformation->DeviceName.Length;

            RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].SymbolicLinkNameOffset),
                          SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);
            RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].UniqueIdOffset),
                          DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength);
            RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[TotalSymLinks].DeviceNameOffset),
                  DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);

            /* Update counters */
            TotalSymLinks++;
            TotalSize += SymlinkInformation->Name.Length + DeviceInformation->UniqueId->UniqueIdLength +
                         DeviceInformation->DeviceName.Length;
        }

        if (UniqueId || SymbolicName)
        {
            break;
        }
    }

    return STATUS_SUCCESS;
}
Пример #18
0
NTSTATUS
Bus_IoCtl (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

    Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

   NT status code

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen, outlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;

    PAGED_CODE ();

	//
	// It is not safe to call IOCTL in raised IRQL.
	//

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
    
    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    //
    // We only take Device Control requests for the FDO.
    // That is the bus itself.
    //

    if (!fdoData->IsFDO) {
    
        //
        // These commands are only allowed to go to the FDO.
        //   
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;

    }

    //
    // Check to see whether the bus is removed
    //
    
    if (fdoData->DevicePnPState == Deleted) {
        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    Bus_IncIoCount (fdoData);
    
    irpStack = IoGetCurrentIrpStackLocation (Irp);

    buffer			= Irp->AssociatedIrp.SystemBuffer;  
    inlen			= irpStack->Parameters.DeviceIoControl.InputBufferLength;
    outlen			= irpStack->Parameters.DeviceIoControl.OutputBufferLength;

    status = STATUS_INVALID_PARAMETER;

	Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode));
    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) 
	{

	case IOCTL_NDASBUS_ADD_TARGET:
	{
		PPDO_DEVICE_DATA	pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));

		if ((inlen == outlen) &&
			(sizeof(NDASBUS_ADD_TARGET_DATA) <= inlen)) 
		{
			ULONG						ulSize;
			PNDASBUS_ADD_TARGET_DATA	addTargetData = buffer;
			BOOLEAN						accepted;
			
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_ADD_TARGET called\n"));
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType));

			status = STATUS_SUCCESS;
			
			//
			// Check structure size
			//
			if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) {
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			if(ulSize != inlen) 
			{
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen));
				status = STATUS_UNSUCCESSFUL;
				break;
			}

			//
			//	Check to see if acceptable structure.
			//

			accepted = TRUE;
			switch(addTargetData->ucTargetType) 
			{
			case NDASSCSI_TYPE_DISK_NORMAL: 
			case NDASSCSI_TYPE_DVD: 
			case NDASSCSI_TYPE_VDVD: 
			case NDASSCSI_TYPE_MO:

				if(addTargetData->ulNumberOfUnitDiskList != 1)
					accepted = FALSE;
				break;

			case NDASSCSI_TYPE_DISK_MIRROR:

				if(2 != addTargetData->ulNumberOfUnitDiskList)
					accepted = FALSE;

				break;

			case NDASSCSI_TYPE_DISK_AGGREGATION:

				if (addTargetData->ulNumberOfUnitDiskList < 2 || 
					addTargetData->ulNumberOfUnitDiskList > MAX_NR_UNITDISK_FOR_AGGR)
					accepted = FALSE;
				break;

			case NDASSCSI_TYPE_DISK_RAID0:
				switch(addTargetData->ulNumberOfUnitDiskList)
				{
				case 2:
				case 4:
				case 8:
					break;
				default: // do not accept
					accepted = FALSE;
					break;
				}
				break;
			case NDASSCSI_TYPE_DISK_RAID1R3:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					if (2 != ulDiskCount) 
						accepted = FALSE;
				}
				break;
			case NDASSCSI_TYPE_DISK_RAID4R3:
			case NDASSCSI_TYPE_DISK_RAID5:
				{
					ULONG						ulDiskCount;
					ulDiskCount = addTargetData->ulNumberOfUnitDiskList - 
						addTargetData->RAID_Info.nSpareDisk;
					switch(ulDiskCount)
				{
				case 3: // 2 + 1
				case 5: // 4 + 1
				case 9: // 8 + 1
					break;
				default: // do not accept
					accepted = FALSE;
					break;
				}
				break;
				}				
			default:
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n"));
				accepted = FALSE;
				break;
			}
			if(accepted == FALSE) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n"));
				status = STATUS_UNSUCCESSFUL;
				break;
			}
						
#if DBG
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_TRY_TO_ADDTARGET,
				IOCTL_NDASBUS_ADD_TARGET,
				addTargetData->ulSlotNo);
#endif
			// Find Pdo Data...
			pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo);
			if(pdoData == NULL) 
			{
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("no pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
									NDASBUS_IO_PDO_NOT_FOUND,
									IOCTL_NDASBUS_ADD_TARGET,
									addTargetData->ulSlotNo);
				break;
			}

			//
			// Save the add target information to the PDO extension
			//

			pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, inlen, BUSENUM_POOL_TAG);
			
			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) 
			{
				Irp->IoStatus.Information = 0;
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}
			else 
			{
				RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen);
				status = STATUS_SUCCESS;
			}

			pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen;

			//
			// Init PDO status
			//

			pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTER_STATUS_INIT;
			pdoData->LanscsiAdapterPDO.DeviceMode = addTargetData->DeviceMode;

			//
			//	Notify to NDASSCSI
			//
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n"));
			KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE);

			//
			//	Register Target
			//
			if(pdoData->Persistent) {
				status = LSBus_RegisterTarget(fdoData, addTargetData);
				if(!NT_SUCCESS(status)) {
					ExFreePoolWithTag(pdoData->LanscsiAdapterPDO.AddDevInfo, BUSENUM_POOL_TAG);
					pdoData->LanscsiAdapterPDO.AddDevInfo = NULL;
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status));
					status = STATUS_INTERNAL_DB_ERROR;
					NDBusIoctlLogError(	fdoData->Self,
										NDASBUS_IO_REGISTER_TARGET_FAIL,
										IOCTL_NDASBUS_ADD_TARGET,
										addTargetData->ulSlotNo);
				} else {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n"));
				}
			}

			ObDereferenceObject(pdoData->Self);

			Irp->IoStatus.Information = outlen;
		}        
		else
		{
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
								("IOCTL_NDASBUS_ADD_TARGET length mismatch!!!"
								" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
								inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		}

	}
		break;

	case IOCTL_NDASBUS_REMOVE_TARGET:
	{
	    PPDO_DEVICE_DATA	pdoData;
		PNDASBUS_REMOVE_TARGET_DATA	removeTarget;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REMOVE_TARGET called\n"));

        if (sizeof (NDASBUS_REMOVE_TARGET_DATA) != inlen)
			break;

		removeTarget = (PNDASBUS_REMOVE_TARGET_DATA)buffer;
		pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_REMOVE_TARGET,
				removeTarget->ulSlotNo);
			break;
		}

		//
		//	redirect to the NDAS SCSI Device
		//
		status = LSBus_IoctlToNdasScsiDevice(
				pdoData,
				NDASSCSI_IOCTL_REMOVE_DEVICE,
				NULL,
				0,
				NULL,
				0
			);

		if(NT_SUCCESS(status) && pdoData->Persistent) {

			status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId);
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, (	"REMOVE_TARGET: Removed  Target instance,"
															" but LSBus_UnregisterTarget() failed.\n"));
				status = STATUS_INTERNAL_DB_ERROR;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_UNREGISTER_TARGET_FAIL,
					IOCTL_NDASBUS_REMOVE_TARGET,
					removeTarget->ulSlotNo);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n"));
			}
#endif
		}

		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = 0;
		break;
	}

	case IOCTL_NDASBUS_STARTSTOP_REGISTRARENUM:{
		PULONG	onOff = (PULONG)buffer;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
			"STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff));

		KeEnterCriticalRegion();
		ExAcquireFastMutexUnsafe(&fdoData->RegMutex);

		if(*onOff != 0) {

			//
			//	Save old state.
			//	Activate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = TRUE;
		} else {

			//
			//	Save old state.
			//	Deactivate the registrar's enumeration
			//

			*onOff = fdoData->StartStopRegistrarEnum;
			fdoData->StartStopRegistrarEnum = FALSE;
		}

		//
		//	Clean up non-enumerated entries.
		//
		LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData);

		ExReleaseFastMutexUnsafe(&fdoData->RegMutex);
		KeLeaveCriticalRegion();

		Irp->IoStatus.Information = sizeof(ULONG);
		status = STATUS_SUCCESS;

		break;
	}

	case IOCTL_NDASBUS_REGISTER_DEVICE:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
							"REGISTER_DEVICE: inlen %d, outlen %d,"
							" sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n",
							inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2)));
		if ((inlen == outlen)) {

			PNDASBUS_PLUGIN_HARDWARE_EX2	PlugIn = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n"));

			status = LSBus_RegisterDevice(fdoData, PlugIn);

			Irp->IoStatus.Information = 0;
		}
		else
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR,
									("REGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n",
									inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2)));

	}
		break;
	case IOCTL_NDASBUS_REGISTER_TARGET:
	{

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		if ((inlen == outlen)) {

			PNDASBUS_ADD_TARGET_DATA	AddTargetData = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n"));

			status = LSBus_RegisterTarget(fdoData, AddTargetData);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"REGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA)));
		}

	}
		break;
	case IOCTL_NDASBUS_UNREGISTER_DEVICE:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: inlen %d, outlen %d,"
									" sizeof(NDASBUS_UNREGISTER_NDASDEV) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV)));
		if ((inlen == outlen)) {

			PNDASBUS_UNREGISTER_NDASDEV	UnregDev = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n"));

			status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_DEVICE: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV)));
		}
	}
	break;
	case IOCTL_NDASBUS_UNREGISTER_TARGET:
	{
		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: inlen %d, outlen %d,"
									" sizeof(NDASBUS_UNREGISTER_TARGET) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET)));
		if ((inlen == outlen)) {

			PNDASBUS_UNREGISTER_TARGET	UnregTarget = buffer;

			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n"));

			status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId);

			Irp->IoStatus.Information = 0;
		}
		else {
			Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, (
									"UNREGISTER_TARGET: length mismatch!!!"
									" inlen %d, outlen %d, sizeof(NDASBUS_UNREGISTER_TARGET) %d\n",
									inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET)));
		}
	}
	break;
	case IOCTL_NDASBUS_SETPDOINFO:
		{
	    PPDO_DEVICE_DATA	pdoData;
		PNDASBUS_SETPDOINFO	SetPdoInfo;
		KIRQL				oldIrql;
		PVOID				sectionHandle;
		BOOLEAN				acceptStatus;

        Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_SETPDOINFO called\n"));

        if (sizeof (NDASBUS_SETPDOINFO) != inlen)
			break;

		acceptStatus = TRUE;
		SetPdoInfo = (PNDASBUS_SETPDOINFO)buffer;
		pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("no pdo\n"));
			status = STATUS_UNSUCCESSFUL;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_SETPDOINFO,
				SetPdoInfo->SlotNo);
			break;
		}

		//
		//	lock the code section of this function to acquire spinlock in raised IRQL.
		//
	    sectionHandle = MmLockPagableCodeSection(Bus_IoCtl);

		KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!!  SETPDOINFO: PDO %p: %08lx %08lx %08lx\n",
										pdoData->Self, SetPdoInfo->AdapterStatus,
										SetPdoInfo->SupportedFeatures,
										SetPdoInfo->EnabledFeatures));


		//
		// Deny the status change if the current status is STATUS_STOPPED except for RESETSTATUS flag.
		//

		if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n"));

				if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS)) {
					Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n"));
				} else {
					acceptStatus = FALSE;
				}
		} else {
			if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
				acceptStatus = FALSE;
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: AddTarget is not occured. Too early to set status.\n"));
			}
		}

		//
		// Mask off RESETSTATUS.
		// NDAS service does not need to know it.
		//

		SetPdoInfo->AdapterStatus &= ~NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS;

		//
		// Set status values to the corresponding physical device object.
		// Save to the extension
		//

		if(acceptStatus) {
			PNDASBUS_PDOEVENT_ENTRY	pdoEventEntry;

			pdoEventEntry = NdasBusCreatePdoStatusItem(SetPdoInfo->AdapterStatus);
			if(pdoEventEntry) {
				NdasBusQueuePdoStatusItem(&pdoData->LanscsiAdapterPDO, pdoEventEntry);
			}
#if DBG
			else {
				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Could not allocate PDO status entry.\n"));
			}
#endif

			pdoData->LanscsiAdapterPDO.LastAdapterStatus = SetPdoInfo->AdapterStatus;
			pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures;
			pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures;

			//
			//	Queue plugout worker if the NDAS SCSI stop abnormally.
			// Notify the NDAS service of abnormal termination
			//
			if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) &&
				ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTER_STATUSFLAG_ABNORMAL_TERMINAT)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n"));

				status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo);

				//
				// Set disconnection event
				//

				KeSetEvent(pdoData->LanscsiAdapterPDO.DisconEventToService, IO_DISK_INCREMENT, FALSE);
			} else {
				//
				// Notify the adapter status change
				//
				KeSetEvent(pdoData->LanscsiAdapterPDO.AlarmEventToService, IO_DISK_INCREMENT, FALSE);
			}
		}

		KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);


		//
		//	Release the code section.
		//

	    MmUnlockPagableImageSection(sectionHandle);

		status = STATUS_SUCCESS;
		ObDereferenceObject(pdoData->Self);

        Irp->IoStatus.Information = outlen;
	}
		break;

	case IOCTL_NDASBUS_QUERY_NODE_ALIVE: 
		{

		PPDO_DEVICE_DATA		pdoData;
		BOOLEAN					bAlive;
		PNDASBUS_NODE_ALIVE_IN	pNodeAliveIn;
		NDASBUS_NODE_ALIVE_OUT	nodeAliveOut;

		// Check Parameter.
		if(inlen != sizeof(NDASBUS_NODE_ALIVE_IN) || 
			outlen != sizeof(NDASBUS_NODE_ALIVE_OUT)) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		
		pNodeAliveIn = (PNDASBUS_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer;  
		
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE,
			("FDO: IOCTL_NDASBUS_QUERY_NODE_ALIVE SlotNumber = %d\n",
			pNodeAliveIn->SlotNo));
		
		pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo);

		if(pdoData == NULL) {
//			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
//				("[LanScsiBus]Bus_IoCtl: IOCTL_NDASBUS_QUERY_NODE_ALIVE No pdo\n"));
			
			bAlive = FALSE;
		} else {
			//
			// Check this PDO would be removed...
			//
			if(pdoData->Present == TRUE) 
				bAlive = TRUE;
			else
				bAlive = FALSE;
		}

		// For Result...
		nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo;
		nodeAliveOut.bAlive = bAlive;
		// Get Adapter Status.
		if(bAlive == TRUE)
		{
			if(	ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPING)) {

				nodeAliveOut.bHasError = TRUE;
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_NDASBUS_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError));
			} else {
				nodeAliveOut.bHasError = FALSE;
			}

		}

		if(pdoData)
			ObDereferenceObject(pdoData->Self);

		RtlCopyMemory(
			Irp->AssociatedIrp.SystemBuffer,
			&nodeAliveOut,
			sizeof(NDASBUS_NODE_ALIVE_OUT)
			);
		
		Irp->IoStatus.Information = sizeof(NDASBUS_NODE_ALIVE_OUT);
		status = STATUS_SUCCESS;
		}
		break;

	//
	//	added by hootch 01172004
	//
	case IOCTL_NDASBUS_UPGRADETOWRITE:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_UPGRADETOWRITE called\n"));
		// Check Parameter.
		if(inlen != sizeof(NDASBUS_UPGRADE_TO_WRITE)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_UPGRADETOWRITE: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		pdoData = LookupPdoData(fdoData, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_UPGRADETOWRITE,
				((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo);
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					NDASSCSI_IOCTL_UPGRADETOWRITE,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_NDASBUS_REDIRECT_NDASSCSI:
		{
		PPDO_DEVICE_DATA				pdoData;
		PNDASBUS_REDIRECT_NDASSCSI		redirectIoctl;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI called\n"));
		// Check Parameter.
		if(inlen < sizeof(NDASBUS_REDIRECT_NDASSCSI)) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_REDIRECT_NDASSCSI: Invalid input buffer length\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		redirectIoctl = (PNDASBUS_REDIRECT_NDASSCSI)buffer;

		pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo);
		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo));
			status = STATUS_NO_SUCH_DEVICE;
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					redirectIoctl->IoctlCode,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize,
					redirectIoctl->IoctlData,
					redirectIoctl->IoctlDataSize
				);

			ObDereferenceObject(pdoData->Self);
		}
		Irp->IoStatus.Information = 0;
	}
		break;

	case IOCTL_NDASBUS_QUERY_NDASSCSIINFO:
		{
		PPDO_DEVICE_DATA				pdoData;

		Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n"));
		// Check Parameter.
		if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n"));
			status = STATUS_UNKNOWN_REVISION;
			break;
		}
		pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo);

		if(pdoData == NULL) {
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n"));
			status = STATUS_NO_SUCH_DEVICE;
			NDBusIoctlLogError(	fdoData->Self,
				NDASBUS_IO_PDO_NOT_FOUND,
				IOCTL_NDASBUS_QUERY_NDASSCSIINFO,
				((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo);
		} else {
			//
			//	redirect to the NDASSCSI Device
			//
			status = LSBus_IoctlToNdasScsiDevice(
					pdoData,
					NDASSCSI_IOCTL_QUERYINFO_EX,
					buffer,
					inlen,
					buffer,
					outlen
				);

			ObDereferenceObject(pdoData->Self);
		}
        Irp->IoStatus.Information = outlen;
		}
		break;

	case IOCTL_NDASBUS_QUERY_INFORMATION:
		{

//		PPDO_DEVICE_DATA				pdoData;
		NDASBUS_QUERY_INFORMATION		Query;
		PNDASBUS_INFORMATION			Information;
		LONG							BufferLenNeeded;

		// Check Parameter.
		if(	inlen < sizeof(NDASBUS_QUERY_INFORMATION) /*|| 
			outlen < sizeof(NDASBUS_INFORMATION) */) {
			status = STATUS_UNKNOWN_REVISION;
			break;
		}

		RtlCopyMemory(&Query, buffer, sizeof(NDASBUS_QUERY_INFORMATION));
		Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE,
			("FDO: IOCTL_NDASBUS_QUERY_INFORMATION QueryType : %d  SlotNumber = %d\n",
			Query.InfoClass, Query.SlotNo));

		Information = (PNDASBUS_INFORMATION)buffer;
		ASSERT(Information);
		Information->InfoClass = Query.InfoClass;
		status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded);
		if(NT_SUCCESS(status)) {
			Information->Size = BufferLenNeeded;
			Irp->IoStatus.Information = BufferLenNeeded;
		} else {
			Irp->IoStatus.Information = BufferLenNeeded;
		}
		}
		break;

	case IOCTL_NDASBUS_PLUGIN_HARDWARE_EX2:
		{
			ULONG	structLen;		// Without variable length field
			ULONG	wholeStructLen; // With variable length field
			ULONG	inputWholeStructLen;

			//
			// Check 32 bit thunking request
            //
			if(IoIs32bitProcess(Irp)) {
				structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2_32, HardwareIDs);
				wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2_32);
				inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2_32) buffer)->Size;
			} else {
				structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2, HardwareIDs);
				wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2);
				inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2) buffer)->Size;
			}

			if ((inlen == outlen) &&
				//
				// Make sure it has at least two nulls and the size 
				// field is set to the declared size of the struct
				//
				((structLen + sizeof(UNICODE_NULL) * 2) <=
				inlen) &&

				//
				// The size field should be set to the sizeof the struct as declared
				// and *not* the size of the struct plus the multi_sz
				//
				(wholeStructLen == inputWholeStructLen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

				status= Bus_PlugInDeviceEx2((PNDASBUS_PLUGIN_HARDWARE_EX2)buffer,
											inlen,
											fdoData,
											IoIs32bitProcess(Irp),
											Irp->RequestorMode, FALSE);

				Irp->IoStatus.Information = outlen;

			}
		}
        break;

	case IOCTL_NDASBUS_GETVERSION:
		{
			if (outlen >= sizeof(NDASBUS_GET_VERSION)) {
				PNDASBUS_GET_VERSION version = (PNDASBUS_GET_VERSION)buffer;

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_GETVERSION: called\n"));

			try {
				version->VersionMajor = VER_FILEMAJORVERSION;
				version->VersionMinor = VER_FILEMINORVERSION;
				version->VersionBuild = VER_FILEBUILD;
				version->VersionPrivate = VER_FILEBUILD_QFE;

					Irp->IoStatus.Information = sizeof(NDASBUS_GET_VERSION);
					status = STATUS_SUCCESS;

				} except (EXCEPTION_EXECUTE_HANDLER) {

					status = GetExceptionCode();
					Irp->IoStatus.Information = 0;
				}

			}
		}			
		break;

    case IOCTL_NDASBUS_UNPLUG_HARDWARE:
		{
			if ((sizeof (NDASBUS_UNPLUG_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PNDASBUS_UNPLUG_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));

				status= Bus_UnPlugDevice(
						(PNDASBUS_UNPLUG_HARDWARE)buffer, fdoData);
				Irp->IoStatus.Information = outlen;

			}
		}
        break;

    case IOCTL_NDASBUS_EJECT_HARDWARE:
		{
			if ((sizeof (NDASBUS_EJECT_HARDWARE) == inlen) &&
				(inlen == outlen) &&
				(((PNDASBUS_EJECT_HARDWARE)buffer)->Size == inlen)) {

				Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));

				status= Bus_EjectDevice((PNDASBUS_EJECT_HARDWARE)buffer, fdoData);

				Irp->IoStatus.Information = outlen;
			}
		}
		break;

	case IOCTL_NDASBUS_DVD_GET_STATUS:
		{
			PPDO_DEVICE_DATA		pdoData;
			PNDASBUS_DVD_STATUS		pDvdStatusData;


			// Check Parameter.
			if((inlen != outlen)
				|| (sizeof(NDASBUS_DVD_STATUS) >  inlen))
			{
				status = STATUS_UNSUCCESSFUL ;
				break;
			}
			
			pDvdStatusData = (PNDASBUS_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer;  
			
			Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
				("FDO: IOCTL_NDASBUS_DVD_GET_STATUS SlotNumber = %d\n",
				pDvdStatusData->SlotNo));	

			pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo);
			
			if(pdoData == NULL) {
				Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
					("IOCTL_NDASBUS_DVD_GET_STATUS No pdo\n"));
				status = STATUS_UNSUCCESSFUL;
				NDBusIoctlLogError(	fdoData->Self,
					NDASBUS_IO_PDO_NOT_FOUND,
					IOCTL_NDASBUS_DVD_GET_STATUS,
					pDvdStatusData->SlotNo);
				break;	
			} else {

				if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
					//
					//	A LUR descriptor is set.
					//
					if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD)
				{
					Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
						("IOCTL_NDASBUS_DVD_GET_STATUS  No DVD Device\n"));
					status = STATUS_UNSUCCESSFUL;
					break;
				}
				} else {
					//
					//	ADD_TARGET_DATA is set.
					//
					if(((PNDASBUS_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD)
					{
						Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR,
							("IOCTL_NDASBUS_DVD_GET_STATUS  No DVD Device\n"));
						status = STATUS_UNSUCCESSFUL;
						break;
					}
				}
				//
				//	redirect to the NDASSCSI Device
				//
				status = LSBus_IoctlToNdasScsiDevice(
						pdoData,
						NDASSCSI_IOCTL_GET_DVD_STATUS,
						buffer,
						inlen,
						buffer,
						outlen
					);

				ObDereferenceObject(pdoData->Self);
				status = STATUS_SUCCESS;
				Irp->IoStatus.Information = outlen;
			}					
		}
		break;
    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }
Пример #19
0
/*
 * @implemented
 */
NTSTATUS
QueryPointsFromSymbolicLinkName(IN PDEVICE_EXTENSION DeviceExtension,
                                IN PUNICODE_STRING SymbolicName,
                                IN PIRP Irp)
{
    NTSTATUS Status;
    ULONG TotalLength;
    PIO_STACK_LOCATION Stack;
    UNICODE_STRING DeviceName;
    PMOUNTMGR_MOUNT_POINTS MountPoints;
    PDEVICE_INFORMATION DeviceInformation = NULL;
    PLIST_ENTRY DeviceEntry, SymlinksEntry;
    PSYMLINK_INFORMATION SymlinkInformation;

    /* Find device */
    Status = QueryDeviceInformation(SymbolicName, &DeviceName,
                                    NULL, NULL, NULL,
                                    NULL, NULL, NULL);
    if (NT_SUCCESS(Status))
    {
        /* Look for the device information */
        for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
             DeviceEntry != &(DeviceExtension->DeviceListHead);
             DeviceEntry = DeviceEntry->Flink)
        {
            DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

            if (RtlEqualUnicodeString(&DeviceName, &(DeviceInformation->DeviceName), TRUE) == 0)
            {
                break;
            }
        }

        FreePool(DeviceName.Buffer);

        if (DeviceEntry == &(DeviceExtension->DeviceListHead))
        {
            return STATUS_INVALID_PARAMETER;
        }

        /* Check for the link */
        for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
             SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
             SymlinksEntry = DeviceEntry->Flink)
        {
            SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);

            if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE) == 0)
            {
                break;
            }
        }

        if (SymlinksEntry == &(DeviceInformation->SymbolicLinksListHead))
        {
            return STATUS_INVALID_PARAMETER;
        }
    }
    else
    {
        /* Browse all the devices to try to find the one
         * that has the given link...
         */
        for (DeviceEntry = DeviceExtension->DeviceListHead.Flink;
             DeviceEntry != &(DeviceExtension->DeviceListHead);
             DeviceEntry = DeviceEntry->Flink)
        {
            DeviceInformation = CONTAINING_RECORD(DeviceEntry, DEVICE_INFORMATION, DeviceListEntry);

            for (SymlinksEntry = DeviceInformation->SymbolicLinksListHead.Flink;
                 SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead);
                 SymlinksEntry = SymlinksEntry->Flink)
            {
                SymlinkInformation = CONTAINING_RECORD(SymlinksEntry, SYMLINK_INFORMATION, SymbolicLinksListEntry);

                if (RtlEqualUnicodeString(SymbolicName, &SymlinkInformation->Name, TRUE) == 0)
                {
                    break;
                }
            }

            if (SymlinksEntry != &(DeviceInformation->SymbolicLinksListHead))
            {
                break;
            }
        }

        /* Even that way we didn't find, give up! */
        if (DeviceEntry == &(DeviceExtension->DeviceListHead))
        {
            return STATUS_OBJECT_NAME_NOT_FOUND;
        }
    }

    /* Get output buffer */
    Stack = IoGetNextIrpStackLocation(Irp);
    MountPoints = (PMOUNTMGR_MOUNT_POINTS)Irp->AssociatedIrp.SystemBuffer;

    /* Compute output length */
    TotalLength = DeviceInformation->UniqueId->UniqueIdLength +
                  SymlinkInformation->Name.Length + DeviceInformation->DeviceName.Length;

    /* Give length to allow reallocation */
    MountPoints->Size = sizeof(MOUNTMGR_MOUNT_POINTS) + TotalLength;
    MountPoints->NumberOfMountPoints = 1;

    if (MountPoints->Size > Stack->Parameters.DeviceIoControl.OutputBufferLength)
    {
        return STATUS_BUFFER_OVERFLOW;
    }

    /* Write out data */
    MountPoints->MountPoints[0].SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS);
    MountPoints->MountPoints[0].SymbolicLinkNameLength = SymlinkInformation->Name.Length;
    /* If link is online write it's unique ID, otherwise, forget about it */
    if (SymlinkInformation->Online)
    {
        MountPoints->MountPoints[0].UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
                                                     SymlinkInformation->Name.Length;
        MountPoints->MountPoints[0].UniqueIdLength = DeviceInformation->UniqueId->UniqueIdLength;
    }
    else
    {
        MountPoints->MountPoints[0].UniqueIdOffset = 0;
        MountPoints->MountPoints[0].UniqueIdLength = 0;
    }

    MountPoints->MountPoints[0].DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINTS) +
                                                   SymlinkInformation->Name.Length +
                                                   DeviceInformation->UniqueId->UniqueIdLength;
    MountPoints->MountPoints[0].DeviceNameLength = DeviceInformation->DeviceName.Length;

    RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].SymbolicLinkNameOffset),
                  SymlinkInformation->Name.Buffer, SymlinkInformation->Name.Length);

    if (SymlinkInformation->Online)
    {
        RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].UniqueIdOffset),
                      DeviceInformation->UniqueId->UniqueId, DeviceInformation->UniqueId->UniqueIdLength);
    }

    RtlCopyMemory((PWSTR)((ULONG_PTR)MountPoints + MountPoints->MountPoints[0].DeviceNameOffset),
                  DeviceInformation->DeviceName.Buffer, DeviceInformation->DeviceName.Length);

    return STATUS_SUCCESS;
}
Пример #20
0
NTSTATUS
DokanDispatchCreate(
	__in PDEVICE_OBJECT DeviceObject,
	__in PIRP Irp
	)

/*++

Routine Description:

	This device control dispatcher handles create & close IRPs.

Arguments:

	DeviceObject - Context for the activity.
	Irp 		 - The device control argument block.

Return Value:

	NTSTATUS

--*/
{
	PDokanVCB			vcb;
	PDokanDCB			dcb;
	PIO_STACK_LOCATION	irpSp;
	NTSTATUS			status = STATUS_INVALID_PARAMETER;
	PFILE_OBJECT		fileObject;
	ULONG				info = 0;
	PEVENT_CONTEXT		eventContext;
	PFILE_OBJECT		relatedFileObject;
	ULONG				fileNameLength = 0;
	ULONG				eventLength;
	PDokanFCB			fcb;
	PDokanCCB			ccb;
	PWCHAR				fileName;
	BOOLEAN				needBackSlashAfterRelatedFile = FALSE;

	PAGED_CODE();

	__try {
		FsRtlEnterFileSystem();

		DDbgPrint("==> DokanCreate\n");

		irpSp = IoGetCurrentIrpStackLocation(Irp);
		fileObject = irpSp->FileObject;
		relatedFileObject = fileObject->RelatedFileObject;

		if (fileObject == NULL) {
			DDbgPrint("  fileObject == NULL\n");
			status = STATUS_INVALID_PARAMETER;
			__leave;
		}

		DDbgPrint("  ProcessId %lu\n", IoGetRequestorProcessId(Irp));
		DDbgPrint("  FileName:%wZ\n", &fileObject->FileName);

		vcb = DeviceObject->DeviceExtension;
		PrintIdType(vcb);
		if (GetIdentifierType(vcb) != VCB) {
            DDbgPrint("  IdentifierType is not vcb\n");
			status = STATUS_SUCCESS;
			__leave;
		}
		dcb = vcb->Dcb;

		DDbgPrint("  IrpSp->Flags = %d\n", irpSp->Flags);
		if (irpSp->Flags & SL_CASE_SENSITIVE) {
			DDbgPrint("  IrpSp->Flags SL_CASE_SENSITIVE\n");
		}
		if (irpSp->Flags & SL_FORCE_ACCESS_CHECK) {
			DDbgPrint("  IrpSp->Flags SL_FORCE_ACCESS_CHECK\n");
		}
		if (irpSp->Flags & SL_OPEN_PAGING_FILE) {
			DDbgPrint("  IrpSp->Flags SL_OPEN_PAGING_FILE\n");
		}
		if (irpSp->Flags & SL_OPEN_TARGET_DIRECTORY) {
			DDbgPrint("  IrpSp->Flags SL_OPEN_TARGET_DIRECTORY\n");
		}

	   if ((fileObject->FileName.Length > sizeof(WCHAR)) &&
			(fileObject->FileName.Buffer[1] == L'\\') &&
			(fileObject->FileName.Buffer[0] == L'\\')) {

			fileObject->FileName.Length -= sizeof(WCHAR);

			RtlMoveMemory(&fileObject->FileName.Buffer[0],
						&fileObject->FileName.Buffer[1],
						fileObject->FileName.Length);
	   }

		if (relatedFileObject != NULL) {
			fileObject->Vpb = relatedFileObject->Vpb;
		} else {
			fileObject->Vpb = dcb->DeviceObject->Vpb;
		}

		if ((relatedFileObject == NULL || relatedFileObject->FileName.Length == 0) &&
			fileObject->FileName.Length == 0) {

			DDbgPrint("   request for FS device\n");

			if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
				status = STATUS_NOT_A_DIRECTORY;
			} else {
				SetFileObjectForVCB(fileObject, vcb);
				info = FILE_OPENED;
				status = STATUS_SUCCESS;
			}
			__leave;
		}

	   if (fileObject->FileName.Length > sizeof(WCHAR) &&
		   fileObject->FileName.Buffer[fileObject->FileName.Length/sizeof(WCHAR)-1] == L'\\') {
			fileObject->FileName.Length -= sizeof(WCHAR);
	   }

   		fileNameLength = fileObject->FileName.Length;
		if (relatedFileObject) {
			fileNameLength += relatedFileObject->FileName.Length;

			if (fileObject->FileName.Length > 0 &&
				fileObject->FileName.Buffer[0] == '\\') {
				DDbgPrint("  when RelatedFileObject is specified, the file name should be relative path\n");
				status = STATUS_OBJECT_NAME_INVALID;
				__leave;
			}
			if (relatedFileObject->FileName.Length > 0 &&
				relatedFileObject->FileName.Buffer[relatedFileObject->FileName.Length/sizeof(WCHAR)-1] != '\\') {
				needBackSlashAfterRelatedFile = TRUE;
				fileNameLength += sizeof(WCHAR);
			}
		}

		// don't open file like stream
		if (!dcb->UseAltStream &&
			DokanUnicodeStringChar(&fileObject->FileName, L':') != -1) {
			DDbgPrint("    alternate stream\n");
			status = STATUS_INVALID_PARAMETER;
			info = 0;
			__leave;
		}
			
		// this memory is freed by DokanGetFCB if needed
		// "+ sizeof(WCHAR)" is for the last NULL character
		fileName = ExAllocatePool(fileNameLength + sizeof(WCHAR));
		if (fileName == NULL) {
            DDbgPrint("    Can't allocatePool for fileName\n");
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		RtlZeroMemory(fileName, fileNameLength + sizeof(WCHAR));

		if (relatedFileObject != NULL) {
			DDbgPrint("  RelatedFileName:%wZ\n", &relatedFileObject->FileName);

			// copy the file name of related file object
			RtlCopyMemory(fileName,
							relatedFileObject->FileName.Buffer,
							relatedFileObject->FileName.Length);

			if (needBackSlashAfterRelatedFile) {
				((PWCHAR)fileName)[relatedFileObject->FileName.Length/sizeof(WCHAR)] = '\\';
			}
			// copy the file name of fileObject
			RtlCopyMemory((PCHAR)fileName +
							relatedFileObject->FileName.Length +
							(needBackSlashAfterRelatedFile? sizeof(WCHAR) : 0),
							fileObject->FileName.Buffer,
							fileObject->FileName.Length);

		} else {
			// if related file object is not specifed, copy the file name of file object
			RtlCopyMemory(fileName,
							fileObject->FileName.Buffer,
							fileObject->FileName.Length);
		}

		fcb = DokanGetFCB(vcb, fileName, fileNameLength);
		if (fcb == NULL) {
            DDbgPrint("    Was not able to get FCB for fileName %s\n", fileName);
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		if (irpSp->Flags & SL_OPEN_PAGING_FILE) {
			fcb->AdvancedFCBHeader.Flags2 |= FSRTL_FLAG2_IS_PAGING_FILE;
			fcb->AdvancedFCBHeader.Flags2 &= ~FSRTL_FLAG2_SUPPORTS_FILTER_CONTEXTS;
		}

		ccb = DokanAllocateCCB(dcb, fcb);
		if (ccb == NULL) {
            DDbgPrint("    Was not able to allocate CCB\n");
			DokanFreeFCB(fcb); // FileName is freed here
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		//remember FILE_DELETE_ON_CLOSE so than the file can be deleted in close for windows 8
		if (irpSp->Parameters.Create.Options & FILE_DELETE_ON_CLOSE) {
			fcb->Flags |= DOKAN_DELETE_ON_CLOSE;
			DDbgPrint("  FILE_DELETE_ON_CLOSE is set so remember for delete in cleanup\n");
		} else {
			fcb->Flags &= ~DOKAN_DELETE_ON_CLOSE;
		}

		fileObject->FsContext = &fcb->AdvancedFCBHeader;
		fileObject->FsContext2 = ccb;
		fileObject->PrivateCacheMap = NULL;
		fileObject->SectionObjectPointer = &fcb->SectionObjectPointers;
		//fileObject->Flags |= FILE_NO_INTERMEDIATE_BUFFERING;

		eventLength = sizeof(EVENT_CONTEXT) + fcb->FileName.Length;
		eventContext = AllocateEventContext(vcb->Dcb, Irp, eventLength, ccb);
				
		if (eventContext == NULL) {
            DDbgPrint("    Was not able to allocate eventContext\n");
			status = STATUS_INSUFFICIENT_RESOURCES;
			__leave;
		}

		eventContext->Context = 0;
		eventContext->FileFlags |= fcb->Flags;

		// copy the file name
		eventContext->Operation.Create.FileNameLength = fcb->FileName.Length;
		RtlCopyMemory(eventContext->Operation.Create.FileName, fcb->FileName.Buffer, fcb->FileName.Length);

		eventContext->Operation.Create.FileAttributes = irpSp->Parameters.Create.FileAttributes;
		eventContext->Operation.Create.CreateOptions = irpSp->Parameters.Create.Options;
		eventContext->Operation.Create.DesiredAccess = irpSp->Parameters.Create.SecurityContext->DesiredAccess;
		eventContext->Operation.Create.ShareAccess = irpSp->Parameters.Create.ShareAccess;

		// register this IRP to waiting IPR list
		status = DokanRegisterPendingIrp(DeviceObject, Irp, eventContext, 0);

	} __finally {

        DokanCompleteIrpRequest(Irp, status, info);

		DDbgPrint("<== DokanCreate\n");
		FsRtlExitFileSystem();
	}

	return status;
}
Пример #21
0
NTSTATUS
SpWmiPassToMiniPort(
    IN     PDEVICE_OBJECT  DeviceObject,
    IN     UCHAR           WmiMinorCode,
    IN OUT PWMI_PARAMETERS WmiParameters
    )
/*++

Routine Description:

   This function pass a WMI request to the miniport driver for processing.
   It creates an SRB which is processed normally by the port driver.  This
   call is synchronous.

   Callers of SpWmiPassToMiniPort must be running at IRQL PASSIVE_LEVEL.

Arguments:

   DeviceObject  - Pointer to the functional or physical device object.

   WmiMinorCode  - WMI action to perform.

   WmiParameters - WMI parameters.

Return Value:

   An NTSTATUS code describing the result of handling the WMI request.
   Complete the IRP with this status.

Notes:

   If this WMI request is completed with STATUS_SUCCESS, the WmiParameters
   BufferSize field will reflect the actual size of the WMI return buffer.

--*/
{
    PCOMMON_EXTENSION commonExtension = DeviceObject->DeviceExtension;
    PADAPTER_EXTENSION fdoExtension;
    SCSI_WMI_REQUEST_BLOCK   srb;
    LARGE_INTEGER            startingOffset;
    PLOGICAL_UNIT_EXTENSION  logicalUnit;

    ULONG                    commonBufferSize;
    PUCHAR                   commonBuffer;
    PHYSICAL_ADDRESS         physicalAddress;
    PVOID                    removeTag = (PVOID)((ULONG_PTR)WmiParameters+3);
    PWNODE_HEADER            wnode;

    NTSTATUS status;

    PAGED_CODE();

    startingOffset.QuadPart = (LONGLONG) 1;

    //
    // Zero out the SRB.
    //
    RtlZeroMemory(&srb, sizeof(SCSI_WMI_REQUEST_BLOCK));

    //
    // Initialize the SRB for a WMI request.
    //
    if (commonExtension->IsPdo) {                                       // [PDO]

        //
        // Set the logical unit addressing from this PDO's device extension.
        //
        logicalUnit = DeviceObject->DeviceExtension;

        SpAcquireRemoveLock(DeviceObject, removeTag);

        srb.PathId      = logicalUnit->PathId;
        srb.TargetId    = logicalUnit->TargetId;
        srb.Lun         = logicalUnit->Lun;

        fdoExtension = logicalUnit->AdapterExtension;

    } else {                                                            // [FDO]

        //
        // Set the logical unit addressing to the first logical unit.  This is
        // merely used for addressing purposes for adapter requests only.
        // NOTE: SpFindSafeLogicalUnit will acquire the remove lock
        //

        logicalUnit = SpFindSafeLogicalUnit(DeviceObject,
                                            0xff,
                                            removeTag);

        if (logicalUnit == NULL) {
            return(STATUS_DEVICE_DOES_NOT_EXIST);
        }

        fdoExtension = DeviceObject->DeviceExtension;

        srb.WMIFlags    = SRB_WMI_FLAGS_ADAPTER_REQUEST;
        srb.PathId      = logicalUnit->PathId;
        srb.TargetId    = logicalUnit->TargetId;
        srb.Lun         = logicalUnit->Lun;
    }

    //
    // HACK - allocate a chunk of common buffer for the actual request to
    // get processed in. We need to determine the size of buffer to allocate
    // this is the larger of the input or output buffers
    //

    if (WmiMinorCode == IRP_MN_EXECUTE_METHOD)
    {
        wnode = (PWNODE_HEADER)WmiParameters->Buffer;
        commonBufferSize = (WmiParameters->BufferSize > wnode->BufferSize) ?
                            WmiParameters->BufferSize :
                            wnode->BufferSize;
    } else {
        commonBufferSize = WmiParameters->BufferSize;
    }
                        
    commonBuffer = HalAllocateCommonBuffer(fdoExtension->DmaAdapterObject,
                                           commonBufferSize,
                                           &physicalAddress,
                                           FALSE);

    if(commonBuffer == NULL) {
        DebugPrint((1, "SpWmiPassToMiniPort: Unable to allocate %#x bytes of "
                       "common buffer\n", commonBufferSize));
        
        SpReleaseRemoveLock(logicalUnit->DeviceObject, removeTag);

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    try {
        KEVENT event;
        PIRP irp;
        PMDL mdl;
        PIO_STACK_LOCATION irpStack;

        RtlCopyMemory(commonBuffer, WmiParameters->Buffer, commonBufferSize);
    
        srb.DataBuffer         = commonBuffer;       // [already non-paged]
        srb.DataTransferLength = WmiParameters->BufferSize;
        srb.Function           = SRB_FUNCTION_WMI;
        srb.Length             = sizeof(SCSI_REQUEST_BLOCK);
        srb.WMISubFunction     = WmiMinorCode;
        srb.DataPath           = WmiParameters->DataPath;
        srb.SrbFlags           = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;
        srb.TimeOutValue       = 10;                                // [ten seconds]
    
        //
        // Note that the value in DataBuffer may be used regardless of the value
        // of the MapBuffers field.
        //
    
        //
        // Initialize the notification event.
        //

        KeInitializeEvent(&event, NotificationEvent, FALSE);
    
        //
        // Build IRP for this request.
        // Note we do this synchronously for two reasons.  If it was done
        // asynchonously then the completion code would have to make a special
        // check to deallocate the buffer.  Second if a completion routine were
        // used then an additional IRP stack location would be needed.
        //

        irp = IoAllocateIrp(logicalUnit->DeviceObject->StackSize, FALSE);

        if(irp == NULL) {
            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
        }

        mdl = IoAllocateMdl(commonBuffer,
                            WmiParameters->BufferSize,
                            FALSE,
                            FALSE,
                            irp);

        if(mdl == NULL) {
            IoFreeIrp(irp);
            status = STATUS_INSUFFICIENT_RESOURCES;
            leave;
        }

        MmBuildMdlForNonPagedPool(mdl);

        srb.OriginalRequest = irp;
    
        irpStack = IoGetNextIrpStackLocation(irp);
    
        //
        // Set major code.
        //
        irpStack->MajorFunction = IRP_MJ_SCSI;
    
        //
        // Set SRB pointer.
        //
        irpStack->Parameters.Scsi.Srb = (PSCSI_REQUEST_BLOCK)&srb;
    
        //
        // Setup a completion routine so we know when the request has completed.
        //

        IoSetCompletionRoutine(irp,
                               SpSignalCompletion,
                               &event,
                               TRUE,
                               TRUE,
                               TRUE);

        //
        // Flush the data buffer for output.  This will insure that the data is
        // written back to memory.  Since the data-in flag is the the port driver
        // will flush the data again for input which will ensure the data is not
        // in the cache.
        //
        KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
    
        //
        // Call port driver to handle this request.
        //
        IoCallDriver(logicalUnit->CommonExtension.DeviceObject, irp);
    
        //
        // Wait for request to complete.
        //
        KeWaitForSingleObject(&event,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
    
        status = irp->IoStatus.Status;

        //
        // Relay the return buffer's size to the caller on success.
        //
        if (NT_SUCCESS(status)) {
            WmiParameters->BufferSize = srb.DataTransferLength;
        }
    
        //
        // Copy back the correct number of bytes into the caller provided buffer.
        //
    
        RtlCopyMemory(WmiParameters->Buffer,
                      commonBuffer,
                      WmiParameters->BufferSize);

        //
        // Free the irp and MDL.
        //

        IoFreeMdl(mdl);
        IoFreeIrp(irp);

    } finally {

        HalFreeCommonBuffer(fdoExtension->DmaAdapterObject,
                            commonBufferSize,
                            physicalAddress,
                            commonBuffer,
                            FALSE);
    
        SpReleaseRemoveLock(logicalUnit->CommonExtension.DeviceObject,
                            removeTag);
    }

    //
    // Return the IRP's status.
    //
    return status;
}
Пример #22
0
/*
* FUNCTION: Retrieve all file information
*/
static NTSTATUS
CdfsGetAllInformation(PFILE_OBJECT FileObject,
                      PFCB Fcb,
                      PFILE_ALL_INFORMATION Info,
                      PULONG BufferLength)
{
    ULONG NameLength;

    ASSERT(Info);
    ASSERT(Fcb);

    NameLength = wcslen(Fcb->PathName) * sizeof(WCHAR);
    if (*BufferLength < sizeof(FILE_ALL_INFORMATION) + NameLength)
        return(STATUS_BUFFER_OVERFLOW);

    /* Basic Information */
    CdfsDateTimeToSystemTime(Fcb,
        &Info->BasicInformation.CreationTime);
    CdfsDateTimeToSystemTime(Fcb,
        &Info->BasicInformation.LastAccessTime);
    CdfsDateTimeToSystemTime(Fcb,
        &Info->BasicInformation.LastWriteTime);
    CdfsDateTimeToSystemTime(Fcb,
        &Info->BasicInformation.ChangeTime);
    CdfsFileFlagsToAttributes(Fcb,
        &Info->BasicInformation.FileAttributes);

    /* Standard Information */
    if (CdfsFCBIsDirectory(Fcb))
    {
        Info->StandardInformation.AllocationSize.QuadPart = 0LL;
        Info->StandardInformation.EndOfFile.QuadPart = 0LL;
        Info->StandardInformation.Directory = TRUE;
    }
    else
    {
        Info->StandardInformation.AllocationSize = Fcb->RFCB.AllocationSize;
        Info->StandardInformation.EndOfFile = Fcb->RFCB.FileSize;
        Info->StandardInformation.Directory = FALSE;
    }
    Info->StandardInformation.NumberOfLinks = 0;
    Info->StandardInformation.DeletePending = FALSE;

    /* Internal Information */
    Info->InternalInformation.IndexNumber.QuadPart = Fcb->IndexNumber.QuadPart;

    /* EA Information */
    Info->EaInformation.EaSize = 0;

    /* Access Information */
    /* The IO-Manager adds this information */

    /* Position Information */
    Info->PositionInformation.CurrentByteOffset.QuadPart = FileObject->CurrentByteOffset.QuadPart;

    /* Mode Information */
    /* The IO-Manager adds this information */

    /* Alignment Information */
    /* The IO-Manager adds this information */

    /* Name Information */
    Info->NameInformation.FileNameLength = NameLength;
    RtlCopyMemory(Info->NameInformation.FileName,
        Fcb->PathName,
        NameLength + sizeof(WCHAR));

    *BufferLength -= (sizeof(FILE_ALL_INFORMATION) + NameLength + sizeof(WCHAR));

    return STATUS_SUCCESS;
}
Пример #23
0
UCHAR
SrbIoctlQueryInfo(
		PMINIPORT_DEVICE_EXTENSION	HwDeviceExtension,
		PMINIPORT_LU_EXTENSION		LuExtension,
		PLSMPIOCTL_QUERYINFO		QueryInfo,
		ULONG						OutputBufferLength,
		PUCHAR						OutputBuffer,
		PNTSTATUS					NtStatus,
		ULONG						CurSrbSequence
) {
	UCHAR				status;
	PCCB				Ccb;
	NTSTATUS			ntStatus;
	KIRQL				oldIrql;

	UNREFERENCED_PARAMETER(LuExtension);

	status = SRB_STATUS_SUCCESS;
	switch(QueryInfo->InfoClass) {
	case LsmpAdapterInformation: {
		PLSMPIOCTL_ADAPTERINFO	adapter = (PLSMPIOCTL_ADAPTERINFO)OutputBuffer;

		KDPrint(1,("LsmpAdapterInformation\n"));

		if(OutputBufferLength < sizeof(LSMPIOCTL_ADAPTERINFO)) {
			KDPrint(1,("Too small output buffer. OutputBufferLength:%d\n", OutputBufferLength));
			*NtStatus = STATUS_BUFFER_TOO_SMALL;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		adapter->Length								= sizeof(LSMPIOCTL_ADAPTERINFO);
		adapter->Adapter.SlotNo						= HwDeviceExtension->SlotNumber;
		adapter->Adapter.Length						= sizeof(LSMP_ADAPTER);
		adapter->Adapter.InitiatorId				= HwDeviceExtension->InitiatorId;
		adapter->Adapter.NumberOfBuses				= HwDeviceExtension->NumberOfBuses;
		adapter->Adapter.MaximumNumberOfTargets		= HwDeviceExtension->MaximumNumberOfTargets;
		adapter->Adapter.MaximumNumberOfLogicalUnits= HwDeviceExtension->MaximumNumberOfLogicalUnits;
		adapter->Adapter.MaxBlocksPerRequest		= HwDeviceExtension->AdapterMaxBlocksPerRequest;

		ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql);
		adapter->Adapter.Status						= HwDeviceExtension->AdapterStatus;
		RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql);

		*NtStatus = STATUS_SUCCESS;
		status = SRB_STATUS_SUCCESS;
		break;
		}
	case LsmpPrimaryUnitDiskInformation: {
		PLSMPIOCTL_PRIMUNITDISKINFO	primUnitDisk = (PLSMPIOCTL_PRIMUNITDISKINFO)OutputBuffer;
		PLUR_QUERY					LurQuery;
		PLURN_PRIMARYINFORMATION	LurPrimaryInfo;
		BYTE						LurBuffer[SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION))];
		ACCESS_MASK					DesiredAccess;

		KDPrint(1,("LsmpPrimaryUnitDiskInformation\n"));

		if(OutputBufferLength < sizeof(LSMPIOCTL_PRIMUNITDISKINFO)) {
			KDPrint(1,("Too small output buffer\n"));
			*NtStatus = STATUS_BUFFER_TOO_SMALL;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		//
		//	Query to the LUR
		//
		ntStatus = LSCcbAllocate(&Ccb);
		if(!NT_SUCCESS(ntStatus)) {
			KDPrint(1,("LSCcbAllocate() failed.\n"));
			*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		LSCCB_INITIALIZE(Ccb, CurSrbSequence);
		Ccb->OperationCode = CCB_OPCODE_QUERY;
		LSCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED);
		Ccb->DataBuffer = LurBuffer;
		Ccb->DataBufferLength = sizeof(LURN_PRIMARYINFORMATION);

		LurQuery = (PLUR_QUERY)LurBuffer;
		LurQuery->InfoClass			= LurPrimaryLurnInformation;
		LurQuery->Length			= SIZE_OF_LURQUERY(0, sizeof(LURN_PRIMARYINFORMATION));
		LurQuery->QueryDataLength	= 0;

		LurPrimaryInfo = (PLURN_PRIMARYINFORMATION)LUR_QUERY_INFORMATION(LurQuery);

		KDPrint(3,("going to default LuExtention 0.\n"));
		if(HwDeviceExtension->LURs[0] == NULL || HwDeviceExtension->LURCount == 0) {
			LSCcbFree(Ccb);

			*NtStatus = STATUS_INVALID_PARAMETER;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		ntStatus = LurRequest(
							HwDeviceExtension->LURs[0],	// default: 0.
							Ccb
						);
		DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess;
		if(!NT_SUCCESS(ntStatus)) {
			LSCcbFree(Ccb);

			KDPrint(1,("LurRequest() failed.\n"));
			*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		//
		//	Set return values.
		//
		primUnitDisk->Length					= sizeof(LSMPIOCTL_PRIMUNITDISKINFO);
		primUnitDisk->UnitDisk.Length			= sizeof(LSMP_UNITDISK);
		//
		//	Adapter information
		//
		primUnitDisk->EnabledTime.QuadPart					=	HwDeviceExtension->EnabledTime.QuadPart;

		primUnitDisk->Adapter.SlotNo						= HwDeviceExtension->SlotNumber;
		primUnitDisk->Adapter.Length						= sizeof(LSMP_ADAPTER);
		primUnitDisk->Adapter.InitiatorId					= HwDeviceExtension->InitiatorId;
		primUnitDisk->Adapter.NumberOfBuses					= HwDeviceExtension->NumberOfBuses;
		primUnitDisk->Adapter.MaximumNumberOfTargets		= HwDeviceExtension->MaximumNumberOfTargets;
		primUnitDisk->Adapter.MaximumNumberOfLogicalUnits	= HwDeviceExtension->MaximumNumberOfLogicalUnits;
		primUnitDisk->Adapter.MaxBlocksPerRequest			= HwDeviceExtension->AdapterMaxBlocksPerRequest;

		ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql);
		primUnitDisk->Adapter.Status						= HwDeviceExtension->AdapterStatus;
		RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql);
		//
		// LUR information ( Scsi LU information )
		//
		primUnitDisk->Lur.Length		= sizeof(LSMP_LUR);
		primUnitDisk->Lur.DevType		= HwDeviceExtension->LURs[0]->DevType;
		primUnitDisk->Lur.TargetId		= HwDeviceExtension->LURs[0]->LurId[1];
		primUnitDisk->Lur.Lun			= HwDeviceExtension->LURs[0]->LurId[2];
		primUnitDisk->Lur.LurnCnt		= HwDeviceExtension->LURs[0]->NodeCount;
		primUnitDisk->Lur.DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess;
		primUnitDisk->Lur.GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess;
		primUnitDisk->Lur.LowestHwVer	= HwDeviceExtension->LURs[0]->LowestHwVer;

		//
		//	Unit device
		//

		primUnitDisk->UnitDisk.UnitDiskId		= LurPrimaryInfo->PrimaryLurn.UnitDiskId;
		primUnitDisk->UnitDisk.DesiredAccess	= DesiredAccess;
		primUnitDisk->UnitDisk.GrantedAccess	= LurPrimaryInfo->PrimaryLurn.AccessRight;
		RtlCopyMemory(
			primUnitDisk->UnitDisk.UserID,
			&LurPrimaryInfo->PrimaryLurn.UserID,
			sizeof(primUnitDisk->UnitDisk.UserID)
			);
		RtlCopyMemory(
			primUnitDisk->UnitDisk.Password,
			&LurPrimaryInfo->PrimaryLurn.Password,
			sizeof(primUnitDisk->UnitDisk.Password)
			);

		RtlCopyMemory(	&primUnitDisk->UnitDisk.NetDiskAddress,
						&LurPrimaryInfo->PrimaryLurn.NetDiskAddress,
						sizeof(TA_LSTRANS_ADDRESS)
			);
		RtlCopyMemory(	&primUnitDisk->UnitDisk.BindingAddress,
						&LurPrimaryInfo->PrimaryLurn.BindingAddress,
						sizeof(TA_LSTRANS_ADDRESS)
			);
		primUnitDisk->UnitDisk.UnitBlocks		= (UINT32)LurPrimaryInfo->PrimaryLurn.UnitBlocks;
		primUnitDisk->UnitDisk.SlotNo			= HwDeviceExtension->SlotNumber;
		break;
		}

	case LsmpAdapterLurInformation: {
		PLSMPIOCTL_ADAPTERLURINFO	info = (PLSMPIOCTL_ADAPTERLURINFO)OutputBuffer;
		PLSMP_LURN_FULL				unitDisk;
		PLUR_QUERY					LurQuery;
		PLURN_ENUM_INFORMATION		LurnEnumInfo;
		UINT32						LurnEnumInfoLen;
		PLURN_INFORMATION			lurnInformation;
		ACCESS_MASK					DesiredAccess;
		ACCESS_MASK					GrantedAccess;
		ULONG						idx_lurn;
		UINT32						returnLength;

		KDPrint(1,("LsmpAdapterLurInformation\n"));

		if(OutputBufferLength < FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks)) {
			KDPrint(1,("PDOSLOTLIST: Buffer size is less than required %d bytes\n", FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks)));
			*NtStatus = STATUS_INVALID_PARAMETER;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		returnLength = FIELD_OFFSET(LSMPIOCTL_ADAPTERLURINFO, UnitDisks);

		//
		//	Adapter information
		//
		info->EnabledTime.QuadPart					=	HwDeviceExtension->EnabledTime.QuadPart;

		info->Adapter.SlotNo						= HwDeviceExtension->SlotNumber;
		info->Adapter.Length						= sizeof(LSMP_ADAPTER);
		info->Adapter.InitiatorId					= HwDeviceExtension->InitiatorId;
		info->Adapter.NumberOfBuses					= HwDeviceExtension->NumberOfBuses;
		info->Adapter.MaximumNumberOfTargets		= HwDeviceExtension->MaximumNumberOfTargets;
		info->Adapter.MaximumNumberOfLogicalUnits	= HwDeviceExtension->MaximumNumberOfLogicalUnits;
		info->Adapter.MaxBlocksPerRequest			= HwDeviceExtension->AdapterMaxBlocksPerRequest;

		ACQUIRE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, &oldIrql);
		info->Adapter.Status						= HwDeviceExtension->AdapterStatus;
		RELEASE_SPIN_LOCK(&HwDeviceExtension->LanscsiAdapterSpinLock, oldIrql);
		//
		// LUR information ( Scsi LU information )
		//
		if(!HwDeviceExtension->LURs[0]) {
			KDPrint(1,("No LUR exists.\n"));
			*NtStatus = STATUS_INVALID_PARAMETER;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}
		info->Lur.Length		= sizeof(LSMP_LUR);
		info->Lur.DevType		= HwDeviceExtension->LURs[0]->DevType;
		info->Lur.TargetId		= HwDeviceExtension->LURs[0]->LurId[1];
		info->Lur.Lun			= HwDeviceExtension->LURs[0]->LurId[2];
		info->Lur.LurnCnt		= HwDeviceExtension->LURs[0]->NodeCount;
		info->Lur.LowestHwVer	= HwDeviceExtension->LURs[0]->LowestHwVer;
		info->UnitDiskCnt		= info->Lur.LurnCnt;

		ASSERT(HwDeviceExtension->LURs[0]->NodeCount >= 1);
		info->Length			=	sizeof(LSMPIOCTL_ADAPTERLURINFO) +
									sizeof(LSMP_LURN_FULL) *
									(HwDeviceExtension->LURs[0]->NodeCount - 1);

		//
		//	Lurn information.
		//	Query to the LUR
		//
		unitDisk = info->UnitDisks;

		//
		//	allocate a CCB
		//
		ntStatus = LSCcbAllocate(&Ccb);
		if(!NT_SUCCESS(ntStatus)) {
			KDPrint(1,("LSCcbAllocate() failed.\n"));
			*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		//
		//	initialize query CCB
		//
		LSCCB_INITIALIZE(Ccb, CurSrbSequence);
		Ccb->OperationCode = CCB_OPCODE_QUERY;
		LSCcbSetFlag(Ccb, CCB_FLAG_SYNCHRONOUS|CCB_FLAG_ALLOCATED);

		ASSERT(info->Lur.LurnCnt >= 1);

		LurnEnumInfoLen = sizeof(LURN_ENUM_INFORMATION) + sizeof(LURN_INFORMATION) * (info->Lur.LurnCnt-1);
		LUR_QUERY_INITIALIZE(LurQuery, LurEnumerateLurn, 0, LurnEnumInfoLen);
		if(!LurQuery) {
			LSCcbFree(Ccb);

			KDPrint(1,("allocating DataBuffer failed.\n"));
			*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		Ccb->DataBuffer = LurQuery;
		Ccb->DataBufferLength = LurQuery->Length;

		LurnEnumInfo = (PLURN_ENUM_INFORMATION)LUR_QUERY_INFORMATION(LurQuery);

		//
		//	send the CCB down
		//
		KDPrint(3,("going to default LuExtention 0.\n"));
		ntStatus = LurRequest(
							HwDeviceExtension->LURs[0],	// default: 0.
							Ccb
						);
		DesiredAccess = HwDeviceExtension->LURs[0]->DesiredAccess;
		GrantedAccess = HwDeviceExtension->LURs[0]->GrantedAccess;
		if(!NT_SUCCESS(ntStatus)) {
			LSCcbFree(Ccb);

			KDPrint(1,("LurRequest() failed.\n"));
			ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL);
			*NtStatus = STATUS_INSUFFICIENT_RESOURCES;
			status = SRB_STATUS_INVALID_REQUEST;
			break;
		}

		info->Lur.DesiredAccess = DesiredAccess;
		info->Lur.GrantedAccess = GrantedAccess;

		//
		//	Set return values for each LURN.
		//
		for(idx_lurn = 0; idx_lurn < info->UnitDiskCnt; idx_lurn++) {

			//
			//	Add one Unitdisk to return bytes and check the user buffer size.
			//
			returnLength += sizeof(LSMP_LURN_FULL);
			if(returnLength > OutputBufferLength) {
				continue;
			}

			unitDisk = info->UnitDisks + idx_lurn;
			lurnInformation = LurnEnumInfo->Lurns + idx_lurn;

			unitDisk->Length = sizeof(LSMP_LURN_FULL);
			unitDisk->UnitDiskId = lurnInformation->UnitDiskId;
			unitDisk->AccessRight = lurnInformation->AccessRight;
			unitDisk->UnitBlocks = lurnInformation->UnitBlocks;
			unitDisk->StatusFlags = lurnInformation->StatusFlags;
			unitDisk->LurnId = lurnInformation->LurnId;
			unitDisk->LurnType = lurnInformation->LurnType;
			unitDisk->StatusFlags = lurnInformation->StatusFlags;

			RtlCopyMemory(
					unitDisk->UserID,
					&lurnInformation->UserID,
					sizeof(unitDisk->UserID)
				);

			RtlCopyMemory(
					unitDisk->Password,
					&lurnInformation->Password,
					sizeof(unitDisk->Password)
				);

			RtlCopyMemory(	&unitDisk->NetDiskAddress,
						&lurnInformation->NetDiskAddress,
						sizeof(TA_LSTRANS_ADDRESS)
					);
			RtlCopyMemory(	&unitDisk->BindingAddress,
						&lurnInformation->BindingAddress,
						sizeof(TA_LSTRANS_ADDRESS)
					);
		}

		if(returnLength > OutputBufferLength) {
			KDPrint(1,("Output buffer too small. outbuffer:%u required:%u\n", OutputBufferLength, returnLength));
			ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL);
			*NtStatus = STATUS_BUFFER_TOO_SMALL;
			status = SRB_STATUS_SUCCESS;
			break;
		}

		ExFreePoolWithTag(LurQuery, LSMP_PTAG_IOCTL);
		*NtStatus = STATUS_SUCCESS;
		status = SRB_STATUS_SUCCESS;
		break;
		}
	//
	//	User application can use this information instead of LANSCSIMINIPORT_IOCTL_GET_VERSION.
	// 
	case 	LsmpDriverVersion:				// 5
		{
			PLSMPIOCTL_DRVVER	version = (PLSMPIOCTL_DRVVER)OutputBuffer;

			version->VersionMajor = VER_FILEMAJORVERSION;
			version->VersionMinor = VER_FILEMINORVERSION;
			version->VersionBuild = VER_FILEBUILD;
			version->VersionPrivate = VER_FILEBUILD_QFE;

			*NtStatus = STATUS_SUCCESS;
			status = SRB_STATUS_SUCCESS;
		break;
		}

	default:
		KDPrint(1,("Invalid Information Class!!\n"));
		*NtStatus = STATUS_INVALID_PARAMETER;
		status = SRB_STATUS_INVALID_REQUEST;
	}

	return status;
}
Пример #24
0
VOID
NTAPI
FatSetFullNameInFcb(PFCB Fcb,
                    PUNICODE_STRING Name)
{
    PUNICODE_STRING ParentName;

    /* Make sure this FCB's name wasn't already set */
    ASSERT(Fcb->FullFileName.Buffer == NULL);

    /* First of all, check exact case name */
    if (Fcb->ExactCaseLongName.Buffer)
    {
        ASSERT(Fcb->ExactCaseLongName.Length != 0);

        /* Use exact case name */
        Name = &Fcb->ExactCaseLongName;
    }

    /* Treat root dir different */
    if (FatNodeType(Fcb->ParentFcb) == FAT_NTC_ROOT_DCB)
    {
        /* Set lengths */
        Fcb->FullFileName.MaximumLength = sizeof(WCHAR) + Name->Length;
        Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;

        /* Allocate a buffer */
        Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
                                                            Fcb->FullFileName.Length,
                                                            TAG_FILENAME);

        /* Prefix with a backslash */
        Fcb->FullFileName.Buffer[0] = L'\\';

        /* Copy the name here */
        RtlCopyMemory(&Fcb->FullFileName.Buffer[1],
                      &Name->Buffer[0],
                       Name->Length );
    }
    else
    {
        ParentName = &Fcb->ParentFcb->FullFileName;

        /* Check if parent's name is set */
        if (!ParentName->Buffer)
            return;

        /* Set lengths */
        Fcb->FullFileName.MaximumLength =
            ParentName->Length + sizeof(WCHAR) + Name->Length;
        Fcb->FullFileName.Length = Fcb->FullFileName.MaximumLength;

        /* Allocate a buffer */
        Fcb->FullFileName.Buffer = FsRtlAllocatePoolWithTag(PagedPool,
                                                            Fcb->FullFileName.Length,
                                                            TAG_FILENAME );

        /* Copy parent's name here */
        RtlCopyMemory(&Fcb->FullFileName.Buffer[0],
                      &ParentName->Buffer[0],
                      ParentName->Length );

        /* Add a backslash */
        Fcb->FullFileName.Buffer[ParentName->Length / sizeof(WCHAR)] = L'\\';

        /* Copy given name here */
        RtlCopyMemory(&Fcb->FullFileName.Buffer[(ParentName->Length / sizeof(WCHAR)) + 1],
                      &Name->Buffer[0],
                      Name->Length );
    }
}
Пример #25
0
NTSTATUS
VIOSerialEvtChildListIdentificationDescriptionDuplicate(
    WDFCHILDLIST DeviceList,
    PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER SourceIdentificationDescription,
    PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER DestinationIdentificationDescription
    )
{
    PVIOSERIAL_PORT src, dst;

    UNREFERENCED_PARAMETER(DeviceList);

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "--> %s\n", __FUNCTION__);

    src = CONTAINING_RECORD(SourceIdentificationDescription,
                            VIOSERIAL_PORT,
                            Header);
    dst = CONTAINING_RECORD(DestinationIdentificationDescription,
                            VIOSERIAL_PORT,
                            Header);

    dst->BusDevice = src->BusDevice;
    dst->Device = src->Device;

    dst->InBuf = src->InBuf;
    dst->InBufLock = src->InBufLock;
    dst->OutVqLock = src->OutVqLock;

    dst->NameString.Length = src->NameString.Length;
    dst->NameString.MaximumLength = src->NameString.MaximumLength;
    if (dst->NameString.Length)
    {
        dst->NameString.Buffer = (PCHAR)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 dst->NameString.MaximumLength,
                                 VIOSERIAL_DRIVER_MEMORY_TAG
                                 );
        if (!dst->NameString.Buffer)
        {
           ASSERT(0);
           return STATUS_INSUFFICIENT_RESOURCES;
        }
        RtlCopyMemory(dst->NameString.Buffer,
                                 src->NameString.Buffer,
                                 dst->NameString.MaximumLength
                                 );
    }
    dst->DeviceId = src->DeviceId;
    dst->PortId = src->PortId;

    dst->OutVqFull = src->OutVqFull;
    dst->HostConnected = src->HostConnected;
    dst->GuestConnected = src->GuestConnected;
    dst->Removed = src->Removed;

    dst->ReadQueue = src->ReadQueue;
    dst->PendingReadRequest = src->PendingReadRequest;
    dst->WriteQueue = src->WriteQueue;
    dst->IoctlQueue = src->IoctlQueue;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__);
    return STATUS_SUCCESS;
}
Пример #26
0
VOID
NTAPI
FatSetFullFileNameInFcb(IN PFAT_IRP_CONTEXT IrpContext,
                        IN PFCB Fcb)
{
    UNICODE_STRING LongName;
    PFCB CurFcb = Fcb;
    PFCB StopFcb;
    PWCHAR TmpBuffer;
    ULONG PathLength = 0;

    /* Do nothing if it's already set */
    if (Fcb->FullFileName.Buffer) return;

    /* Allocate a temporary buffer */
    LongName.Length = 0;
    LongName.MaximumLength = FF_MAX_FILENAME * sizeof(WCHAR);
    LongName.Buffer =
        FsRtlAllocatePoolWithTag(PagedPool,
                                 FF_MAX_FILENAME * sizeof(WCHAR),
                                 TAG_FILENAME);

    /* Go through all parents to calculate needed length */
    while (CurFcb != Fcb->Vcb->RootDcb)
    {
        /* Does current FCB have FullFileName set? */
        if (CurFcb != Fcb &&
            CurFcb->FullFileName.Buffer)
        {
            /* Yes, just use it! */
            PathLength += CurFcb->FullFileName.Length;

            Fcb->FullFileName.Buffer =
                FsRtlAllocatePoolWithTag(PagedPool,
                                         PathLength,
                                         TAG_FILENAME);

            RtlCopyMemory(Fcb->FullFileName.Buffer,
                          CurFcb->FullFileName.Buffer,
                          CurFcb->FullFileName.Length);

            break;
        }

        /* Sum up length of a current item */
        PathLength += CurFcb->FileNameLength + sizeof(WCHAR);

        /* Go to the parent */
        CurFcb = CurFcb->ParentFcb;
    }

    /* Allocate FullFileName if it wasn't already allocated above */
    if (!Fcb->FullFileName.Buffer)
    {
        Fcb->FullFileName.Buffer =
            FsRtlAllocatePoolWithTag(PagedPool,
                                     PathLength,
                                     TAG_FILENAME);
    }

    StopFcb = CurFcb;

    CurFcb = Fcb;
    TmpBuffer =  Fcb->FullFileName.Buffer + PathLength / sizeof(WCHAR);

    /* Set lengths */
    Fcb->FullFileName.Length = PathLength;
    Fcb->FullFileName.MaximumLength = PathLength;

    while (CurFcb != StopFcb)
    {
        /* Get its unicode name */
        FatGetFcbUnicodeName(IrpContext,
                             CurFcb,
                             &LongName);

        /* Copy it */
        TmpBuffer -= LongName.Length / sizeof(WCHAR);
        RtlCopyMemory(TmpBuffer, LongName.Buffer, LongName.Length);

        /* Append with a backslash */
        TmpBuffer -= 1;
        *TmpBuffer = L'\\';

        /* Go to the parent */
        CurFcb = CurFcb->ParentFcb;
    }

    /* Free the temp buffer */
    ExFreePool(LongName.Buffer);
}
Пример #27
0
VOID
VIOSerialPortCreateName(
    IN WDFDEVICE WdfDevice,
    IN PVIOSERIAL_PORT port,
    IN PPORT_BUFFER buf
    )
{
    WDF_OBJECT_ATTRIBUTES attributes;
    WDF_WORKITEM_CONFIG   workitemConfig;
    WDFWORKITEM           hWorkItem;
    PRAWPDO_VIOSERIAL_PORT  pdoData = NULL;
    NTSTATUS              status = STATUS_SUCCESS;
    size_t                length;
    PVIRTIO_CONSOLE_CONTROL cpkt;

    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "--> %s\n", __FUNCTION__);
    cpkt = (PVIRTIO_CONSOLE_CONTROL)((ULONG_PTR)buf->va_buf + buf->offset);
    if (port && !port->NameString.Buffer)
    {
        length = buf->len - buf->offset - sizeof(VIRTIO_CONSOLE_CONTROL);
        port->NameString.Length = (USHORT)( length );
        port->NameString.MaximumLength = port->NameString.Length + 1;
        port->NameString.Buffer = (PCHAR)ExAllocatePoolWithTag(
                                 NonPagedPool,
                                 port->NameString.MaximumLength,
                                 VIOSERIAL_DRIVER_MEMORY_TAG
                                 );
        if (port->NameString.Buffer)
        {
           RtlCopyMemory(  port->NameString.Buffer,
                                 (PVOID)((LONG_PTR)buf->va_buf + buf->offset + sizeof(*cpkt)),
                                 length
                                 );
           port->NameString.Buffer[length] = '\0';
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME name_size = %d %s\n", length, port->NameString.Buffer);
        }
        else
        {
           TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                                 "VIRTIO_CONSOLE_PORT_NAME: Unable to alloc string buffer\n"
                                 );
        }

        WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
        WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&attributes, RAWPDO_VIOSERIAL_PORT);
        attributes.ParentObject = WdfDevice;
        WDF_WORKITEM_CONFIG_INIT(&workitemConfig, VIOSerialPortSymbolicNameWork);

        status = WdfWorkItemCreate( &workitemConfig,
                                 &attributes,
                                 &hWorkItem);

        if (!NT_SUCCESS(status))
        {
           TraceEvents(TRACE_LEVEL_INFORMATION, DBG_DPC, "WdfWorkItemCreate failed with status = 0x%08x\n", status);
           return;
        }

        pdoData = RawPdoSerialPortGetData(hWorkItem);

        pdoData->port = port;

        WdfWorkItemEnqueue(hWorkItem);
    }
    else
    {
        TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "VIRTIO_CONSOLE_PORT_NAME invalid id = %d\n", cpkt->id);
    }
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_CREATE_CLOSE, "<-- %s\n", __FUNCTION__);
}
Пример #28
0
VOID
NTAPI
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
               IN PFCB Fcb)
{
    FF_DIRENT DirEnt;
    FF_ERROR Err;
    POEM_STRING ShortName;
    CHAR ShortNameRaw[13];
    UCHAR EntryBuffer[32];
    UCHAR NumLFNs;
    PUNICODE_STRING UnicodeName;
    OEM_STRING LongNameOem;
    NTSTATUS Status;

    /* Get the dir entry */
    Err = FF_GetEntry(Fcb->Vcb->Ioman,
                      Fcb->FatHandle->DirEntry,
                      Fcb->FatHandle->DirCluster,
                      &DirEnt);

    if (Err != FF_ERR_NONE)
    {
        DPRINT1("Error %d getting dirent of a file\n", Err);
        return;
    }

    /* Read the dirent to fetch the raw short name */
    FF_FetchEntry(Fcb->Vcb->Ioman,
                  Fcb->FatHandle->DirCluster,
                  Fcb->FatHandle->DirEntry,
                  EntryBuffer);
    NumLFNs = (UCHAR)(EntryBuffer[0] & ~0x40);
    RtlCopyMemory(ShortNameRaw, EntryBuffer, 11);

    /* Initialize short name string */
    ShortName = &Fcb->ShortName.Name.Ansi;
    ShortName->Buffer = Fcb->ShortNameBuffer;
    ShortName->Length = 0;
    ShortName->MaximumLength = sizeof(Fcb->ShortNameBuffer);

    /* Convert raw short name to a proper string */
    Fati8dot3ToString(ShortNameRaw, FALSE, ShortName);

    /* Add the short name link */
    FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksAnsi, &Fcb->ShortName);
    Fcb->ShortName.Fcb = Fcb;

    /* Get the long file name (if any) */
    if (NumLFNs > 0)
    {
        /* Prepare the oem string */
        LongNameOem.Buffer = DirEnt.FileName;
        LongNameOem.MaximumLength = FF_MAX_FILENAME;
        LongNameOem.Length = strlen(DirEnt.FileName);

        /* Prepare the unicode string */
        UnicodeName = &Fcb->LongName.Name.String;
        UnicodeName->Length = (LongNameOem.Length + 1) * sizeof(WCHAR);
        UnicodeName->MaximumLength = UnicodeName->Length;
        UnicodeName->Buffer = FsRtlAllocatePool(PagedPool, UnicodeName->Length);

        /* Convert it to unicode */
        Status = RtlOemStringToUnicodeString(UnicodeName, &LongNameOem, FALSE);
        if (!NT_SUCCESS(Status))
        {
            ASSERT(FALSE);
        }

        /* Set its length */
        Fcb->FileNameLength = UnicodeName->Length;

        /* Save case-preserved copy */
        Fcb->ExactCaseLongName.Length = UnicodeName->Length;
        Fcb->ExactCaseLongName.MaximumLength = UnicodeName->Length;
        Fcb->ExactCaseLongName.Buffer =
            FsRtlAllocatePoolWithTag(PagedPool, UnicodeName->Length, TAG_FILENAME);

        RtlCopyMemory(Fcb->ExactCaseLongName.Buffer,
                      UnicodeName->Buffer,
                      UnicodeName->Length);

        /* Perform a trick which is done by MS's FASTFAT driver to monocase
           the filename */
        RtlDowncaseUnicodeString(UnicodeName, UnicodeName, FALSE);
        RtlUpcaseUnicodeString(UnicodeName, UnicodeName, FALSE);

        DPRINT("Converted long name: %wZ\n", UnicodeName);

        /* Add the long unicode name link */
        FatInsertName(IrpContext, &Fcb->ParentFcb->Dcb.SplayLinksUnicode, &Fcb->LongName);
        Fcb->LongName.Fcb = Fcb;

        /* Indicate that this FCB has a unicode long name */
        SetFlag(Fcb->State, FCB_STATE_HAS_UNICODE_NAME);
    }
    else
    {
        /* No LFN, set exact case name to 0 length */
        Fcb->ExactCaseLongName.Length = 0;
        Fcb->ExactCaseLongName.MaximumLength = 0;

        /* Set the length based on the short name */
        Fcb->FileNameLength = RtlOemStringToCountedUnicodeSize(ShortName);
    }

    /* Mark the fact that names were added to splay trees*/
    SetFlag(Fcb->State, FCB_STATE_HAS_NAMES);
}
Пример #29
0
//前面说到为每一个磁盘设备对象生成了一个系统线程,用来处理Irp
VOID
FileDiskThread (
    IN PVOID Context
    )
{
    PDEVICE_OBJECT      device_object;
    PDEVICE_EXTENSION   device_extension;
    PLIST_ENTRY         request;
    PIRP                irp;
    PIO_STACK_LOCATION  io_stack;
    PUCHAR              system_buffer;
    PUCHAR              buffer;

    ASSERT(Context != NULL);

    device_object = (PDEVICE_OBJECT) Context;

    device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension;

    KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);

    for (;;)
    {
        KeWaitForSingleObject(
            &device_extension->request_event,
            Executive,
            KernelMode,
            FALSE,
            NULL
            );

        if (device_extension->terminate_thread)
        {
            PsTerminateSystemThread(STATUS_SUCCESS);
        }

        while (request = ExInterlockedRemoveHeadList(
            &device_extension->list_head,
            &device_extension->list_lock
            ))
        {
            irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry);

            io_stack = IoGetCurrentIrpStackLocation(irp);

            switch (io_stack->MajorFunction)
            {
            case IRP_MJ_READ:
                system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
                if (system_buffer == NULL)
                {
                    irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    irp->IoStatus.Information = 0;
                    break;
                }
                buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length);
                if (buffer == NULL)
                {
                    irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                    irp->IoStatus.Information = 0;
                    break;
                }
                ZwReadFile(
                    device_extension->file_handle,
                    NULL,
                    NULL,
                    NULL,
                    &irp->IoStatus,
                    buffer,
                    io_stack->Parameters.Read.Length,
                    &io_stack->Parameters.Read.ByteOffset,
                    NULL
                    );
                RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length);
                ExFreePool(buffer);
                break;

            case IRP_MJ_WRITE:
                if ((io_stack->Parameters.Write.ByteOffset.QuadPart +
                     io_stack->Parameters.Write.Length) >
                     device_extension->file_size.QuadPart)
                {
                    irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                    irp->IoStatus.Information = 0;
                }
                ZwWriteFile(
                    device_extension->file_handle,
                    NULL,
                    NULL,
                    NULL,
                    &irp->IoStatus,
                    MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority),
                    io_stack->Parameters.Write.Length,
                    &io_stack->Parameters.Write.ByteOffset,
                    NULL
                    );
                break;

            case IRP_MJ_DEVICE_CONTROL:
                switch (io_stack->Parameters.DeviceIoControl.IoControlCode)
                {
                case IOCTL_FILE_DISK_OPEN_FILE:

                    SeImpersonateClient(device_extension->security_client_context, NULL);

                    irp->IoStatus.Status = FileDiskOpenFile(device_object, irp);

                    PsRevertToSelf();

                    break;

                case IOCTL_FILE_DISK_CLOSE_FILE:
                    irp->IoStatus.Status = FileDiskCloseFile(device_object, irp);
                    break;

                default:
                    irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
                }
                break;

            default:
                irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR;
            }

            IoCompleteRequest(
                irp,
                (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ?
                IO_DISK_INCREMENT : IO_NO_INCREMENT)
                );
        }
    }
}
Пример #30
0
NTSTATUS
AFSLoadLibrary( IN ULONG Flags,
                IN UNICODE_STRING *ServicePath)
{
    UNREFERENCED_PARAMETER(Flags);

    NTSTATUS ntStatus = STATUS_SUCCESS;
    AFSDeviceExt       *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension;
    UNICODE_STRING uniLibraryName;
    AFSDeviceExt *pLibDevExt = NULL;
    PFILE_OBJECT pLibraryFileObject = NULL;
    PDEVICE_OBJECT pLibraryDeviceObject = NULL;

    __Enter
    {

        //
        // Wait on the load library event so we don't race with any
        // other requests coming through
        //

        AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "%s Start load library\n",
                      __FUNCTION__));

        ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent,
                                          Executive,
                                          KernelMode,
                                          FALSE,
                                          NULL);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSLoadLibrary Wait for LoadLibraryEvent failure %08lX\n",
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // Check our current state to ensure we currently do not have a library loaded
        //

        if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_VERBOSE,
                          "%s Library already loaded\n",
                          __FUNCTION__));

            try_return( ntStatus = STATUS_DEVICE_NOT_READY);
        }

        pDevExt->Specific.Control.LibraryServicePath.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool,
                                                                                                 ServicePath->Length,
                                                                                                 AFS_GENERIC_MEMORY_25_TAG);

        if( pDevExt->Specific.Control.LibraryServicePath.Buffer == NULL)
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSLoadLibrary AFS_GENERIC_MEMORY_25_TAG allocation error\n"));

            try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES);
        }

        RtlZeroMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer,
                       ServicePath->Length);

        pDevExt->Specific.Control.LibraryServicePath.Length = ServicePath->Length;
        pDevExt->Specific.Control.LibraryServicePath.MaximumLength = pDevExt->Specific.Control.LibraryServicePath.Length;

        RtlCopyMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer,
                       ServicePath->Buffer,
                       pDevExt->Specific.Control.LibraryServicePath.Length);

        //
        // Load the library
        //

        ntStatus = ZwLoadDriver( ServicePath);

        if( !NT_SUCCESS( ntStatus))
        {

            AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "%s Failed to load library Status %08lX\n",
                          __FUNCTION__,
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // Open up the control device and grab teh entry points for the library
        //

        RtlInitUnicodeString( &uniLibraryName,
                              AFS_LIBRARY_CONTROL_DEVICE_NAME);

        ntStatus = IoGetDeviceObjectPointer( &uniLibraryName,
                                             FILE_ALL_ACCESS,
                                             &pLibraryFileObject,
                                             &pLibraryDeviceObject);

        if( !NT_SUCCESS( ntStatus))
        {
            AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                          AFS_TRACE_LEVEL_ERROR,
                          "AFSLoadLibrary IoGetDeviceObjectPointer failure %08lX\n",
                          ntStatus));

            try_return( ntStatus);
        }

        //
        // We have our reference to the library device object. Grab the
        // device extension and setup our callbacks
        //

        pLibDevExt = (AFSDeviceExt *)pLibraryDeviceObject->DeviceExtension;

        //
        // Save off our references
        //

        pDevExt->Specific.Control.LibraryFileObject = pLibraryFileObject;

        pDevExt->Specific.Control.LibraryDeviceObject = pLibraryDeviceObject;

        //
        // Reset the state for our library
        //

        AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock,
                        TRUE);

        SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED);

        ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED);

        AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "%s Completed load library, processing queued requests\n",
                      __FUNCTION__));

        AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock);

        //
        // Process the queued requests
        //

        AFSProcessQueuedResults( FALSE);

try_exit:

        AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING,
                      AFS_TRACE_LEVEL_VERBOSE,
                      "%s Library load complete Status %08lX\n",
                      __FUNCTION__,
                      ntStatus));

        if( !NT_SUCCESS( ntStatus))
        {

            if( pDevExt->Specific.Control.LibraryServicePath.Buffer != NULL)
            {

                ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath);

                ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer);

                pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL;
                pDevExt->Specific.Control.LibraryServicePath.Length = 0;
                pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0;
            }
        }

        KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent,
                    0,
                    FALSE);
    }

    return ntStatus;
}