예제 #1
0
파일: floppy.c 프로젝트: hoangduit/reactos
static VOID NTAPI
QueueThread(PVOID Context)
/*
 * FUNCTION: Thread that manages the queue and dispatches any queued requests
 * ARGUMENTS:
 *     Context: unused
 */
{
    PIRP Irp;
    PIO_STACK_LOCATION Stack;
    PDEVICE_OBJECT DeviceObject;
    PVOID Objects[2];

    PAGED_CODE();
    UNREFERENCED_PARAMETER(Context);

    Objects[0] = &QueueSemaphore;
    Objects[1] = &QueueThreadTerminate;

    for(;;)
    {
        KeWaitForMultipleObjects(2, Objects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);

        if(KeReadStateEvent(&QueueThreadTerminate))
        {
            INFO_(FLOPPY, "QueueThread terminating\n");
            return;
        }

        INFO_(FLOPPY, "QueueThread: servicing an IRP\n");

        Irp = IoCsqRemoveNextIrp(&Csq, 0);

        /* we won't get an irp if it was canceled */
        if(!Irp)
        {
            INFO_(FLOPPY, "QueueThread: IRP queue empty\n");
            continue;
        }

        DeviceObject = (PDEVICE_OBJECT)Irp->Tail.Overlay.DriverContext[0];

        ASSERT(DeviceObject);

        Stack = IoGetCurrentIrpStackLocation(Irp);

        /* Decide what to do with the IRP */
        switch(Stack->MajorFunction)
        {
        case IRP_MJ_READ:
        case IRP_MJ_WRITE:
            ReadWritePassive(DeviceObject->DeviceExtension, Irp);
            break;

        case IRP_MJ_DEVICE_CONTROL:
            DeviceIoctlPassive(DeviceObject->DeviceExtension, Irp);
            break;

        default:
            WARN_(FLOPPY, "QueueThread(): Unrecognized irp: mj: 0x%x\n", Stack->MajorFunction);
            Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
        }
    }
}
예제 #2
0
static VOID NTAPI
i8042PowerWorkItem(
	IN PDEVICE_OBJECT DeviceObject,
	IN PVOID Context)
{
	PI8042_KEYBOARD_EXTENSION DeviceExtension;
	PIRP WaitingIrp;
	NTSTATUS Status;

	DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context;

	UNREFERENCED_PARAMETER(DeviceObject);

	/* See http://blogs.msdn.com/doronh/archive/2006/09/08/746961.aspx */

	/* Register GUID_DEVICE_SYS_BUTTON interface and report capability */
	if (DeviceExtension->NewCaps != DeviceExtension->ReportedCaps)
	{
		WaitingIrp = InterlockedExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL);
		if (WaitingIrp)
		{
			/* Cancel the current power irp, as capability changed */
			WaitingIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
			WaitingIrp->IoStatus.Information = sizeof(ULONG);
			IoCompleteRequest(WaitingIrp, IO_NO_INCREMENT);
		}

		if (DeviceExtension->PowerInterfaceName.MaximumLength == 0)
		{
			/* We have never registred this interface ; do it */
			Status = IoRegisterDeviceInterface(
				DeviceExtension->Common.Pdo,
				&GUID_DEVICE_SYS_BUTTON,
				NULL,
				&DeviceExtension->PowerInterfaceName);
			if (!NT_SUCCESS(Status))
			{
				/* We can't do more yet, ignore the keypress... */
				WARN_(I8042PRT, "IoRegisterDeviceInterface(GUID_DEVICE_SYS_BUTTON) failed with status 0x%08lx\n",
					Status);
				DeviceExtension->PowerInterfaceName.MaximumLength = 0;
				return;
			}
		}
		else
		{
			/* Disable the interface. Once activated again, capabilities would be asked again */
			Status = IoSetDeviceInterfaceState(
				&DeviceExtension->PowerInterfaceName,
				FALSE);
			if (!NT_SUCCESS(Status))
			{
				/* Ignore the key press... */
				WARN_(I8042PRT, "Disabling interface %wZ failed with status 0x%08lx\n",
					&DeviceExtension->PowerInterfaceName, Status);
				return;
			}
		}
		/* Enable the interface. This leads to receving a IOCTL_GET_SYS_BUTTON_CAPS,
		 * so we can report new capability */
		Status = IoSetDeviceInterfaceState(
				&DeviceExtension->PowerInterfaceName,
				TRUE);
		if (!NT_SUCCESS(Status))
		{
			/* Ignore the key press... */
			WARN_(I8042PRT, "Enabling interface %wZ failed with status 0x%08lx\n",
					&DeviceExtension->PowerInterfaceName, Status);
			return;
		}
	}

	/* Directly complete the IOCTL_GET_SYS_BUTTON_EVENT Irp (if any) */
	WaitingIrp = InterlockedExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL);
	if (WaitingIrp)
	{
		PULONG pEvent = (PULONG)WaitingIrp->AssociatedIrp.SystemBuffer;

		WaitingIrp->IoStatus.Status = STATUS_SUCCESS;
		WaitingIrp->IoStatus.Information = sizeof(ULONG);
		*pEvent = InterlockedExchange((PLONG)&DeviceExtension->LastPowerKey, 0);
		IoCompleteRequest(WaitingIrp, IO_NO_INCREMENT);
	}
}
예제 #3
0
/*
 * Runs the keyboard IOCTL_INTERNAL dispatch.
 */
NTSTATUS NTAPI
i8042KbdInternalDeviceControl(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp)
{
	PIO_STACK_LOCATION Stack;
	PI8042_KEYBOARD_EXTENSION DeviceExtension;
	NTSTATUS Status;

	Stack = IoGetCurrentIrpStackLocation(Irp);
	Irp->IoStatus.Information = 0;
	DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension;

	switch (Stack->Parameters.DeviceIoControl.IoControlCode)
	{
		case IOCTL_INTERNAL_KEYBOARD_CONNECT:
		{
			SIZE_T Size;
			PIO_WORKITEM WorkItem = NULL;
			PI8042_HOOK_WORKITEM WorkItemData = NULL;

			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_CONNECT\n");
			if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CONNECT_DATA))
			{
				Status = STATUS_INVALID_PARAMETER;
				goto cleanup;
			}

			DeviceExtension->KeyboardData =
				*((PCONNECT_DATA)Stack->Parameters.DeviceIoControl.Type3InputBuffer);

			/* Send IOCTL_INTERNAL_I8042_HOOK_KEYBOARD to device stack */
			WorkItem = IoAllocateWorkItem(DeviceObject);
			if (!WorkItem)
			{
				WARN_(I8042PRT, "IoAllocateWorkItem() failed\n");
				Status = STATUS_INSUFFICIENT_RESOURCES;
				goto cleanup;
			}
			WorkItemData = ExAllocatePoolWithTag(
				NonPagedPool,
				sizeof(I8042_HOOK_WORKITEM),
				I8042PRT_TAG);
			if (!WorkItemData)
			{
				WARN_(I8042PRT, "ExAllocatePoolWithTag() failed\n");
				Status = STATUS_NO_MEMORY;
				goto cleanup;
			}
			WorkItemData->WorkItem = WorkItem;
			WorkItemData->Irp = Irp;

			/* Initialize extension */
			DeviceExtension->Common.Type = Keyboard;
			Size = DeviceExtension->Common.PortDeviceExtension->Settings.KeyboardDataQueueSize * sizeof(KEYBOARD_INPUT_DATA);
			DeviceExtension->KeyboardBuffer = ExAllocatePoolWithTag(
				NonPagedPool,
				Size,
				I8042PRT_TAG);
			if (!DeviceExtension->KeyboardBuffer)
			{
				WARN_(I8042PRT, "ExAllocatePoolWithTag() failed\n");
				Status = STATUS_NO_MEMORY;
				goto cleanup;
			}
			RtlZeroMemory(DeviceExtension->KeyboardBuffer, Size);
			KeInitializeDpc(
				&DeviceExtension->DpcKeyboard,
				i8042KbdDpcRoutine,
				DeviceExtension);
			DeviceExtension->PowerWorkItem = IoAllocateWorkItem(DeviceObject);
			if (!DeviceExtension->PowerWorkItem)
			{
				WARN_(I8042PRT, "IoAllocateWorkItem() failed\n");
				Status = STATUS_INSUFFICIENT_RESOURCES;
				goto cleanup;
			}
			DeviceExtension->DebugWorkItem = IoAllocateWorkItem(DeviceObject);
			if (!DeviceExtension->DebugWorkItem)
			{
				WARN_(I8042PRT, "IoAllocateWorkItem() failed\n");
				Status = STATUS_INSUFFICIENT_RESOURCES;
				goto cleanup;
			}
			DeviceExtension->Common.PortDeviceExtension->KeyboardExtension = DeviceExtension;
			DeviceExtension->Common.PortDeviceExtension->Flags |= KEYBOARD_CONNECTED;

            i8042InitializeKeyboardAttributes(DeviceExtension);

			IoMarkIrpPending(Irp);
			/* FIXME: DeviceExtension->KeyboardHook.IsrWritePort = ; */
			DeviceExtension->KeyboardHook.QueueKeyboardPacket = i8042KbdQueuePacket;
			DeviceExtension->KeyboardHook.CallContext = DeviceExtension;
			IoQueueWorkItem(WorkItem,
				i8042SendHookWorkItem,
				DelayedWorkQueue,
				WorkItemData);
			Status = STATUS_PENDING;
			break;

cleanup:
			if (DeviceExtension->KeyboardBuffer)
				ExFreePoolWithTag(DeviceExtension->KeyboardBuffer, I8042PRT_TAG);
			if (DeviceExtension->PowerWorkItem)
				IoFreeWorkItem(DeviceExtension->PowerWorkItem);
			if (DeviceExtension->DebugWorkItem)
				IoFreeWorkItem(DeviceExtension->DebugWorkItem);
			if (WorkItem)
				IoFreeWorkItem(WorkItem);
			if (WorkItemData)
				ExFreePoolWithTag(WorkItemData, I8042PRT_TAG);
			break;
		}
		case IOCTL_INTERNAL_KEYBOARD_DISCONNECT:
		{
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_KEYBOARD_DISCONNECT\n");
			/* MSDN says that operation is to implemented.
			 * To implement it, we just have to do:
			 * DeviceExtension->KeyboardData.ClassService = NULL;
			 */
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_INTERNAL_I8042_HOOK_KEYBOARD:
		{
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_INTERNAL_I8042_HOOK_KEYBOARD\n");
			/* Nothing to do here */
			Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
		{
		    PKEYBOARD_ATTRIBUTES KeyboardAttributes;

            /* FIXME: KeyboardAttributes are not initialized anywhere */
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_ATTRIBUTES\n");
			if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KEYBOARD_ATTRIBUTES))
			{
				Status = STATUS_BUFFER_TOO_SMALL;
				break;
			}

            KeyboardAttributes = Irp->AssociatedIrp.SystemBuffer;
            *KeyboardAttributes = DeviceExtension->KeyboardAttributes;

			Irp->IoStatus.Information = sizeof(KEYBOARD_ATTRIBUTES);
			Status = STATUS_SUCCESS;
			break;

			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
		{
			DPRINT1("IOCTL_KEYBOARD_QUERY_TYPEMATIC not implemented\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_KEYBOARD_SET_TYPEMATIC:
		{
			DPRINT1("IOCTL_KEYBOARD_SET_TYPEMATIC not implemented\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
		{
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION\n");

			/* We should check the UnitID, but it's kind of pointless as
			 * all keyboards are supposed to have the same one
			 */
			if (Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION))
			{
				Status = STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				RtlCopyMemory(
					Irp->AssociatedIrp.SystemBuffer,
					&IndicatorTranslation,
					sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION));
				Irp->IoStatus.Information = sizeof(LOCAL_KEYBOARD_INDICATOR_TRANSLATION);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_KEYBOARD_QUERY_INDICATORS:
		{
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_QUERY_INDICATORS\n");

			if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
			{
				Status = STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				RtlCopyMemory(
					Irp->AssociatedIrp.SystemBuffer,
					&DeviceExtension->KeyboardIndicators,
					sizeof(KEYBOARD_INDICATOR_PARAMETERS));
				Irp->IoStatus.Information = sizeof(KEYBOARD_INDICATOR_PARAMETERS);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_KEYBOARD_SET_INDICATORS:
		{
			TRACE_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / IOCTL_KEYBOARD_SET_INDICATORS\n");

			if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KEYBOARD_INDICATOR_PARAMETERS))
			{
				Status = STATUS_BUFFER_TOO_SMALL;
			}
			else
			{
				RtlCopyMemory(
					&DeviceExtension->KeyboardIndicators,
					Irp->AssociatedIrp.SystemBuffer,
					sizeof(KEYBOARD_INDICATOR_PARAMETERS));
				Status = STATUS_PENDING;
				IoMarkIrpPending(Irp);
				IoStartPacket(DeviceObject, Irp, NULL, NULL);
			}
			break;
		}
		default:
		{
			ERR_(I8042PRT, "IRP_MJ_INTERNAL_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
				Stack->Parameters.DeviceIoControl.IoControlCode);
			ASSERT(FALSE);
			return ForwardIrpAndForget(DeviceObject, Irp);
		}
	}

	Irp->IoStatus.Status = Status;
	if (Status != STATUS_PENDING)
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return Status;
}
예제 #4
0
NTSTATUS
IntCreateRegistryPath(
   IN PCUNICODE_STRING DriverRegistryPath,
   OUT PUNICODE_STRING DeviceRegistryPath)
{
   static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
   static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
   static WCHAR ControlSet[] = L"CONTROLSET";
   static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
   static WCHAR Insert2[] = L"\\Device0";
   BOOLEAN Valid;
   UNICODE_STRING AfterControlSet;

   AfterControlSet = *DriverRegistryPath;
   /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */
   Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) &&
            0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem,
            wcslen(RegistryMachineSystem)));
   if (Valid)
   {
      AfterControlSet.Buffer += wcslen(RegistryMachineSystem);
      AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL);

      /* Check if path contains CURRENTCONTROLSET */
      if (AfterControlSet.Length > sizeof(CurrentControlSet) &&
          0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet)))
      {
         AfterControlSet.Buffer += wcslen(CurrentControlSet);
         AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL);
      }
      /* Check if path contains CONTROLSETnum */
      else if (AfterControlSet.Length > sizeof(ControlSet) &&
               0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet)))
      {
         AfterControlSet.Buffer += wcslen(ControlSet);
         AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL);
         while (AfterControlSet.Length > 0 &&
                *AfterControlSet.Buffer >= L'0' &&
                *AfterControlSet.Buffer <= L'9')
         {
            AfterControlSet.Buffer++;
            AfterControlSet.Length -= sizeof(WCHAR);
         }
         Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer);
         AfterControlSet.Buffer++;
         AfterControlSet.Length -= sizeof(WCHAR);
         AfterControlSet.MaximumLength = AfterControlSet.Length;
      }
      else
      {
         Valid = FALSE;
      }
   }

   if (Valid)
   {
      DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2);
      DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool,
         DeviceRegistryPath->MaximumLength,
         TAG_VIDEO_PORT);
      if (DeviceRegistryPath->Buffer != NULL)
      {
         /* Build device path */
         wcsncpy(DeviceRegistryPath->Buffer,
                 DriverRegistryPath->Buffer,
                 AfterControlSet.Buffer - DriverRegistryPath->Buffer);
         DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR);
         RtlAppendUnicodeToString(DeviceRegistryPath, Insert1);
         RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet);
         RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);

         /* Check if registry key exists */
         Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer));

         if (!Valid)
            ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT);
      }
      else
      {
         Valid = FALSE;
      }
   }
   else
   {
      WARN_(VIDEOPRT, "Unparsable registry path %wZ", DriverRegistryPath);
   }

   /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */
   if (!Valid)
   {
      DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2);
      DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(
         NonPagedPool,
         DeviceRegistryPath->MaximumLength,
         TAG_VIDEO_PORT);

      if (!DeviceRegistryPath->Buffer)
         return STATUS_NO_MEMORY;

      RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath);
      RtlAppendUnicodeToString(DeviceRegistryPath, Insert2);
   }

   return STATUS_SUCCESS;
}
예제 #5
0
/***********************************************************************
 *           LoadLibraryExA   (KERNEL32)
 */
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
{
	WINE_MODREF *wm = 0;
	char* listpath[] = { "", "", "/usr/lib/win32", "/usr/local/lib/win32", 0 };
	extern char* def_path;
	char path[512];
	char checked[2000];
        int i = -1;

        checked[0] = 0;
	if(!libname)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return 0;
	}

	wm=MODULE_FindModule(libname);
	if(wm) return wm->module;

//	if(fs_installed==0)
//	    install_fs();

	while (wm == 0 && listpath[++i])
	{
	    if (i < 2)
	    {
		if (i == 0)
		    /* check just original file name */
		    strncpy(path, libname, 511);
                else
		    /* check default user path */
		    strncpy(path, def_path, 300);
	    }
	    else if (strcmp(def_path, listpath[i]))
                /* path from the list */
		strncpy(path, listpath[i], 300);
	    else
		continue;

	    if (i > 0)
	    {
		strcat(path, "/");
		strncat(path, libname, 100);
	    }
	    path[511] = 0;
	    wm = MODULE_LoadLibraryExA( path, hfile, flags );

	    if (!wm)
	    {
		if (checked[0])
		    strcat(checked, ", ");
		strcat(checked, path);
                checked[1500] = 0;

	    }
	}
	if ( wm )
	{
		if ( !MODULE_DllProcessAttach( wm, NULL ) )
		{
			WARN_(module)("Attach failed for module '%s', \n", libname);
			MODULE_FreeLibrary(wm);
			SetLastError(ERROR_DLL_INIT_FAILED);
			MODULE_RemoveFromList(wm);
			wm = NULL;
		}
	}

	if (!wm && !strstr(checked, "avisynth.dll"))
	    printf("Win32 LoadLibrary failed to load: %s\n", checked);

#define RVA(x) ((char *)wm->module+(unsigned int)(x))

	if (strstr(libname,"vp31vfw.dll") && wm)
	{
	    int i;

	  // sse hack moved from patch dll into runtime patching
          if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(FARPROC)RVA(0x1000)) {
	    fprintf(stderr, "VP3 DLL found\n");
	    for (i=0;i<18;i++) RVA(0x4bd6)[i]=0x90;
	  }
	}

        // remove a few divs in the VP codecs that make trouble
        if (strstr(libname,"vp5vfw.dll") && wm)
        {
          int i;
          if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(FARPROC)RVA(0x3930)) {
            for (i=0;i<3;i++) RVA(0x4e86)[i]=0x90;
            for (i=0;i<3;i++) RVA(0x5a23)[i]=0x90;
            for (i=0;i<3;i++) RVA(0x5bff)[i]=0x90;
          } else {
            fprintf(stderr, "Unsupported VP5 version\n");
            return 0;
          }
        }

        if (strstr(libname,"vp6vfw.dll") && wm)
        {
          int i;
          if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(FARPROC)RVA(0x3ef0)) {
            // looks like VP 6.1.0.2
            for (i=0;i<6;i++) RVA(0x7268)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x7e83)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x806a)[i]=0x90;
          } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(FARPROC)RVA(0x4120)) {
            // looks like VP 6.2.0.10
            for (i=0;i<6;i++) RVA(0x7688)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x82c3)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x84aa)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x1d2cc)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x2179d)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x1977f)[i]=0x90;
          } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(FARPROC)RVA(0x3e70)) {
            // looks like VP 6.0.7.3
            for (i=0;i<6;i++) RVA(0x7559)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x81c3)[i]=0x90;
            for (i=0;i<6;i++) RVA(0x839e)[i]=0x90;
          } else {
            fprintf(stderr, "Unsupported VP6 version\n");
            return 0;
          }
        }

        // Windows Media Video 9 Advanced
        if (strstr(libname,"wmvadvd.dll") && wm)
        {
          // The codec calls IsRectEmpty with coords 0,0,0,0 => result is 0
          // but it really wants the rectangle to be not empty
          if (PE_FindExportedFunction(wm, "CreateInstance", TRUE)==(FARPROC)RVA(0xb812)) {
            // Dll version is 10.0.0.3645
            *RVA(0x8b0f)=0xeb; // Jump always, ignoring IsRectEmpty result
          } else {
            fprintf(stderr, "Unsupported WMVA version\n");
            return 0;
          }
        }

	if (strstr(libname,"QuickTime.qts") && wm)
	{
	    void** ptr;
	    void *dispatch_addr;
	    int i;

//	    dispatch_addr = GetProcAddress(wm->module, "theQuickTimeDispatcher", TRUE);
	    dispatch_addr = PE_FindExportedFunction(wm, "theQuickTimeDispatcher", TRUE);
	    if (dispatch_addr == RVA(0x124c30))
	    {
	        fprintf(stderr, "QuickTime5 DLLs found\n");
		ptr = (void **)RVA(0x375ca4); // dispatch_ptr
	        for (i=0;i<5;i++)  RVA(0x19e842)[i]=0x90; // make_new_region ?
	        for (i=0;i<28;i++) RVA(0x19e86d)[i]=0x90; // call__call_CreateCompatibleDC ?
		for (i=0;i<5;i++)  RVA(0x19e898)[i]=0x90; // jmp_to_call_loadbitmap ?
	        for (i=0;i<9;i++)  RVA(0x19e8ac)[i]=0x90; // call__calls_OLE_shit ?
	        for (i=0;i<106;i++) RVA(0x261b10)[i]=0x90; // disable threads
#if 0
		/* CreateThread callers */
		for (i=0;i<5;i++) RVA(0x1487c5)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x14b275)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x1a24b1)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x1afc5a)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x2f799c)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x2f7efe)[i]=0x90;
		for (i=0;i<5;i++) RVA(0x2fa33e)[i]=0x90;
#endif

#if 0
		/* TerminateQTML fix */
		for (i=0;i<47;i++) RVA(0x2fa3b8)[i]=0x90; // terminate thread
		for (i=0;i<47;i++) RVA(0x2f7f78)[i]=0x90; // terminate thread
		for (i=0;i<77;i++) RVA(0x1a13d5)[i]=0x90;
		RVA(0x08e0ae)[0] = 0xc3; // font/dc remover
		for (i=0;i<24;i++) RVA(0x07a1ad)[i]=0x90; // destroy window
#endif
	    } else if (dispatch_addr == RVA(0x13b330))
	    {
    		fprintf(stderr, "QuickTime6 DLLs found\n");
		ptr = (void **)RVA(0x3b9524); // dispatcher_ptr
		for (i=0;i<5;i++)  RVA(0x2730cc)[i]=0x90; // make_new_region
		for (i=0;i<28;i++) RVA(0x2730f7)[i]=0x90; // call__call_CreateCompatibleDC
		for (i=0;i<5;i++)  RVA(0x273122)[i]=0x90; // jmp_to_call_loadbitmap
		for (i=0;i<9;i++)  RVA(0x273131)[i]=0x90; // call__calls_OLE_shit
		for (i=0;i<96;i++) RVA(0x2ac852)[i]=0x90; // disable threads
	    } else if (dispatch_addr == RVA(0x13c3e0))
	    {
    		fprintf(stderr, "QuickTime6.3 DLLs found\n");
		ptr = (void **)RVA(0x3ca01c); // dispatcher_ptr
		for (i=0;i<5;i++)  RVA(0x268f6c)[i]=0x90; // make_new_region
		for (i=0;i<28;i++) RVA(0x268f97)[i]=0x90; // call__call_CreateCompatibleDC
		for (i=0;i<5;i++)  RVA(0x268fc2)[i]=0x90; // jmp_to_call_loadbitmap
		for (i=0;i<9;i++)  RVA(0x268fd1)[i]=0x90; // call__calls_OLE_shit
		for (i=0;i<96;i++) RVA(0x2b4722)[i]=0x90; // disable threads
	    } else
	    {
	        fprintf(stderr, "Unsupported QuickTime version (%p)\n",
		    dispatch_addr);
		return 0;
	    }

	    fprintf(stderr,"QuickTime.qts patched!!! old entry=%p\n",ptr[0]);

#ifdef EMU_QTX_API
	    report_entry = report_func;
	    report_ret   = report_func_ret;
	    wrapper_target=ptr[0];
	    ptr[0]=wrapper;
#endif
	}
#undef RVA

	return wm ? wm->module : 0;
}
예제 #6
0
파일: mouclass.c 프로젝트: Moteesh/reactos
static NTSTATUS
ReadRegistryEntries(
	IN PUNICODE_STRING RegistryPath,
	IN PCLASS_DRIVER_EXTENSION DriverExtension)
{
	UNICODE_STRING ParametersRegistryKey;
	RTL_QUERY_REGISTRY_TABLE Parameters[4];
	NTSTATUS Status;

	ULONG DefaultConnectMultiplePorts = 1;
	ULONG DefaultDataQueueSize = 0x64;
	PCWSTR DefaultDeviceBaseName = L"PointerClass";

	ParametersRegistryKey.Length = 0;
	ParametersRegistryKey.MaximumLength = RegistryPath->Length + sizeof(L"\\Parameters") + sizeof(UNICODE_NULL);
	ParametersRegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool, ParametersRegistryKey.MaximumLength, CLASS_TAG);
	if (!ParametersRegistryKey.Buffer)
	{
		WARN_(CLASS_NAME, "ExAllocatePoolWithTag() failed\n");
		return STATUS_NO_MEMORY;
	}
	RtlCopyUnicodeString(&ParametersRegistryKey, RegistryPath);
	RtlAppendUnicodeToString(&ParametersRegistryKey, L"\\Parameters");
	ParametersRegistryKey.Buffer[ParametersRegistryKey.Length / sizeof(WCHAR)] = UNICODE_NULL;

	RtlZeroMemory(Parameters, sizeof(Parameters));

	Parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[0].Name = L"ConnectMultiplePorts";
	Parameters[0].EntryContext = &DriverExtension->ConnectMultiplePorts;
	Parameters[0].DefaultType = REG_DWORD;
	Parameters[0].DefaultData = &DefaultConnectMultiplePorts;
	Parameters[0].DefaultLength = sizeof(ULONG);

	Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[1].Name = L"MouseDataQueueSize";
	Parameters[1].EntryContext = &DriverExtension->DataQueueSize;
	Parameters[1].DefaultType = REG_DWORD;
	Parameters[1].DefaultData = &DefaultDataQueueSize;
	Parameters[1].DefaultLength = sizeof(ULONG);

	Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[2].Name = L"PointerDeviceBaseName";
	Parameters[2].EntryContext = &DriverExtension->DeviceBaseName;
	Parameters[2].DefaultType = REG_SZ;
	Parameters[2].DefaultData = (PVOID)DefaultDeviceBaseName;
	Parameters[2].DefaultLength = 0;

	Status = RtlQueryRegistryValues(
		RTL_REGISTRY_ABSOLUTE,
		ParametersRegistryKey.Buffer,
		Parameters,
		NULL,
		NULL);

	if (NT_SUCCESS(Status))
	{
		/* Check values */
		if (DriverExtension->ConnectMultiplePorts != 0
			&& DriverExtension->ConnectMultiplePorts != 1)
		{
			DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
		}
		if (DriverExtension->DataQueueSize == 0)
		{
			DriverExtension->DataQueueSize = DefaultDataQueueSize;
		}
	}
	else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
	{
		/* Registry path doesn't exist. Set defaults */
		DriverExtension->ConnectMultiplePorts = DefaultConnectMultiplePorts;
		DriverExtension->DataQueueSize = DefaultDataQueueSize;
		if (RtlCreateUnicodeString(&DriverExtension->DeviceBaseName, DefaultDeviceBaseName))
			Status = STATUS_SUCCESS;
		else
			Status = STATUS_NO_MEMORY;
	}

	ExFreePoolWithTag(ParametersRegistryKey.Buffer, CLASS_TAG);
	return Status;
}
예제 #7
0
파일: ne_segment.c 프로젝트: AlexSteel/wine
/***********************************************************************
 *           apply_relocations
 *
 * Apply relocations to a segment. Helper for NE_LoadSegment.
 */
static inline BOOL apply_relocations( NE_MODULE *pModule, const struct relocation_entry_s *rep,
                                      int count, int segnum )
{
    BYTE *func_name;
    char buffer[256];
    int i, ordinal;
    WORD offset, *sp;
    HMODULE16 module;
    FARPROC16 address = 0;
    HMODULE16 *pModuleTable = (HMODULE16 *)((char *)pModule + pModule->ne_modtab);
    SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
    SEGTABLEENTRY *pSeg = pSegTable + segnum - 1;

    /*
     * Go through the relocation table one entry at a time.
     */
    for (i = 0; i < count; i++, rep++)
    {
        /*
         * Get the target address corresponding to this entry.
         */

        /* If additive, there is no target chain list. Instead, add source
           and target */
        int additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
        switch (rep->relocation_type & 3)
        {
        case NE_RELTYPE_ORDINAL:
            module = pModuleTable[rep->target1-1];
            ordinal = rep->target2;
            address = NE_GetEntryPoint( module, ordinal );
            if (!address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                if (!pTarget)
                    WARN_(module)("Module not found: %04x, reference %d of module %*.*s\n",
                             module, rep->target1,
                             *((BYTE *)pModule + pModule->ne_restab),
                             *((BYTE *)pModule + pModule->ne_restab),
                             (char *)pModule + pModule->ne_restab + 1 );
                else
                {
                    ERR("No implementation for %.*s.%d, setting to 0xdeadbeef\n",
                            *((BYTE *)pTarget + pTarget->ne_restab),
                            (char *)pTarget + pTarget->ne_restab + 1,
                            ordinal );
                    address = (FARPROC16)0xdeadbeef;
                }
            }
            if (TRACE_ON(fixup))
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE("%d: %.*s.%d=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->ne_restab),
                       (char *)pTarget + pTarget->ne_restab + 1,
                       ordinal, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
            break;

        case NE_RELTYPE_NAME:
            module = pModuleTable[rep->target1-1];
            func_name = (BYTE *)pModule + pModule->ne_imptab + rep->target2;
            memcpy( buffer, func_name+1, *func_name );
            buffer[*func_name] = '\0';
            ordinal = NE_GetOrdinal( module, buffer );
            address = NE_GetEntryPoint( module, ordinal );

            if (ERR_ON(fixup) && !address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                ERR("No implementation for %.*s.%s, setting to 0xdeadbeef\n",
                    *((BYTE *)pTarget + pTarget->ne_restab),
                    (char *)pTarget + pTarget->ne_restab + 1, buffer );
            }
            if (!address) address = (FARPROC16) 0xdeadbeef;
            if (TRACE_ON(fixup))
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE("%d: %.*s.%s=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->ne_restab),
                       (char *)pTarget + pTarget->ne_restab + 1,
                       buffer, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
            break;

        case NE_RELTYPE_INTERNAL:
            if ((rep->target1 & 0xff) == 0xff)
            {
                address  = NE_GetEntryPoint( pModule->self, rep->target2 );
            }
            else
            {
                address = (FARPROC16)MAKESEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 );
            }

            TRACE("%d: %04x:%04x %s\n",
                  i + 1, HIWORD(address), LOWORD(address),
                  NE_GetRelocAddrName( rep->address_type, additive ) );
            break;

        case NE_RELTYPE_OSFIXUP:
            /* Relocation type 7:
             *
             *    These appear to be used as fixups for the Windows
             * floating point emulator.  Let's just ignore them and
             * try to use the hardware floating point.  Linux should
             * successfully emulate the coprocessor if it doesn't
             * exist.
             */
            TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                  i + 1, rep->relocation_type, rep->offset,
                  rep->target1, rep->target2,
                  NE_GetRelocAddrName( rep->address_type, additive ) );
            continue;
        }

        offset  = rep->offset;

        /* Apparently, high bit of address_type is sometimes set; */
        /* we ignore it for now */
        if (rep->address_type > NE_RADDR_OFFSET32)
        {
            char module[10];
            GetModuleName16( pModule->self, module, sizeof(module) );
            ERR("WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
                 module, rep->address_type );
        }

        if (additive)
        {
            sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
            TRACE("    %04x:%04x\n", offset, *sp );
            switch (rep->address_type & 0x7f)
            {
            case NE_RADDR_LOWBYTE:
                *(BYTE *)sp += LOBYTE((int)address);
                break;
            case NE_RADDR_OFFSET16:
                *sp += LOWORD(address);
                break;
            case NE_RADDR_POINTER32:
                *sp += LOWORD(address);
                *(sp+1) = HIWORD(address);
                break;
            case NE_RADDR_SELECTOR:
                /* Borland creates additive records with offset zero. Strange, but OK */
                if (*sp)
                    ERR("Additive selector to %04x.Please report\n",*sp);
                else
                    *sp = HIWORD(address);
                break;
            default:
                goto unknown;
            }
        }
        else  /* non-additive fixup */
        {
            do
            {
                WORD next_offset;

                sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
                next_offset = *sp;
                TRACE("    %04x:%04x\n", offset, *sp );
                switch (rep->address_type & 0x7f)
                {
                case NE_RADDR_LOWBYTE:
                    *(BYTE *)sp = LOBYTE((int)address);
                    break;
                case NE_RADDR_OFFSET16:
                    *sp = LOWORD(address);
                    break;
                case NE_RADDR_POINTER32:
                    *(FARPROC16 *)sp = address;
                    break;
                case NE_RADDR_SELECTOR:
                    *sp = SELECTOROF(address);
                    break;
                default:
                    goto unknown;
                }
                if (next_offset == offset) break;  /* avoid infinite loop */
                if (next_offset >= GlobalSize16(pSeg->hSeg)) break;
                offset = next_offset;
            } while (offset != 0xffff);
        }
    }
    return TRUE;

unknown:
    WARN("WARNING: %d: unknown ADDR TYPE %d,  "
         "TYPE %d,  OFFSET %04x,  TARGET %04x %04x\n",
         i + 1, rep->address_type, rep->relocation_type,
         rep->offset, rep->target1, rep->target2);
    return FALSE;
}
예제 #8
0
파일: floppy.c 프로젝트: hoangduit/reactos
static BOOLEAN NTAPI
AddControllers(PDRIVER_OBJECT DriverObject)
/*
 * FUNCTION: Called on initialization to find our controllers and build device and controller objects for them
 * ARGUMENTS:
 *     DriverObject: Our driver's DriverObject (so we can create devices against it)
 * RETURNS:
 *     FALSE if we can't allocate a device, adapter, or interrupt object, or if we fail to find any controllers
 *     TRUE otherwise (i.e. we have at least one fully-configured controller)
 * NOTES:
 *     - Currently we only support ISA buses.
 *     - BUG: Windows 2000 seems to clobber the response from the IoQueryDeviceDescription callback, so now we
 *       just test a boolean value in the first object to see if it was completely populated.  The same value
 *       is tested for each controller before we build device objects for it.
 * TODO:
 *     - Report resource usage to the HAL
 */
{
    INTERFACE_TYPE InterfaceType = Isa;
    CONFIGURATION_TYPE ControllerType = DiskController;
    CONFIGURATION_TYPE PeripheralType = FloppyDiskPeripheral;
    KAFFINITY Affinity;
    DEVICE_DESCRIPTION DeviceDescription;
    UCHAR i;
    UCHAR j;

    PAGED_CODE();

    /* Find our controllers on all ISA buses */
    IoQueryDeviceDescription(&InterfaceType, 0, &ControllerType, 0, &PeripheralType, 0, ConfigCallback, 0);

    /*
     * w2k breaks the return val from ConfigCallback, so we have to hack around it, rather than just
     * looking for a return value from ConfigCallback.  We expect at least one controller.
     */
    if(!gControllerInfo[0].Populated)
    {
        WARN_(FLOPPY, "AddControllers: failed to get controller info from registry\n");
        return FALSE;
    }

    /* Now that we have a controller, set it up with the system */
    for(i = 0; i < gNumberOfControllers && gControllerInfo[i].NumberOfDrives > 0; i++)
    {
        /* 0: Report resource usage to the kernel, to make sure they aren't assigned to anyone else */
        /* FIXME: Implement me. */

        /* 1: Set up interrupt */
        gControllerInfo[i].MappedVector = HalGetInterruptVector(gControllerInfo[i].InterfaceType, gControllerInfo[i].BusNumber,
                                          gControllerInfo[i].Level, gControllerInfo[i].Vector,
                                          &gControllerInfo[i].MappedLevel, &Affinity);

        /* Must set up the DPC before we connect the interrupt */
        KeInitializeDpc(&gControllerInfo[i].Dpc, DpcForIsr, &gControllerInfo[i]);

        INFO_(FLOPPY, "Connecting interrupt %d to controller%d (object 0x%p)\n", gControllerInfo[i].MappedVector,
              i, &gControllerInfo[i]);

        /* NOTE: We cannot share our interrupt, even on level-triggered buses.  See Isr() for details. */
        if(IoConnectInterrupt(&gControllerInfo[i].InterruptObject, Isr, &gControllerInfo[i], 0, gControllerInfo[i].MappedVector,
                              gControllerInfo[i].MappedLevel, gControllerInfo[i].MappedLevel, gControllerInfo[i].InterruptMode,
                              FALSE, Affinity, 0) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers: unable to connect interrupt\n");
            continue;
        }

        /* 2: Set up DMA */
        memset(&DeviceDescription, 0, sizeof(DeviceDescription));
        DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
        DeviceDescription.DmaChannel = gControllerInfo[i].Dma;
        DeviceDescription.InterfaceType = gControllerInfo[i].InterfaceType;
        DeviceDescription.BusNumber = gControllerInfo[i].BusNumber;
        DeviceDescription.MaximumLength = 2*18*512; /* based on a 1.44MB floppy */

        /* DMA 0,1,2,3 are 8-bit; 4,5,6,7 are 16-bit (4 is chain i think) */
        DeviceDescription.DmaWidth = gControllerInfo[i].Dma > 3 ? Width16Bits: Width8Bits;

        gControllerInfo[i].AdapterObject = HalGetAdapter(&DeviceDescription, &gControllerInfo[i].MapRegisters);

        if(!gControllerInfo[i].AdapterObject)
        {
            WARN_(FLOPPY, "AddControllers: unable to allocate an adapter object\n");
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2b: Initialize the new controller */
        if(InitController(&gControllerInfo[i]) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "AddControllers(): Unable to set up controller %d - initialization failed\n", i);
            IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
            continue;
        }

        /* 2c: Set the controller's initlized flag so we know to release stuff in Unload */
        gControllerInfo[i].Initialized = TRUE;

        /* 3: per-drive setup */
        for(j = 0; j < gControllerInfo[i].NumberOfDrives; j++)
        {
            WCHAR DeviceNameBuf[MAX_DEVICE_NAME];
            UNICODE_STRING DeviceName;
            UNICODE_STRING LinkName;
            UNICODE_STRING ArcPath;
            UCHAR DriveNumber;

            INFO_(FLOPPY, "AddControllers(): Configuring drive %d on controller %d\n", i, j);

            /*
             * 3a: create a device object for the drive
             * Controllers and drives are 0-based, so the combos are:
             * 0: 0,0
             * 1: 0,1
             * 2: 0,2
             * 3: 0,3
             * 4: 1,0
             * 5: 1,1
             * ...
             * 14: 3,2
             * 15: 3,3
             */

            DriveNumber = (UCHAR)(i*4 + j); /* loss of precision is OK; there are only 16 of 'em */

            RtlZeroMemory(&DeviceNameBuf, MAX_DEVICE_NAME * sizeof(WCHAR));
            swprintf(DeviceNameBuf, L"\\Device\\Floppy%d", DriveNumber);
            RtlInitUnicodeString(&DeviceName, DeviceNameBuf);

            if(IoCreateDevice(DriverObject, sizeof(PVOID), &DeviceName,
                              FILE_DEVICE_DISK, FILE_REMOVABLE_MEDIA | FILE_FLOPPY_DISKETTE, FALSE,
                              &gControllerInfo[i].DriveInfo[j].DeviceObject) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: unable to register a Device object\n");
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                continue; /* continue on to next drive */
            }

            INFO_(FLOPPY, "AddControllers: New device: %S (0x%p)\n", DeviceNameBuf, gControllerInfo[i].DriveInfo[j].DeviceObject);

            /* 3b.5: Create an ARC path in case we're booting from this drive */
            swprintf(gControllerInfo[i].DriveInfo[j].ArcPathBuffer,
                     L"\\ArcName\\multi(%d)disk(%d)fdisk(%d)", gControllerInfo[i].BusNumber, i, DriveNumber);

            RtlInitUnicodeString(&ArcPath, gControllerInfo[i].DriveInfo[j].ArcPathBuffer);
            IoAssignArcName(&ArcPath, &DeviceName);

            /* 3c: Set flags up */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags |= DO_DIRECT_IO;

            /* 3d: Create a symlink */
            swprintf(gControllerInfo[i].DriveInfo[j].SymLinkBuffer, L"\\DosDevices\\%c:", DriveNumber + 'A');
            RtlInitUnicodeString(&LinkName, gControllerInfo[i].DriveInfo[j].SymLinkBuffer);
            if(IoCreateSymbolicLink(&LinkName, &DeviceName) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "AddControllers: Unable to create a symlink for drive %d\n", DriveNumber);
                IoDisconnectInterrupt(gControllerInfo[i].InterruptObject);
                IoDeassignArcName(&ArcPath);
                continue; /* continue to next drive */
            }

            /* 3e: Increase global floppy drives count */
            IoGetConfigurationInformation()->FloppyCount++;

            /* 3f: Set up the DPC */
            IoInitializeDpcRequest(gControllerInfo[i].DriveInfo[j].DeviceObject, (PIO_DPC_ROUTINE)DpcForIsr);

            /* 3g: Point the device extension at our DriveInfo struct */
            gControllerInfo[i].DriveInfo[j].DeviceObject->DeviceExtension = &gControllerInfo[i].DriveInfo[j];

            /* 3h: neat comic strip */

            /* 3i: set the initial media type to unknown */
            memset(&gControllerInfo[i].DriveInfo[j].DiskGeometry, 0, sizeof(DISK_GEOMETRY));
            gControllerInfo[i].DriveInfo[j].DiskGeometry.MediaType = Unknown;

            /* 3j: Now that we're done, set the Initialized flag so we know to free this in Unload */
            gControllerInfo[i].DriveInfo[j].Initialized = TRUE;

            /* 3k: Clear the DO_DEVICE_INITIALIZING flag */
            gControllerInfo[i].DriveInfo[j].DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
        }
    }

    INFO_(FLOPPY, "AddControllers: --------------------------------------------> finished adding controllers\n");

    return (IoGetConfigurationInformation()->FloppyCount != 0);
}
예제 #9
0
static NTSTATUS NTAPI
ClassDeviceControl(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp)
{
	//PCLASS_DEVICE_EXTENSION DeviceExtension;
	NTSTATUS Status = STATUS_NOT_SUPPORTED;

	TRACE_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL\n");

	if (!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO)
		return ForwardIrpAndForget(DeviceObject, Irp);

	//DeviceExtension = (PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

	switch (IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode)
	{
		case IOCTL_KEYBOARD_QUERY_ATTRIBUTES:
		case IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION:
		case IOCTL_KEYBOARD_QUERY_INDICATORS:
		case IOCTL_KEYBOARD_QUERY_TYPEMATIC:
		{
			/* FIXME: We hope that all devices will return the same result.
			 * Ask only the first one */
			PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
			if (Head->Flink != Head)
			{
				/* We have at least one device */
				PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Head->Flink, PORT_DEVICE_EXTENSION, ListEntry);
				IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
				IoSkipCurrentIrpStackLocation(Irp);
				return IoCallDriver(DevExt->DeviceObject, Irp);
			}
			break;
		}
		case IOCTL_KEYBOARD_SET_INDICATORS:
		case IOCTL_KEYBOARD_SET_TYPEMATIC: /* not in MSDN, would seem logical */
		{
			/* Send it to all associated Port devices */
			PLIST_ENTRY Head = &((PCLASS_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ListHead;
			PLIST_ENTRY Entry = Head->Flink;
			Status = STATUS_SUCCESS;
			while (Entry != Head)
			{
				PPORT_DEVICE_EXTENSION DevExt = CONTAINING_RECORD(Entry, PORT_DEVICE_EXTENSION, ListEntry);
				NTSTATUS IntermediateStatus;

				IoGetCurrentIrpStackLocation(Irp)->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
				IntermediateStatus = ForwardIrpAndWait(DevExt->DeviceObject, Irp);
				if (!NT_SUCCESS(IntermediateStatus))
					Status = IntermediateStatus;
				Entry = Entry->Flink;
			}
			break;
		}
		default:
			WARN_(CLASS_NAME, "IRP_MJ_DEVICE_CONTROL / unknown I/O control code 0x%lx\n",
				IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode);
			ASSERT(FALSE);
			break;
	}

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

	return Status;
}
예제 #10
0
파일: floppy.c 프로젝트: hoangduit/reactos
static NTSTATUS NTAPI
ConfigCallback(PVOID Context,
               PUNICODE_STRING PathName,
               INTERFACE_TYPE BusType,
               ULONG BusNumber,
               PKEY_VALUE_FULL_INFORMATION *BusInformation,
               CONFIGURATION_TYPE ControllerType,
               ULONG ControllerNumber,
               PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
               CONFIGURATION_TYPE PeripheralType,
               ULONG PeripheralNumber,
               PKEY_VALUE_FULL_INFORMATION *PeripheralInformation)
/*
 * FUNCTION: Callback to IoQueryDeviceDescription, which tells us about our controllers
 * ARGUMENTS:
 *     Context: Unused
 *     PathName: Unused
 *     BusType: Type of the bus that our controller is on
 *     BusNumber: Number of the bus that our controller is on
 *     BusInformation: Unused
 *     ControllerType: Unused
 *     ControllerNumber: Number of the controller that we're adding
 *     ControllerInformation: Full configuration information for our controller
 *     PeripheralType: Unused
 *     PeripheralNumber: Unused
 *     PeripheralInformation: Full configuration information for each drive on our controller
 * RETURNS:
 *     STATUS_SUCCESS in all cases
 * NOTES:
 *     - The only documentation I've found about the contents of these structures is
 *       from the various Microsoft floppy samples and from the DDK headers.  They're
 *       very vague, though, so I'm only mostly sure that this stuff is correct, as
 *       the MS samples do things completely differently than I have done them.  Seems
 *       to work in my VMWare, though.
 *     - Basically, the function gets all of the information (port, dma, irq) about the
 *       controller, and then loops through all of the drives presented in PeripheralInformation.
 *     - Each controller has a CONTROLLER_INFO created for it, and each drive has a DRIVE_INFO.
 *     - Device objects are created for each drive (not controller), as that's the targeted
 *       device in the eyes of the rest of the OS.  Each DRIVE_INFO points to a single CONTROLLER_INFO.
 *     - We only support up to four controllers in the whole system, each of which supports up to four
 *       drives.
 */
{
    PKEY_VALUE_FULL_INFORMATION ControllerFullDescriptor = ControllerInformation[IoQueryDeviceConfigurationData];
    PCM_FULL_RESOURCE_DESCRIPTOR ControllerResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)ControllerFullDescriptor +
            ControllerFullDescriptor->DataOffset);

    PKEY_VALUE_FULL_INFORMATION PeripheralFullDescriptor = PeripheralInformation[IoQueryDeviceConfigurationData];
    PCM_FULL_RESOURCE_DESCRIPTOR PeripheralResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PCHAR)PeripheralFullDescriptor +
            PeripheralFullDescriptor->DataOffset);

    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
    PCM_FLOPPY_DEVICE_DATA FloppyDeviceData;
    UCHAR i;

    PAGED_CODE();
    UNREFERENCED_PARAMETER(PeripheralType);
    UNREFERENCED_PARAMETER(PeripheralNumber);
    UNREFERENCED_PARAMETER(BusInformation);
    UNREFERENCED_PARAMETER(Context);
    UNREFERENCED_PARAMETER(ControllerType);
    UNREFERENCED_PARAMETER(PathName);


    TRACE_(FLOPPY, "ConfigCallback called with ControllerNumber %d\n", ControllerNumber);

    gControllerInfo[gNumberOfControllers].ControllerNumber = ControllerNumber;
    gControllerInfo[gNumberOfControllers].InterfaceType = BusType;
    gControllerInfo[gNumberOfControllers].BusNumber = BusNumber;

    /* Get controller interrupt level/vector, dma channel, and port base */
    for(i = 0; i < ControllerResourceDescriptor->PartialResourceList.Count; i++)
    {
        KeInitializeEvent(&gControllerInfo[gNumberOfControllers].SynchEvent, NotificationEvent, FALSE);

        PartialDescriptor = &ControllerResourceDescriptor->PartialResourceList.PartialDescriptors[i];

        if(PartialDescriptor->Type == CmResourceTypeInterrupt)
        {
            gControllerInfo[gNumberOfControllers].Level = PartialDescriptor->u.Interrupt.Level;
            gControllerInfo[gNumberOfControllers].Vector = PartialDescriptor->u.Interrupt.Vector;

            if(PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
                gControllerInfo[gNumberOfControllers].InterruptMode = Latched;
            else
                gControllerInfo[gNumberOfControllers].InterruptMode = LevelSensitive;
        }

        else if(PartialDescriptor->Type == CmResourceTypePort)
        {
            PHYSICAL_ADDRESS TranslatedAddress;
            ULONG AddressSpace = 0x1; /* I/O Port Range */

            if(!HalTranslateBusAddress(BusType, BusNumber, PartialDescriptor->u.Port.Start, &AddressSpace, &TranslatedAddress))
            {
                WARN_(FLOPPY, "HalTranslateBusAddress failed; returning\n");
                return STATUS_IO_DEVICE_ERROR;
            }

            if(AddressSpace == 0)
                gControllerInfo[gNumberOfControllers].BaseAddress = MmMapIoSpace(TranslatedAddress, FDC_PORT_BYTES, MmNonCached);
            else
                gControllerInfo[gNumberOfControllers].BaseAddress = (PUCHAR)(ULONG_PTR)TranslatedAddress.QuadPart;
        }

        else if(PartialDescriptor->Type == CmResourceTypeDma)
            gControllerInfo[gNumberOfControllers].Dma = PartialDescriptor->u.Dma.Channel;
    }

    /* Start with 0 drives, then go looking */
    gControllerInfo[gNumberOfControllers].NumberOfDrives = 0;

    /* learn about drives attached to controller */
    for(i = 0; i < PeripheralResourceDescriptor->PartialResourceList.Count; i++)
    {
        PDRIVE_INFO DriveInfo = &gControllerInfo[gNumberOfControllers].DriveInfo[i];

        PartialDescriptor = &PeripheralResourceDescriptor->PartialResourceList.PartialDescriptors[i];

        if(PartialDescriptor->Type != CmResourceTypeDeviceSpecific)
            continue;

        FloppyDeviceData = (PCM_FLOPPY_DEVICE_DATA)(PartialDescriptor + 1);

        DriveInfo->ControllerInfo = &gControllerInfo[gNumberOfControllers];
        DriveInfo->UnitNumber = i;

        DriveInfo->FloppyDeviceData.MaxDensity = FloppyDeviceData->MaxDensity;
        DriveInfo->FloppyDeviceData.MountDensity = FloppyDeviceData->MountDensity;
        DriveInfo->FloppyDeviceData.StepRateHeadUnloadTime = FloppyDeviceData->StepRateHeadUnloadTime;
        DriveInfo->FloppyDeviceData.HeadLoadTime = FloppyDeviceData->HeadLoadTime;
        DriveInfo->FloppyDeviceData.MotorOffTime = FloppyDeviceData->MotorOffTime;
        DriveInfo->FloppyDeviceData.SectorLengthCode = FloppyDeviceData->SectorLengthCode;
        DriveInfo->FloppyDeviceData.SectorPerTrack = FloppyDeviceData->SectorPerTrack;
        DriveInfo->FloppyDeviceData.ReadWriteGapLength = FloppyDeviceData->ReadWriteGapLength;
        DriveInfo->FloppyDeviceData.FormatGapLength = FloppyDeviceData->FormatGapLength;
        DriveInfo->FloppyDeviceData.FormatFillCharacter = FloppyDeviceData->FormatFillCharacter;
        DriveInfo->FloppyDeviceData.HeadSettleTime = FloppyDeviceData->HeadSettleTime;
        DriveInfo->FloppyDeviceData.MotorSettleTime = FloppyDeviceData->MotorSettleTime;
        DriveInfo->FloppyDeviceData.MaximumTrackValue = FloppyDeviceData->MaximumTrackValue;
        DriveInfo->FloppyDeviceData.DataTransferLength = FloppyDeviceData->DataTransferLength;

        /* Once it's all set up, acknowledge its existance in the controller info object */
        gControllerInfo[gNumberOfControllers].NumberOfDrives++;
    }

    gControllerInfo[gNumberOfControllers].Populated = TRUE;
    gNumberOfControllers++;

    return STATUS_SUCCESS;
}
예제 #11
0
파일: floppy.c 프로젝트: hoangduit/reactos
static NTSTATUS NTAPI
InitController(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION:  Initialize a newly-found controller
 * ARGUMENTS:
 *     ControllerInfo: pointer to the controller to be initialized
 * RETURNS:
 *     STATUS_SUCCESS if the controller is successfully initialized
 *     STATUS_IO_DEVICE_ERROR otherwise
 */
{
    int i;
    UCHAR HeadLoadTime;
    UCHAR HeadUnloadTime;
    UCHAR StepRateTime;
    UCHAR ControllerVersion;

    PAGED_CODE();
    ASSERT(ControllerInfo);

    TRACE_(FLOPPY, "InitController called with Controller 0x%p\n", ControllerInfo);

    /* Get controller in a known state */
    HwConfigure(ControllerInfo, FALSE, TRUE, TRUE, 0, 0);

    /* Get the controller version */
    ControllerVersion = HwGetVersion(ControllerInfo);

    KeClearEvent(&ControllerInfo->SynchEvent);

    /* Reset the controller */
    if(HwReset(ControllerInfo) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "InitController: unable to reset controller\n");
        return STATUS_IO_DEVICE_ERROR;
    }

    INFO_(FLOPPY, "InitController: waiting for initial interrupt\n");

    /* Wait for an interrupt */
    WaitForControllerInterrupt(ControllerInfo);

    /* Reset means you have to clear each of the four interrupts (one per drive) */
    for(i = 0; i < MAX_DRIVES_PER_CONTROLLER; i++)
    {
        INFO_(FLOPPY, "InitController: Sensing interrupt %d\n", i);

        if(HwSenseInterruptStatus(ControllerInfo) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "InitController: Unable to clear interrupt 0x%x\n", i);
            return STATUS_IO_DEVICE_ERROR;
        }
    }

    INFO_(FLOPPY, "InitController: done sensing interrupts\n");

    /* Next, see if we have the right version to do implied seek */
    if(ControllerVersion == VERSION_ENHANCED)
    {
        /* If so, set that up -- all defaults below except first TRUE for EIS */
        if(HwConfigure(ControllerInfo, TRUE, TRUE, TRUE, 0, 0) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "InitController: unable to set up implied seek\n");
            ControllerInfo->ImpliedSeeks = FALSE;
        }
        else
        {
            INFO_(FLOPPY, "InitController: implied seeks set!\n");
            ControllerInfo->ImpliedSeeks = TRUE;
        }

        /*
         * FIXME: Figure out the answer to the below
         *
         * I must admit that I'm really confused about the Model 30 issue.  At least one
         * important bit (the disk change bit in the DIR) is flipped if this is a Model 30
         * controller.  However, at least one other floppy driver believes that there are only
         * two computers that are guaranteed to have a Model 30 controller:
         *  - IBM Thinkpad 750
         *  - IBM PS2e
         *
         * ...and another driver only lists a config option for "thinkpad", that flips
         * the change line.  A third driver doesn't mention the Model 30 issue at all.
         *
         * What I can't tell is whether or not the average, run-of-the-mill computer now has
         * a Model 30 controller.  For the time being, I'm going to wire this to FALSE,
         * and just not support the computers mentioned above, while I try to figure out
         * how ubiquitous these newfangled 30 thingies are.
         */
        //ControllerInfo->Model30 = TRUE;
        ControllerInfo->Model30 = FALSE;
    }
    else
    {
        INFO_(FLOPPY, "InitController: enhanced version not supported; disabling implied seeks\n");
        ControllerInfo->ImpliedSeeks = FALSE;
        ControllerInfo->Model30 = FALSE;
    }

    /* Specify */
    WARN_(FLOPPY, "FIXME: Figure out speed\n");
    HeadLoadTime = SPECIFY_HLT_500K;
    HeadUnloadTime = SPECIFY_HUT_500K;
    StepRateTime = SPECIFY_SRT_500K;

    INFO_(FLOPPY, "InitController: setting data rate\n");

    /* Set data rate */
    if(HwSetDataRate(ControllerInfo, DRSR_DSEL_500KBPS) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "InitController: unable to set data rate\n");
        return STATUS_IO_DEVICE_ERROR;
    }

    INFO_(FLOPPY, "InitController: issuing specify command to controller\n");

    /* Don't disable DMA --> enable dma (dumb & confusing) */
    if(HwSpecify(ControllerInfo, HeadLoadTime, HeadUnloadTime, StepRateTime, FALSE) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "InitController: unable to specify options\n");
        return STATUS_IO_DEVICE_ERROR;
    }

    /* Init the stop stuff */
    KeInitializeDpc(&ControllerInfo->MotorStopDpc, MotorStopDpcFunc, ControllerInfo);
    KeInitializeTimer(&ControllerInfo->MotorTimer);
    KeInitializeEvent(&ControllerInfo->MotorStoppedEvent, NotificationEvent, FALSE);
    ControllerInfo->StopDpcQueued = FALSE;

    /*
     * Recalibrate each drive on the controller (depends on StartMotor, which depends on the timer stuff above)
     * We don't even know if there is a disk in the drive, so this may not work, but that's OK.
     */
    for(i = 0; i < ControllerInfo->NumberOfDrives; i++)
    {
        INFO_(FLOPPY, "InitController: recalibrating drive 0x%x on controller 0x%p\n", i, ControllerInfo);
        Recalibrate(&ControllerInfo->DriveInfo[i]);
    }

    INFO_(FLOPPY, "InitController: done initializing; returning STATUS_SUCCESS\n");

    return STATUS_SUCCESS;
}
예제 #12
0
파일: floppy.c 프로젝트: hoangduit/reactos
NTSTATUS NTAPI
ResetChangeFlag(PDRIVE_INFO DriveInfo)
/*
 * FUNCTION: Reset the drive's change flag (as reflected in the DIR)
 * ARGUMENTS:
 *     DriveInfo: the drive to reset
 * RETURNS:
 *     STATUS_SUCCESS if the changeline is cleared
 *     STATUS_NO_MEDIA_IN_DEVICE if the changeline cannot be cleared
 *     STATUS_IO_DEVICE_ERROR if the controller cannot be communicated with
 * NOTES:
 *     - Change reset procedure: recalibrate, seek 1, seek 0
 *     - If the line is still set after that, there's clearly no disk in the
 *       drive, so we return STATUS_NO_MEDIA_IN_DEVICE
 *     - PAGED_CODE because we wait
 */
{
    BOOLEAN DiskChanged;

    PAGED_CODE();
    ASSERT(DriveInfo);

    TRACE_(FLOPPY, "ResetChangeFlag called\n");

    /* Try to recalibrate.  We don't care if it works. */
    Recalibrate(DriveInfo);

    /* clear spurious interrupts in prep for seeks */
    KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);

    /* must re-start the drive because Recalibrate() stops it */
    StartMotor(DriveInfo);

    /* Seek to 1 */
    if(HwSeek(DriveInfo, 1) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    WaitForControllerInterrupt(DriveInfo->ControllerInfo);

    if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus failed; bailing out\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    /* Seek back to 0 */
    if(HwSeek(DriveInfo, 0) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ResetChangeFlag(): HwSeek failed; returning STATUS_IO_DEVICE_ERROR\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    WaitForControllerInterrupt(DriveInfo->ControllerInfo);

    if(HwSenseInterruptStatus(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ResetChangeFlag(): HwSenseInterruptStatus #2 failed; bailing\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    /* Check the change bit */
    if(HwDiskChanged(DriveInfo, &DiskChanged) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ResetChangeFlag(): HwDiskChanged failed; returning STATUS_IO_DEVICE_ERROR\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    StopMotor(DriveInfo->ControllerInfo);

    /* if the change flag is still set, there's probably no media in the drive. */
    if(DiskChanged)
        return STATUS_NO_MEDIA_IN_DEVICE;

    /* else we're done! */
    return STATUS_SUCCESS;
}
예제 #13
0
파일: floppy.c 프로젝트: hoangduit/reactos
static NTSTATUS NTAPI
Recalibrate(PDRIVE_INFO DriveInfo)
/*
 * FUNCTION: Start the recalibration process
 * ARGUMENTS:
 *     DriveInfo: Pointer to the driveinfo struct associated with the targeted drive
 * RETURNS:
 *     STATUS_SUCCESS on successful starting of the process
 *     STATUS_IO_DEVICE_ERROR if it fails
 * NOTES:
 *     - Sometimes you have to do two recalibrations, particularly if the disk has <80 tracks.
 *     - PAGED_CODE because we wait
 */
{
    NTSTATUS Status;
    ULONG i;

    PAGED_CODE();
    ASSERT(DriveInfo);

    /* first turn on the motor */
    /* Must stop after every start, prior to return */
    StartMotor(DriveInfo);

    /* set the data rate */
    WARN_(FLOPPY, "FIXME: UN-HARDCODE DATA RATE\n");
    if(HwSetDataRate(DriveInfo->ControllerInfo, 0) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "Recalibrate: HwSetDataRate failed\n");
        StopMotor(DriveInfo->ControllerInfo);
        return STATUS_IO_DEVICE_ERROR;
    }

    /* clear the event just in case the last call forgot */
    KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);

    /* sometimes you have to do this twice; we'll just do it twice all the time since
     * we don't know if the people calling this Recalibrate routine expect a disk to
     * even be in the drive, and if so, if that disk is formatted.
     */
    for(i = 0; i < 2; i++)
    {
        /* Send the command */
        Status = HwRecalibrate(DriveInfo);
        if(Status != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "Recalibrate: HwRecalibrate returned error\n");
            continue;
        }

        WaitForControllerInterrupt(DriveInfo->ControllerInfo);

        /* Get the results */
        Status = HwRecalibrateResult(DriveInfo->ControllerInfo);
        if(Status != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "Recalibrate: HwRecalibrateResult returned error\n");
            break;
        }
    }

    KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);

    /* Must stop after every start, prior to return */
    StopMotor(DriveInfo->ControllerInfo);

    return Status;
}
예제 #14
0
파일: floppy.c 프로젝트: hoangduit/reactos
NTSTATUS NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
/*
 * FUNCTION: Entry-point for the driver
 * ARGUMENTS:
 *     DriverObject: Our driver object
 *     RegistryPath: Unused
 * RETURNS:
 *     STATUS_SUCCESS on successful initialization of at least one drive
 *     STATUS_NO_SUCH_DEVICE if we didn't find even one drive
 *     STATUS_UNSUCCESSFUL otherwise
 */
{
    HANDLE ThreadHandle;

    UNREFERENCED_PARAMETER(RegistryPath);

    /*
     * Set up dispatch routines
     */
    DriverObject->MajorFunction[IRP_MJ_CREATE]         = (PDRIVER_DISPATCH)CreateClose;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = (PDRIVER_DISPATCH)CreateClose;
    DriverObject->MajorFunction[IRP_MJ_READ]           = (PDRIVER_DISPATCH)ReadWrite;
    DriverObject->MajorFunction[IRP_MJ_WRITE]          = (PDRIVER_DISPATCH)ReadWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DeviceIoctl;

    DriverObject->DriverUnload = Unload;

    /*
     * We depend on some zeroes in these structures.  I know this is supposed to be
     * initialized to 0 by the complier but this makes me feel beter.
     */
    memset(&gControllerInfo, 0, sizeof(gControllerInfo));

    /*
     * Set up queue.  This routine cannot fail (trust me, I wrote it).
     */
    IoCsqInitialize(&Csq, CsqInsertIrp, CsqRemoveIrp, CsqPeekNextIrp,
                    CsqAcquireLock, CsqReleaseLock, CsqCompleteCanceledIrp);

    /*
     * ...and its lock
     */
    KeInitializeSpinLock(&IrpQueueLock);

    /*
     * ...and the queue list itself
     */
    InitializeListHead(&IrpQueue);

    /*
     * The queue is counted by a semaphore.  The queue management thread
     * blocks on this semaphore, so if requests come in faster than the queue
     * thread can handle them, the semaphore count goes up.
     */
    KeInitializeSemaphore(&QueueSemaphore, 0, 0x7fffffff);

    /*
     * Event to terminate that thread
     */
    KeInitializeEvent(&QueueThreadTerminate, NotificationEvent, FALSE);

    /*
     * Create the queue processing thread.  Save its handle in the global variable
     * ThreadHandle so we can wait on its termination during Unload.
     */
    if(PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, QueueThread, 0) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "Unable to create system thread; failing init\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if(ObReferenceObjectByHandle(ThreadHandle, STANDARD_RIGHTS_ALL, *PsThreadType, KernelMode, &QueueThreadObject, NULL) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "Unable to reference returned thread handle; failing init\n");
        return STATUS_UNSUCCESSFUL;
    }

    /*
     * Close the handle, now that we have the object pointer and a reference of our own.
     * The handle will certainly not be valid in the context of the caller next time we
     * need it, as handles are process-specific.
     */
    ZwClose(ThreadHandle);

    /*
     * Start the device discovery proces.  Returns STATUS_SUCCESS if
     * it finds even one drive attached to one controller.
     */
    if(!AddControllers(DriverObject))
        return STATUS_NO_SUCH_DEVICE;

    return STATUS_SUCCESS;
}
예제 #15
0
static NTSTATUS
StartProcedure(
    IN PPORT_DEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS Status;
    UCHAR FlagsToDisable = 0;
    UCHAR FlagsToEnable = 0;
    KIRQL Irql;

    if (DeviceExtension->DataPort == 0)
    {
        /* Unable to do something at the moment */
        return STATUS_SUCCESS;
    }

    if (!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_PRESENT)))
    {
        /* Try to detect them */
        TRACE_(I8042PRT, "Check if the controller is really a i8042\n");
        Status = i8042BasicDetect(DeviceExtension);
        if (!NT_SUCCESS(Status))
        {
            WARN_(I8042PRT, "i8042BasicDetect() failed with status 0x%08lx\n", Status);
            return STATUS_UNSUCCESSFUL;
        }

        /* First detect the mouse and then the keyboard!
           If we do it the other way round, some systems throw away settings like the keyboard translation, when detecting the mouse. */
        TRACE_(I8042PRT, "Detecting mouse\n");
        i8042DetectMouse(DeviceExtension);
        TRACE_(I8042PRT, "Detecting keyboard\n");
        i8042DetectKeyboard(DeviceExtension);

        INFO_(I8042PRT, "Keyboard present: %s\n", DeviceExtension->Flags & KEYBOARD_PRESENT ? "YES" : "NO");
        INFO_(I8042PRT, "Mouse present   : %s\n", DeviceExtension->Flags & MOUSE_PRESENT ? "YES" : "NO");

        TRACE_(I8042PRT, "Enabling i8042 interrupts\n");
        if (DeviceExtension->Flags & KEYBOARD_PRESENT)
        {
            FlagsToDisable |= CCB_KBD_DISAB;
            FlagsToEnable |= CCB_KBD_INT_ENAB;
        }
        if (DeviceExtension->Flags & MOUSE_PRESENT)
        {
            FlagsToDisable |= CCB_MOUSE_DISAB;
            FlagsToEnable |= CCB_MOUSE_INT_ENAB;
        }

        Status = EnableInterrupts(DeviceExtension, FlagsToDisable, FlagsToEnable);
        if (!NT_SUCCESS(Status))
        {
            DeviceExtension->Flags &= ~(KEYBOARD_PRESENT | MOUSE_PRESENT);
            return Status;
        }
    }

    /* Connect interrupts */
    if (DeviceExtension->Flags & KEYBOARD_PRESENT &&
        DeviceExtension->Flags & KEYBOARD_CONNECTED &&
        DeviceExtension->Flags & KEYBOARD_STARTED &&
        !(DeviceExtension->Flags & KEYBOARD_INITIALIZED))
    {
        /* Keyboard is ready to be initialized */
        Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension);
        if (NT_SUCCESS(Status))
        {
            DeviceExtension->Flags |= KEYBOARD_INITIALIZED;
        }
    }

    if (DeviceExtension->Flags & MOUSE_PRESENT &&
        DeviceExtension->Flags & MOUSE_CONNECTED &&
        DeviceExtension->Flags & MOUSE_STARTED &&
        !(DeviceExtension->Flags & MOUSE_INITIALIZED))
    {
        /* Mouse is ready to be initialized */
        Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension);
        if (NT_SUCCESS(Status))
        {
            DeviceExtension->Flags |= MOUSE_INITIALIZED;
        }

        /* Start the mouse */
        Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt);
        i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE);
        KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql);
    }

    return Status;
}
예제 #16
0
BOOLEAN NTAPI
IntVideoPortSetupInterrupt(
   IN PDEVICE_OBJECT DeviceObject,
   IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
   IN PVIDEO_PORT_CONFIG_INFO ConfigInfo)
{
   NTSTATUS Status;
   PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;

   DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

   /*
    * MSDN documentation for VIDEO_PORT_CONFIG_INFO states: "If a miniport driver's
    * HwVidFindAdapter function finds that the video adapter does not generate
    * interrupts or that it cannot determine a valid interrupt vector/level for
    * the adapter, HwVidFindAdapter should set both BusInterruptVector and
    * BusInterruptLevel to zero.
    */

   if (DriverExtension->InitializationData.HwInterrupt != NULL &&
       (ConfigInfo->BusInterruptLevel != 0 ||
       ConfigInfo->BusInterruptVector != 0))
   {
      ULONG InterruptVector;
      KIRQL Irql;
      KAFFINITY Affinity;

      InterruptVector = HalGetInterruptVector(
         ConfigInfo->AdapterInterfaceType,
         ConfigInfo->SystemIoBusNumber,
         ConfigInfo->BusInterruptLevel,
         ConfigInfo->BusInterruptVector,
         &Irql,
         &Affinity);

      if (InterruptVector == 0)
      {
         WARN_(VIDEOPRT, "HalGetInterruptVector failed\n");
         return FALSE;
      }

      KeInitializeSpinLock(&DeviceExtension->InterruptSpinLock);
      Status = IoConnectInterrupt(
         &DeviceExtension->InterruptObject,
         IntVideoPortInterruptRoutine,
         DeviceExtension,
         &DeviceExtension->InterruptSpinLock,
         InterruptVector,
         Irql,
         Irql,
         ConfigInfo->InterruptMode,
         DeviceExtension->InterruptShared,
         Affinity,
         FALSE);

      if (!NT_SUCCESS(Status))
      {
         WARN_(VIDEOPRT, "IoConnectInterrupt failed with status 0x%08x\n", Status);
         return FALSE;
      }
   }

   return TRUE;
}
예제 #17
0
static NTSTATUS
i8042PnpStartDevice(
    IN PDEVICE_OBJECT DeviceObject,
    IN PCM_RESOURCE_LIST AllocatedResources,
    IN PCM_RESOURCE_LIST AllocatedResourcesTranslated)
{
    PFDO_DEVICE_EXTENSION DeviceExtension;
    PPORT_DEVICE_EXTENSION PortDeviceExtension;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor, ResourceDescriptorTranslated;
    INTERRUPT_DATA InterruptData;
    BOOLEAN FoundDataPort = FALSE;
    BOOLEAN FoundControlPort = FALSE;
    BOOLEAN FoundIrq = FALSE;
    ULONG i;
    NTSTATUS Status;

    TRACE_(I8042PRT, "i8042PnpStartDevice(%p)\n", DeviceObject);
    DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
    PortDeviceExtension = DeviceExtension->PortDeviceExtension;

    ASSERT(DeviceExtension->PnpState == dsStopped);

    if (!AllocatedResources)
    {
        WARN_(I8042PRT, "No allocated resources sent to driver\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    if (AllocatedResources->Count != 1)
    {
        WARN_(I8042PRT, "Wrong number of allocated resources sent to driver\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    if (AllocatedResources->List[0].PartialResourceList.Version != 1
     || AllocatedResources->List[0].PartialResourceList.Revision != 1
     || AllocatedResourcesTranslated->List[0].PartialResourceList.Version != 1
     || AllocatedResourcesTranslated->List[0].PartialResourceList.Revision != 1)
    {
        WARN_(I8042PRT, "Revision mismatch: %u.%u != 1.1 or %u.%u != 1.1\n",
            AllocatedResources->List[0].PartialResourceList.Version,
            AllocatedResources->List[0].PartialResourceList.Revision,
            AllocatedResourcesTranslated->List[0].PartialResourceList.Version,
            AllocatedResourcesTranslated->List[0].PartialResourceList.Revision);
        return STATUS_REVISION_MISMATCH;
    }

    /* Get Irq and optionally control port and data port */
    for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
    {
        ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
        ResourceDescriptorTranslated = &AllocatedResourcesTranslated->List[0].PartialResourceList.PartialDescriptors[i];
        switch (ResourceDescriptor->Type)
        {
            case CmResourceTypePort:
            {
                if (ResourceDescriptor->u.Port.Length == 1)
                {
                    /* We assume that the first ressource will
                     * be the control port and the second one
                     * will be the data port...
                     */
                    if (!FoundDataPort)
                    {
                        PortDeviceExtension->DataPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
                        INFO_(I8042PRT, "Found data port: %p\n", PortDeviceExtension->DataPort);
                        FoundDataPort = TRUE;
                    }
                    else if (!FoundControlPort)
                    {
                        PortDeviceExtension->ControlPort = ULongToPtr(ResourceDescriptor->u.Port.Start.u.LowPart);
                        INFO_(I8042PRT, "Found control port: %p\n", PortDeviceExtension->ControlPort);
                        FoundControlPort = TRUE;
                    }
                    else
                    {
                        WARN_(I8042PRT, "Too much I/O ranges provided: 0x%lx\n", ResourceDescriptor->u.Port.Length);
                        return STATUS_INVALID_PARAMETER;
                    }
                }
                else
                    WARN_(I8042PRT, "Invalid I/O range length: 0x%lx\n", ResourceDescriptor->u.Port.Length);
                break;
            }
            case CmResourceTypeInterrupt:
            {
                if (FoundIrq)
                    return STATUS_INVALID_PARAMETER;
                InterruptData.Dirql = (KIRQL)ResourceDescriptorTranslated->u.Interrupt.Level;
                InterruptData.Vector = ResourceDescriptorTranslated->u.Interrupt.Vector;
                InterruptData.Affinity = ResourceDescriptorTranslated->u.Interrupt.Affinity;
                if (ResourceDescriptorTranslated->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
                    InterruptData.InterruptMode = Latched;
                else
                    InterruptData.InterruptMode = LevelSensitive;
                InterruptData.ShareInterrupt = (ResourceDescriptorTranslated->ShareDisposition == CmResourceShareShared);
                INFO_(I8042PRT, "Found irq resource: %lu\n", ResourceDescriptor->u.Interrupt.Level);
                FoundIrq = TRUE;
                break;
            }
            default:
                WARN_(I8042PRT, "Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
        }
    }

    if (!FoundIrq)
    {
        WARN_(I8042PRT, "Interrupt resource was not found in allocated resources list\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    else if (DeviceExtension->Type == Keyboard && (!FoundDataPort || !FoundControlPort))
    {
        WARN_(I8042PRT, "Some required resources were not found in allocated resources list\n");
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    else if (DeviceExtension->Type == Mouse && (FoundDataPort || FoundControlPort))
    {
        WARN_(I8042PRT, "Too much resources were provided in allocated resources list\n");
        return STATUS_INVALID_PARAMETER;
    }

    switch (DeviceExtension->Type)
    {
        case Keyboard:
        {
            RtlCopyMemory(
                &PortDeviceExtension->KeyboardInterrupt,
                &InterruptData,
                sizeof(INTERRUPT_DATA));
            PortDeviceExtension->Flags |= KEYBOARD_STARTED;
            Status = StartProcedure(PortDeviceExtension);
            break;
        }
        case Mouse:
        {
            RtlCopyMemory(
                &PortDeviceExtension->MouseInterrupt,
                &InterruptData,
                sizeof(INTERRUPT_DATA));
            PortDeviceExtension->Flags |= MOUSE_STARTED;
            Status = StartProcedure(PortDeviceExtension);
            break;
        }
        default:
        {
            WARN_(I8042PRT, "Unknown FDO type %u\n", DeviceExtension->Type);
            ASSERT(!(PortDeviceExtension->Flags & KEYBOARD_CONNECTED) || !(PortDeviceExtension->Flags & MOUSE_CONNECTED));
            Status = STATUS_INVALID_DEVICE_REQUEST;
        }
    }

    if (NT_SUCCESS(Status))
        DeviceExtension->PnpState = dsStarted;

    return Status;
}
예제 #18
0
파일: devctrl.c 프로젝트: RPG-7/reactos
NTSTATUS NTAPI
SerialDeviceControl(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp)
{
	PIO_STACK_LOCATION Stack;
	ULONG IoControlCode;
	PSERIAL_DEVICE_EXTENSION DeviceExtension;
	ULONG LengthIn, LengthOut;
	ULONG_PTR Information = 0;
	PVOID BufferIn, BufferOut;
	PUCHAR ComPortBase;
	NTSTATUS Status;

	TRACE_(SERIAL, "IRP_MJ_DEVICE_CONTROL dispatch\n");

	Stack = IoGetCurrentIrpStackLocation(Irp);
	LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
	LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
	DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
	ComPortBase = ULongToPtr(DeviceExtension->BaseAddress);
	IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
	SerialGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);

	/* FIXME: need to probe buffers */
	/* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */
	switch (IoControlCode)
	{
		case IOCTL_SERIAL_CLEAR_STATS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_CLEAR_STATS\n");
			KeSynchronizeExecution(
				DeviceExtension->Interrupt,
				(PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats,
				DeviceExtension);
			Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_SERIAL_CLR_DTR:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_CLR_DTR\n");
			/* FIXME: If the handshake flow control of the device is configured to
			 * automatically use DTR, return STATUS_INVALID_PARAMETER */
			Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
			if (NT_SUCCESS(Status))
			{
				DeviceExtension->MCR &= ~SR_MCR_DTR;
				WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
				IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
			}
			break;
		}
		case IOCTL_SERIAL_CLR_RTS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_CLR_RTS\n");
			/* FIXME: If the handshake flow control of the device is configured to
			 * automatically use RTS, return STATUS_INVALID_PARAMETER */
			Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
			if (NT_SUCCESS(Status))
			{
				DeviceExtension->MCR &= ~SR_MCR_RTS;
				WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
				IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
			}
			break;
		}
		case IOCTL_SERIAL_CONFIG_SIZE:
		{
			/* Obsolete on Microsoft Windows 2000+ */
			PULONG pConfigSize;
			TRACE_(SERIAL, "IOCTL_SERIAL_CONFIG_SIZE\n");
			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pConfigSize = (PULONG)BufferOut;
				*pConfigSize = 0;
				Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_BAUD_RATE:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_BAUD_RATE\n");
			if (LengthOut < sizeof(SERIAL_BAUD_RATE))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				((PSERIAL_BAUD_RATE)BufferOut)->BaudRate = DeviceExtension->BaudRate;
				Information = sizeof(SERIAL_BAUD_RATE);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_CHARS:
		{
			/* FIXME */
			PSERIAL_CHARS pSerialChars;
			ERR_(SERIAL, "IOCTL_SERIAL_GET_CHARS not implemented.\n");
			if (LengthOut < sizeof(SERIAL_CHARS))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pSerialChars = (PSERIAL_CHARS)BufferOut;
				pSerialChars->EofChar = 0;
				pSerialChars->ErrorChar = 0;
				pSerialChars->BreakChar = 0;
				pSerialChars->EventChar = 0;
				pSerialChars->XonChar = 0;
				pSerialChars->XoffChar = 0;
				Information = sizeof(SERIAL_CHARS);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_COMMSTATUS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_COMMSTATUS\n");
			if (LengthOut < sizeof(SERIAL_STATUS))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				Status = SerialGetCommStatus((PSERIAL_STATUS)BufferOut, DeviceExtension);
				Information = sizeof(SERIAL_STATUS);
			}
			break;
		}
		case IOCTL_SERIAL_GET_DTRRTS:
		{
			PULONG pDtrRts;
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_DTRRTS\n");
			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pDtrRts = (PULONG)BufferOut;
				*pDtrRts = 0;
				if (DeviceExtension->MCR & SR_MCR_DTR)
					*pDtrRts |= SERIAL_DTR_STATE;
				if (DeviceExtension->MCR & SR_MCR_RTS)
					*pDtrRts |= SERIAL_RTS_STATE;
				Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_HANDFLOW:
		{
			/* FIXME */
			PSERIAL_HANDFLOW pSerialHandflow;
			ERR_(SERIAL, "IOCTL_SERIAL_GET_HANDFLOW not implemented.\n");
			if (LengthOut < sizeof(SERIAL_HANDFLOW))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pSerialHandflow = (PSERIAL_HANDFLOW)BufferOut;
				pSerialHandflow->ControlHandShake = 0;
				pSerialHandflow->FlowReplace = 0;
				pSerialHandflow->XonLimit = 0;
				pSerialHandflow->XoffLimit = 0;
				Information = sizeof(SERIAL_HANDFLOW);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_LINE_CONTROL:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_LINE_CONTROL\n");
			if (LengthOut < sizeof(SERIAL_LINE_CONTROL))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				*((PSERIAL_LINE_CONTROL)BufferOut) = DeviceExtension->SerialLineControl;
				Information = sizeof(SERIAL_LINE_CONTROL);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_MODEM_CONTROL:
		{
			PULONG pMCR;
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEM_CONTROL\n");
			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pMCR = (PULONG)BufferOut;
				*pMCR = DeviceExtension->MCR;
				Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_MODEMSTATUS:
		{
			PULONG pMSR;
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_MODEMSTATUS\n");
			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pMSR = (PULONG)BufferOut;
				*pMSR = DeviceExtension->MSR;
				Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_PROPERTIES:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_PROPERTIES\n");
			if (LengthOut < sizeof(SERIAL_COMMPROP))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				Status = SerialGetCommProp((PSERIAL_COMMPROP)BufferOut, DeviceExtension);
				Information = sizeof(SERIAL_COMMPROP);
			}
			break;
		}
		case IOCTL_SERIAL_GET_STATS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_STATS\n");
			if (LengthOut < sizeof(SERIALPERF_STATS))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				KeSynchronizeExecution(DeviceExtension->Interrupt,
					(PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
				Information = sizeof(SERIALPERF_STATS);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_TIMEOUTS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_TIMEOUTS\n");
			if (LengthOut != sizeof(SERIAL_TIMEOUTS) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				*(PSERIAL_TIMEOUTS)BufferOut = DeviceExtension->SerialTimeOuts;
				Information = sizeof(SERIAL_TIMEOUTS);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_GET_WAIT_MASK:
		{
			PULONG pWaitMask;
			TRACE_(SERIAL, "IOCTL_SERIAL_GET_WAIT_MASK\n");
			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pWaitMask = (PULONG)BufferOut;
				*pWaitMask = DeviceExtension->WaitMask;
				Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_IMMEDIATE_CHAR:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_IMMEDIATE_CHAR not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_LSRMST_INSERT:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_LSRMST_INSERT not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_PURGE:
		{
			KIRQL Irql;
			TRACE_(SERIAL, "IOCTL_SERIAL_PURGE\n");
			/* FIXME: SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT
			 * should stop current request */
			if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				ULONG PurgeMask = *(PULONG)BufferIn;

				Status = STATUS_SUCCESS;
				/* FIXME: use SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT flags */
				if (PurgeMask & SERIAL_PURGE_RXCLEAR)
				{
					KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
					DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
					if (DeviceExtension->UartType >= Uart16550A)
					{
						/* Clear also Uart FIFO */
						Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
						if (NT_SUCCESS(Status))
						{
							WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_RCVR);
							IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
						}
					}
					KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
				}

				if (PurgeMask & SERIAL_PURGE_TXCLEAR)
				{
					KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
					DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
					if (DeviceExtension->UartType >= Uart16550A)
					{
						/* Clear also Uart FIFO */
						Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
						if (NT_SUCCESS(Status))
						{
							WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_XMIT);
							IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
						}
					}
					KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
				}
			}
			break;
		}
		case IOCTL_SERIAL_RESET_DEVICE:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_RESET_DEVICE not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_SET_BAUD_RATE:
		{
			PULONG pNewBaudRate;
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_BAUD_RATE\n");
			if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pNewBaudRate = (PULONG)BufferIn;
				Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate);
			}
			break;
		}
		case IOCTL_SERIAL_SET_BREAK_OFF:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_OFF not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_SET_BREAK_ON:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_BREAK_ON not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_SET_CHARS:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_CHARS not implemented.\n");
			Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_SERIAL_SET_DTR:
		{
			/* FIXME: If the handshake flow control of the device is configured to
			 * automatically use DTR, return STATUS_INVALID_PARAMETER */
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_DTR\n");
			if (!(DeviceExtension->MCR & SR_MCR_DTR))
			{
				Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				if (NT_SUCCESS(Status))
				{
					DeviceExtension->MCR |= SR_MCR_DTR;
					WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
					IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				}
			}
			else
				Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_SERIAL_SET_FIFO_CONTROL:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_FIFO_CONTROL\n");
			if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				if (NT_SUCCESS(Status))
				{
					WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
					IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				}
			}
			break;
		}
		case IOCTL_SERIAL_SET_HANDFLOW:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_HANDFLOW not implemented.\n");
			Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_SERIAL_SET_LINE_CONTROL:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_LINE_CONTROL\n");
			if (LengthIn < sizeof(SERIAL_LINE_CONTROL))
				Status = STATUS_BUFFER_TOO_SMALL;
			else if (BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
				Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)BufferIn);
			break;
		}
		case IOCTL_SERIAL_SET_MODEM_CONTROL:
		{
			PULONG pMCR;
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_MODEM_CONTROL\n");
			if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				if (NT_SUCCESS(Status))
				{
					pMCR = (PULONG)BufferIn;
					DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
					WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
					IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				}
			}
			break;
		}
		case IOCTL_SERIAL_SET_QUEUE_SIZE:
		{
			if (LengthIn < sizeof(SERIAL_QUEUE_SIZE ))
				return STATUS_BUFFER_TOO_SMALL;
			else if (BufferIn == NULL)
				return STATUS_INVALID_PARAMETER;
			else
			{
				KIRQL Irql;
				PSERIAL_QUEUE_SIZE NewQueueSize = (PSERIAL_QUEUE_SIZE)BufferIn;
				Status = STATUS_SUCCESS;
				if (NewQueueSize->InSize > DeviceExtension->InputBuffer.Length)
				{
					KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
					Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, NewQueueSize->InSize);
					KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
				}
				if (NT_SUCCESS(Status) && NewQueueSize->OutSize > DeviceExtension->OutputBuffer.Length)
				{
					KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
					Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, NewQueueSize->OutSize);
					KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
				}
			}
			break;
		}
		case IOCTL_SERIAL_SET_RTS:
		{
			/* FIXME: If the handshake flow control of the device is configured to
			 * automatically use DTR, return STATUS_INVALID_PARAMETER */
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_RTS\n");
			if (!(DeviceExtension->MCR & SR_MCR_RTS))
			{
				Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				if (NT_SUCCESS(Status))
				{
					DeviceExtension->MCR |= SR_MCR_RTS;
					WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
					IoReleaseRemoveLock(&DeviceExtension->RemoveLock, ULongToPtr(DeviceExtension->ComPort));
				}
			}
			else
				Status = STATUS_SUCCESS;
			break;
		}
		case IOCTL_SERIAL_SET_TIMEOUTS:
		{
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_TIMEOUTS\n");
			if (LengthIn != sizeof(SERIAL_TIMEOUTS) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)BufferIn;
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_SET_WAIT_MASK:
		{
			PULONG pWaitMask = (PULONG)BufferIn;
			TRACE_(SERIAL, "IOCTL_SERIAL_SET_WAIT_MASK\n");

			if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else if (DeviceExtension->WaitOnMaskIrp) /* FIXME: Race condition ; field may be currently in modification */
			{
				WARN_(SERIAL, "An IRP is already currently processed\n");
				Status = STATUS_INVALID_PARAMETER;
			}
			else
			{
				DeviceExtension->WaitMask = *pWaitMask;
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_SERIAL_SET_XOFF:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_XOFF not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_SET_XON:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_SET_XON not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		case IOCTL_SERIAL_WAIT_ON_MASK:
		{
			PIRP WaitingIrp;
			TRACE_(SERIAL, "IOCTL_SERIAL_WAIT_ON_MASK\n");

			if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				IoMarkIrpPending(Irp);

				WaitingIrp = InterlockedCompareExchangePointer(
					&DeviceExtension->WaitOnMaskIrp,
					Irp,
					NULL);

				/* Check if an Irp is already pending */
				if (WaitingIrp != NULL)
				{
					/* Unable to have a 2nd pending IRP for this IOCTL */
					WARN_(SERIAL, "Unable to pend a second IRP for IOCTL_SERIAL_WAIT_ON_MASK\n");
					Irp->IoStatus.Information = 0;
					Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
					IoCompleteRequest(Irp, IO_NO_INCREMENT);
				}
				return STATUS_PENDING;
			}
			break;
		}
		case IOCTL_SERIAL_XOFF_COUNTER:
		{
			/* FIXME */
			ERR_(SERIAL, "IOCTL_SERIAL_XOFF_COUNTER not implemented.\n");
			Status = STATUS_NOT_IMPLEMENTED;
			break;
		}
		default:
		{
			/* Pass Irp to lower driver */
			TRACE_(SERIAL, "Unknown IOCTL code 0x%x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
			IoSkipCurrentIrpStackLocation(Irp);
			return IoCallDriver(DeviceExtension->LowerDevice, Irp);
		}
	}

	Irp->IoStatus.Status = Status;
	if (Status == STATUS_PENDING)
	{
		IoMarkIrpPending(Irp);
	}
	else
	{
		Irp->IoStatus.Information = Information;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
	}
	return Status;
}
예제 #19
0
NTSTATUS
NTAPI
IntCopyRegistryKey(
    _In_ HANDLE SourceKeyHandle,
    _In_ HANDLE DestKeyHandle)
{
    PVOID InfoBuffer;
    PKEY_BASIC_INFORMATION KeyInformation;
    PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
    OBJECT_ATTRIBUTES ObjectAttributes;
    ULONG Index, InformationLength, RequiredLength;
    UNICODE_STRING NameString;
    NTSTATUS Status;
    HANDLE SourceSubKeyHandle, DestSubKeyHandle;

    /* Start with no buffer, set initial size */
    InfoBuffer = NULL;
    InformationLength = 256;

    /* Start looping with key index 0 */
    Index = 0;
    while (TRUE)
    {
        /* Check if we have no buffer */
        if (InfoBuffer == NULL)
        {
            /* Allocate a new buffer */
            InfoBuffer = ExAllocatePoolWithTag(PagedPool,
                                               InformationLength,
                                               TAG_VIDEO_PORT_BUFFER);
            if (InfoBuffer == NULL)
            {
                ERR_(VIDEOPRT, "Could not allocate buffer for key info\n");
                return Status;
            }
        }

        /* Enumerate the next sub-key */
        KeyInformation = InfoBuffer;
        Status = ZwEnumerateKey(SourceKeyHandle,
                                Index,
                                KeyBasicInformation,
                                KeyInformation,
                                InformationLength,
                                &RequiredLength);
        if ((Status == STATUS_BUFFER_OVERFLOW) ||
                (Status == STATUS_BUFFER_TOO_SMALL))
        {
            /* Free the buffer and remember the required size */
            ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
            InfoBuffer = NULL;
            InformationLength = RequiredLength;

            /* Try again */
            continue;
        }
        else if (Status == STATUS_NO_MORE_ENTRIES)
        {
            /* We are done with the sub-keys */
            break;
        }
        else if (!NT_SUCCESS(Status))
        {
            ERR_(VIDEOPRT, "ZwEnumerateKey failed, status 0x%lx\n", Status);
            goto Cleanup;
        }

        /* Initialize a unicode string from the key name */
        NameString.Buffer = KeyInformation->Name;
        NameString.Length = (USHORT)KeyInformation->NameLength;
        NameString.MaximumLength = NameString.Length;

        /* Initialize object attributes and open the source sub-key */
        InitializeObjectAttributes(&ObjectAttributes,
                                   &NameString,
                                   OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                                   SourceKeyHandle,
                                   NULL);
        Status = ZwOpenKey(&SourceSubKeyHandle, KEY_READ, &ObjectAttributes);
        if (!NT_SUCCESS(Status))
        {
            ERR_(VIDEOPRT, "failed to open the source key.\n");
            goto Cleanup;
        }

        /* Initialize object attributes and create the dest sub-key */
        InitializeObjectAttributes(&ObjectAttributes,
                                   &NameString,
                                   OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
                                   DestKeyHandle,
                                   NULL);
        Status = ZwCreateKey(&DestSubKeyHandle,
                             KEY_WRITE,
                             &ObjectAttributes,
                             0,
                             NULL,
                             0,
                             NULL);
        if (!NT_SUCCESS(Status))
        {
            ERR_(VIDEOPRT, "failed to create the destination key.\n");
            ObCloseHandle(SourceSubKeyHandle, KernelMode);
            goto Cleanup;
        }

        /* Recursively copy the sub-key */
        Status = IntCopyRegistryKey(SourceSubKeyHandle, DestSubKeyHandle);
        if (!NT_SUCCESS(Status))
        {
            /* Just warn, but continue with the remaining sub-keys */
            WARN_(VIDEOPRT, "failed to copy subkey '%wZ'.\n", &NameString);
        }

        /* Close the sub-key handles */
        ObCloseHandle(SourceSubKeyHandle, KernelMode);
        ObCloseHandle(DestSubKeyHandle, KernelMode);

        /* Next sub-key */
        Index++;
    }

    /* Start looping with value index 0 */
    Index = 0;
    while (TRUE)
    {
        /* Check if we have no buffer */
        if (InfoBuffer == NULL)
        {
            /* Allocate a new buffer */
            InfoBuffer = ExAllocatePoolWithTag(PagedPool,
                                               InformationLength,
                                               TAG_VIDEO_PORT_BUFFER);
            if (InfoBuffer == NULL)
            {
                ERR_(VIDEOPRT, "Could not allocate buffer for key values\n");
                return Status;
            }
        }

        /* Enumerate the next value */
        KeyValueInformation = InfoBuffer;
        Status = ZwEnumerateValueKey(SourceKeyHandle,
                                     Index,
                                     KeyValueFullInformation,
                                     KeyValueInformation,
                                     InformationLength,
                                     &RequiredLength);
        if ((Status == STATUS_BUFFER_OVERFLOW) ||
                (Status == STATUS_BUFFER_TOO_SMALL))
        {
            /* Free the buffer and remember the required size */
            ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
            InfoBuffer = NULL;
            InformationLength = RequiredLength;

            /* Try again */
            continue;
        }
        else if (Status == STATUS_NO_MORE_ENTRIES)
        {
            /* We are done with the values */
            Status = STATUS_SUCCESS;
            break;
        }
        else if (!NT_SUCCESS(Status))
        {
            ERR_(VIDEOPRT, "ZwEnumerateValueKey failed, status 0x%lx\n", Status);
            goto Cleanup;
        }

        /* Initialize a unicode string from the value name */
        NameString.Buffer = KeyValueInformation->Name;
        NameString.Length = (USHORT)KeyValueInformation->NameLength;
        NameString.MaximumLength = NameString.Length;

        /* Create the key value in the destination key */
        Status = ZwSetValueKey(DestKeyHandle,
                               &NameString,
                               KeyValueInformation->TitleIndex,
                               KeyValueInformation->Type,
                               (PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
                               KeyValueInformation->DataLength);
        if (!NT_SUCCESS(Status))
        {
            /* Just warn, but continue with the remaining sub-keys */
            WARN_(VIDEOPRT, "failed to set value '%wZ'.\n", NameString);
        }

        /* Next subkey */
        Index++;
    }

Cleanup:
    /* Free the buffer and return the failure code */
    if (InfoBuffer != NULL)
        ExFreePoolWithTag(InfoBuffer, TAG_VIDEO_PORT_BUFFER);
    return Status;
}
예제 #20
0
파일: registry.c 프로젝트: GYGit/reactos
NTSTATUS
ReadRegistryEntries(
	IN PUNICODE_STRING RegistryPath,
	OUT PI8042_SETTINGS Settings)
{
	RTL_QUERY_REGISTRY_TABLE Parameters[17];
	NTSTATUS Status;

	ULONG DefaultKeyboardDataQueueSize = 0x64;
	PCWSTR DefaultKeyboardDeviceBaseName = L"KeyboardPort";
	ULONG DefaultMouseDataQueueSize = 0x64;
	ULONG DefaultMouseResolution = 3;
	ULONG DefaultMouseSynchIn100ns = 20000000;
	ULONG DefaultNumberOfButtons = 2;
	PCWSTR DefaultPointerDeviceBaseName = L"PointerPort";
	ULONG DefaultPollStatusIterations = 1;
	ULONG DefaultOverrideKeyboardType = 4;
	ULONG DefaultOverrideKeyboardSubtype = 0;
	ULONG DefaultPollingIterations = 12000;
	ULONG DefaultPollingIterationsMaximum = 12000;
	ULONG DefaultResendIterations = 0x3;
	ULONG DefaultSampleRate = 60;
	ULONG DefaultCrashOnCtrlScroll;

	/* Default value for CrashOnCtrlScroll depends if we're
	 * running a debug build or a normal build.
	 */
#if DBG
	DefaultCrashOnCtrlScroll = 1;
#else
	DefaultCrashOnCtrlScroll = 0;
#endif

	RtlZeroMemory(Parameters, sizeof(Parameters));

	Parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
	Parameters[0].Name = L"Parameters";

	Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[1].Name = L"KeyboardDataQueueSize";
	Parameters[1].EntryContext = &Settings->KeyboardDataQueueSize;
	Parameters[1].DefaultType = REG_DWORD;
	Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize;
	Parameters[1].DefaultLength = sizeof(ULONG);

	Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[2].Name = L"KeyboardDeviceBaseName";
	Parameters[2].EntryContext = &Settings->KeyboardDeviceBaseName;
	Parameters[2].DefaultType = REG_SZ;
	Parameters[2].DefaultData = (PVOID)DefaultKeyboardDeviceBaseName;
	Parameters[2].DefaultLength = 0;

	Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[3].Name = L"MouseDataQueueSize";
	Parameters[3].EntryContext = &Settings->MouseDataQueueSize;
	Parameters[3].DefaultType = REG_DWORD;
	Parameters[3].DefaultData = &DefaultMouseDataQueueSize;
	Parameters[3].DefaultLength = sizeof(ULONG);

	Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[4].Name = L"MouseResolution";
	Parameters[4].EntryContext = &Settings->MouseResolution;
	Parameters[4].DefaultType = REG_DWORD;
	Parameters[4].DefaultData = &DefaultMouseResolution;
	Parameters[4].DefaultLength = sizeof(ULONG);

	Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[5].Name = L"MouseSynchIn100ns";
	Parameters[5].EntryContext = &Settings->MouseSynchIn100ns;
	Parameters[5].DefaultType = REG_DWORD;
	Parameters[5].DefaultData = &DefaultMouseSynchIn100ns;
	Parameters[5].DefaultLength = sizeof(ULONG);

	Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[6].Name = L"NumberOfButtons";
	Parameters[6].EntryContext = &Settings->NumberOfButtons;
	Parameters[6].DefaultType = REG_DWORD;
	Parameters[6].DefaultData = &DefaultNumberOfButtons;
	Parameters[6].DefaultLength = sizeof(ULONG);

	Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[7].Name = L"PointerDeviceBaseName";
	Parameters[7].EntryContext = &Settings->PointerDeviceBaseName;
	Parameters[7].DefaultType = REG_SZ;
	Parameters[7].DefaultData = (PVOID)DefaultPointerDeviceBaseName;
	Parameters[7].DefaultLength = 0;

	Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[8].Name = L"PollStatusIterations";
	Parameters[8].EntryContext = &Settings->PollStatusIterations;
	Parameters[8].DefaultType = REG_DWORD;
	Parameters[8].DefaultData = &DefaultPollStatusIterations;
	Parameters[8].DefaultLength = sizeof(ULONG);

	Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[9].Name = L"OverrideKeyboardType";
	Parameters[9].EntryContext = &Settings->OverrideKeyboardType;
	Parameters[9].DefaultType = REG_DWORD;
	Parameters[9].DefaultData = &DefaultOverrideKeyboardType;
	Parameters[9].DefaultLength = sizeof(ULONG);

	Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[10].Name = L"OverrideKeyboardSubtype";
	Parameters[10].EntryContext = &Settings->OverrideKeyboardSubtype;
	Parameters[10].DefaultType = REG_DWORD;
	Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype;
	Parameters[10].DefaultLength = sizeof(ULONG);

	Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[11].Name = L"PollingIterations";
	Parameters[11].EntryContext = &Settings->PollingIterations;
	Parameters[11].DefaultType = REG_DWORD;
	Parameters[11].DefaultData = &DefaultPollingIterations;
	Parameters[11].DefaultLength = sizeof(ULONG);

	Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[12].Name = L"PollingIterationsMaximum";
	Parameters[12].EntryContext = &Settings->PollingIterationsMaximum;
	Parameters[12].DefaultType = REG_DWORD;
	Parameters[12].DefaultData = &DefaultPollingIterationsMaximum;
	Parameters[12].DefaultLength = sizeof(ULONG);

	Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[13].Name = L"ResendIterations";
	Parameters[13].EntryContext = &Settings->ResendIterations;
	Parameters[13].DefaultType = REG_DWORD;
	Parameters[13].DefaultData = &DefaultResendIterations;
	Parameters[13].DefaultLength = sizeof(ULONG);

	Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[14].Name = L"SampleRate";
	Parameters[14].EntryContext = &Settings->SampleRate;
	Parameters[14].DefaultType = REG_DWORD;
	Parameters[14].DefaultData = &DefaultSampleRate;
	Parameters[14].DefaultLength = sizeof(ULONG);

	Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_REGISTRY_OPTIONAL;
	Parameters[15].Name = L"CrashOnCtrlScroll";
	Parameters[15].EntryContext = &Settings->CrashOnCtrlScroll;
	Parameters[15].DefaultType = REG_DWORD;
	Parameters[15].DefaultData = &DefaultCrashOnCtrlScroll;
	Parameters[15].DefaultLength = sizeof(ULONG);

	Status = RtlQueryRegistryValues(
		RTL_REGISTRY_ABSOLUTE,
		RegistryPath->Buffer,
		Parameters,
		NULL,
		NULL);

	if (NT_SUCCESS(Status))
	{
		/* Check values */
		if (Settings->KeyboardDataQueueSize < 1)
			Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
		if (Settings->MouseDataQueueSize < 1)
			Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
		if (Settings->NumberOfButtons < 1)
			Settings->NumberOfButtons = DefaultNumberOfButtons;
		if (Settings->PollingIterations < 0x400)
			Settings->PollingIterations = DefaultPollingIterations;
		if (Settings->PollingIterationsMaximum < 0x400)
			Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum;
		if (Settings->ResendIterations < 1)
			Settings->ResendIterations = DefaultResendIterations;
	}
	else if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
	{
		/* Registry path doesn't exist. Set defaults */
		Settings->KeyboardDataQueueSize = DefaultKeyboardDataQueueSize;
		Settings->MouseDataQueueSize = DefaultMouseDataQueueSize;
		Settings->MouseResolution = DefaultMouseResolution;
		Settings->MouseSynchIn100ns = DefaultMouseSynchIn100ns;
		Settings->NumberOfButtons = DefaultNumberOfButtons;
		Settings->PollStatusIterations = DefaultPollStatusIterations;
		Settings->OverrideKeyboardType = DefaultOverrideKeyboardType;
		Settings->OverrideKeyboardSubtype = DefaultOverrideKeyboardSubtype;
		Settings->PollingIterations = DefaultPollingIterations;
		Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum;
		Settings->ResendIterations = DefaultResendIterations;
		Settings->SampleRate = DefaultSampleRate;
		Settings->CrashOnCtrlScroll = DefaultCrashOnCtrlScroll;
		if (!RtlCreateUnicodeString(&Settings->KeyboardDeviceBaseName, DefaultKeyboardDeviceBaseName)
		 || !RtlCreateUnicodeString(&Settings->PointerDeviceBaseName, DefaultPointerDeviceBaseName))
		{
			WARN_(I8042PRT, "RtlCreateUnicodeString() failed\n");
			Status = STATUS_NO_MEMORY;
		}
		else
		{
			Status = STATUS_SUCCESS;
		}
	}

	if (NT_SUCCESS(Status))
	{
		INFO_(I8042PRT, "KeyboardDataQueueSize : 0x%lx\n", Settings->KeyboardDataQueueSize);
		INFO_(I8042PRT, "KeyboardDeviceBaseName : %wZ\n", &Settings->KeyboardDeviceBaseName);
		INFO_(I8042PRT, "MouseDataQueueSize : 0x%lx\n", Settings->MouseDataQueueSize);
		INFO_(I8042PRT, "MouseResolution : 0x%lx\n", Settings->MouseResolution);
		INFO_(I8042PRT, "MouseSynchIn100ns : %lu\n", Settings->MouseSynchIn100ns);
		INFO_(I8042PRT, "NumberOfButtons : 0x%lx\n", Settings->NumberOfButtons);
		INFO_(I8042PRT, "PointerDeviceBaseName : %wZ\n", &Settings->PointerDeviceBaseName);
		INFO_(I8042PRT, "PollStatusIterations : 0x%lx\n", Settings->PollStatusIterations);
		INFO_(I8042PRT, "OverrideKeyboardType : 0x%lx\n", Settings->OverrideKeyboardType);
		INFO_(I8042PRT, "OverrideKeyboardSubtype : 0x%lx\n", Settings->OverrideKeyboardSubtype);
		INFO_(I8042PRT, "PollingIterations : 0x%lx\n", Settings->PollingIterations);
		INFO_(I8042PRT, "PollingIterationsMaximum : %lu\n", Settings->PollingIterationsMaximum);
		INFO_(I8042PRT, "ResendIterations : 0x%lx\n", Settings->ResendIterations);
		INFO_(I8042PRT, "SampleRate : %lu\n", Settings->SampleRate);
	}

	return Status;
}
예제 #21
0
LOCAL void threadRoutine(TThreadDesc *pDesc) {
   if (!pDesc) {
      return;
   }

   int8_t sched = SCHED_OTHER;
   TBaCoreThreadArg *pArg = 0;
   // Wait for the pThread pointer to be assigned
   {
      std::lock_guard<std::mutex> lck(pDesc->mtx);

      // Get the native OS TID
#ifdef __linux
      pDesc->tid = syscall(SYS_gettid);
#elif __WIN32
      pDesc->tid = GetCurrentThreadId();
#endif

      // This means that the thread was destroyed before it could start
      // Inform and return
      if (pDesc->status == eDetached) {
        if (!WARN_("Th(%i:%s): Destroyed before starting",
               pDesc->tid, pDesc->name.c_str())) {
           BASYSLOG(TAG, "Th(%i:%s): Destroyed before starting",
                 pDesc->tid, pDesc->name.c_str());
        }
         return;
      }

      pDesc->status = eRunning;
      // Define the priority and scheduler
      struct sched_param prio;
#ifdef __linux
      prio.__sched_priority = prio2Prio(pDesc->prio);
      // Set the soft real-time scheduler if required
      sched = pDesc->prio > eBaCorePrio_Highest ? SCHED_FIFO : SCHED_OTHER;
#elif __WIN32
      prio.sched_priority = prio2Prio(pDesc->prio);
#endif


      // pThread gets destroyed if the thread destructor is called right after
      // the thread creator.
      // Set thread name, scheduler, and priority
      pthread_t hld = pDesc->pThread->native_handle();
      pthread_setname_np(hld, pDesc->name.c_str());
      pthread_setschedparam(hld, sched, &prio);
      pArg = pDesc->pArg;
   }

   // Call the actual thread entry function /////
   pDesc->routine(pArg);
   // ///////////////////////////////////// /////

   // Check if the thread was detached to either notify of release the descriptor
   if (pDesc->status != eDetached) {
      pDesc->status = eFinished;
      pDesc->cv.notify_all();
   } else {
      // Wait for detach to avoid a race condition
      {
         std::lock_guard<std::mutex> lck(pDesc->mtx);
      }
      delete pDesc;
   }
}
예제 #22
0
파일: hardware.c 프로젝트: Moteesh/reactos
NTSTATUS NTAPI
HwReadWriteData(PCONTROLLER_INFO ControllerInfo,
                BOOLEAN Read,
                UCHAR Unit,
                UCHAR Cylinder,
                UCHAR Head,
                UCHAR Sector,
                UCHAR BytesPerSector,
                UCHAR EndOfTrack,
                UCHAR Gap3Length,
                UCHAR DataLength)
/*
 * FUNCTION: Read or write data to the drive
 * ARGUMENTS:
 *     ControllerInfo: controller to target the read/write request to
 *     Read: TRUE if the device should be read; FALSE if written
 *     Unit: Drive number to target
 *     Cylinder: cylinder to start the read on
 *     Head: head to start the read on
 *     Sector: sector to start the read on (1-based!)
 *     BytesPerSector: sector size constant (hardware.h)
 *     EndOfTrack: Marks the last sector number to read/write on the track
 *     Gap3Length: Gap length for the operation
 *     DataLength: Bytes to read, *unless* BytesPerSector is specified
 * RETURNS:
 *     STATUS_SUCCESS if the operation was successfully queued to the controller
 *     STATUS_UNSUCCESSFUL otherwise
 * NOTES:
 *     - Generates an interrupt
 */
{
    UCHAR Buffer[9];
    int i;

    PAGED_CODE();

    /* Shouldn't be using DataLength in this driver */
    ASSERT(DataLength == 0xff);

    /* Build the command to send */
    if(Read)
        Buffer[0] = COMMAND_READ_DATA;
    else
        Buffer[0] = COMMAND_WRITE_DATA;

    Buffer[0] |= READ_DATA_MFM | READ_DATA_MT;

    Buffer[1] = (Head << COMMAND_HEAD_NUMBER_SHIFT) | Unit;
    Buffer[2] = Cylinder;
    Buffer[3] = Head;
    Buffer[4] = Sector;
    Buffer[5] = BytesPerSector;
    Buffer[6] = EndOfTrack;
    Buffer[7] = Gap3Length;
    Buffer[8] = DataLength;

    /* Send the command */
    for(i = 0; i < 9; i++)
    {
        INFO_(FLOPPY, "HwReadWriteData: Sending a command byte to the FIFO: 0x%x\n", Buffer[i]);

        if(Send_Byte(ControllerInfo, Buffer[i]) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "HwReadWriteData: Unable to write to the FIFO\n");
            return STATUS_UNSUCCESSFUL;
        }
    }

    return STATUS_SUCCESS;
}
예제 #23
0
파일: module.c 프로젝트: Caught/openpliPC
/***********************************************************************
 *           LoadLibraryExA   (KERNEL32)
 */
HMODULE WINAPI LoadLibraryExA(LPCSTR libname, HANDLE hfile, DWORD flags)
{
	WINE_MODREF *wm = 0;
	char path[512];
	char checked[2000];
        int i = -1;

        checked[0] = 0;
	if(!libname)
	{
		SetLastError(ERROR_INVALID_PARAMETER);
		return 0;
	}

	wm=MODULE_FindModule(libname);
	if(wm) return wm->module;

//	if(fs_installed==0)
//	    install_fs();

	for (i = 0; !wm && (i < 2); i++)
	{
	    memset (&path, 0, sizeof (path));

	    if (i == 0) {
	        /* check just original file name */
	        strncpy(path, libname, sizeof(path) - 1);
            } else {
	        /* check default user path */
                snprintf(path, sizeof(path), "%s/%s", win32_def_path, libname);
	    }
	    wm = MODULE_LoadLibraryExA( path, hfile, flags );

	    if (!wm)
	    {
		if (checked[0])
		    strcat(checked, ", ");
		strcat(checked, path);
                checked[1500] = 0;

	    }
	}
	if ( wm )
	{
		if ( !MODULE_DllProcessAttach( wm, NULL ) )
		{
			WARN_(module)("Attach failed for module '%s', \n", libname);
			MODULE_FreeLibrary(wm);
			SetLastError(ERROR_DLL_INIT_FAILED);
			MODULE_RemoveFromList(wm);
			wm = NULL;
		}
	}

	if (!wm)
	    printf("wine/module: Win32 LoadLibrary failed to load: %s\n", checked);

        // remove a few divs in the VP codecs that make trouble
        if (strstr(libname,"vp5vfw.dll") && wm)
        {
          int i;
          if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003930) {
            for (i=0;i<3;i++) ((char*)0x10004e86)[i]=0x90;
            for (i=0;i<3;i++) ((char*)0x10005a23)[i]=0x90;
            for (i=0;i<3;i++) ((char*)0x10005bff)[i]=0x90;
          } else {
            printf("wine/module: Unsupported VP5 version\n");
            return 0;
          }
        }

        if (strstr(libname,"vp6vfw.dll") && wm)
        {
          int i;
          if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003ef0) {
            // looks like VP 6.1.0.2
            for (i=0;i<6;i++) ((char*)0x10007268)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x10007e83)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x1000806a)[i]=0x90;
          } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10004120) {
            // looks like VP 6.2.0.10
            for (i=0;i<6;i++) ((char*)0x10007688)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x100082c3)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x100084aa)[i]=0x90;
          } else if (PE_FindExportedFunction(wm, "DriverProc", TRUE)==(void*)0x10003e70) {
            // looks like VP 6.0.7.3
            for (i=0;i<6;i++) ((char*)0x10007559)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x100081c3)[i]=0x90;
            for (i=0;i<6;i++) ((char*)0x1000839e)[i]=0x90;
          } else {
            printf("wine/module: Unsupported VP6 version\n");
            return 0;
          }
        }

	if (strstr(libname,"QuickTime.qts") && wm)
	{
	    void** ptr;
	    void *dispatch_addr;
	    int i;

//	    dispatch_addr = GetProcAddress(wm->module, "theQuickTimeDispatcher", TRUE);
	    dispatch_addr = PE_FindExportedFunction(wm, "theQuickTimeDispatcher", TRUE);
	    if (dispatch_addr == (void *)0x62924c30)
	    {
	        printf ("wine/module: QuickTime5 DLLs found\n");
		ptr = (void **)0x62b75ca4; // dispatch_ptr
	        for (i=0;i<5;i++)  ((char*)0x6299e842)[i]=0x90; // make_new_region ?
	        for (i=0;i<28;i++) ((char*)0x6299e86d)[i]=0x90; // call__call_CreateCompatibleDC ?
		for (i=0;i<5;i++)  ((char*)0x6299e898)[i]=0x90; // jmp_to_call_loadbitmap ?
	        for (i=0;i<9;i++)  ((char*)0x6299e8ac)[i]=0x90; // call__calls_OLE_shit ?
	        for (i=0;i<106;i++) ((char*)0x62a61b10)[i]=0x90; // disable threads
#if 0
		/* CreateThread callers */
		for (i=0;i<5;i++) ((char*)0x629487c5)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x6294b275)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x629a24b1)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x629afc5a)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x62af799c)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x62af7efe)[i]=0x90;
		for (i=0;i<5;i++) ((char*)0x62afa33e)[i]=0x90;
#endif

#if 0
		/* TerminateQTML fix */
		for (i=0;i<47;i++) ((char*)0x62afa3b8)[i]=0x90; // terminate thread
		for (i=0;i<47;i++) ((char*)0x62af7f78)[i]=0x90; // terminate thread
		for (i=0;i<77;i++) ((char*)0x629a13d5)[i]=0x90;
		((char *)0x6288e0ae)[0] = 0xc3; // font/dc remover
		for (i=0;i<24;i++) ((char*)0x6287a1ad)[i]=0x90; // destroy window
#endif
	    } else if (dispatch_addr == (void *)0x6693b330)
	    {
	        printf ("wine/module: QuickTime6 DLLs found\n");
		ptr = (void **)0x66bb9524; // dispatcher_ptr
		for (i=0;i<5;i++)  ((char *)0x66a730cc)[i]=0x90; // make_new_region
		for (i=0;i<28;i++) ((char *)0x66a730f7)[i]=0x90; // call__call_CreateCompatibleDC
		for (i=0;i<5;i++)  ((char *)0x66a73122)[i]=0x90; // jmp_to_call_loadbitmap
		for (i=0;i<9;i++)  ((char *)0x66a73131)[i]=0x90; // call__calls_OLE_shit
		for (i=0;i<96;i++) ((char *)0x66aac852)[i]=0x90; // disable threads
	    } else if (dispatch_addr == (void *)0x6693c3e0)
	    {
    		printf ("wine/module: QuickTime6.3 DLLs found\n");
		ptr = (void **)0x66bca01c; // dispatcher_ptr
		for (i=0;i<5;i++)  ((char *)0x66a68f6c)[i]=0x90; // make_new_region
		for (i=0;i<28;i++) ((char *)0x66a68f97)[i]=0x90; // call__call_CreateCompatibleDC
		for (i=0;i<5;i++)  ((char *)0x66a68fc2)[i]=0x90; // jmp_to_call_loadbitmap
		for (i=0;i<9;i++)  ((char *)0x66a68fd1)[i]=0x90; // call__calls_OLE_shit
		for (i=0;i<96;i++) ((char *)0x66ab4722)[i]=0x90; // disable threads
	    } else
	    {
	        printf ("wine/module: Unsupported QuickTime version (%p)\n",
			dispatch_addr);
		return 0;
	    }

	    printf ("wine/module: QuickTime.qts patched!!! old entry=%p\n",ptr[0]);

#ifdef EMU_QTX_API
	    wrapper_target=ptr[0];
	    ptr[0]=wrapper;
#endif
	}

	return wm ? wm->module : 0;
}
예제 #24
0
파일: hardware.c 프로젝트: Moteesh/reactos
NTSTATUS NTAPI
HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo)
/*
 * FUNCTION: Get the result of a recalibrate command
 * ARGUMENTS:
 *     ControllerInfo: controller to query
 * RETURNS:
 *     STATUS_SUCCESS if the recalibratewas a success
 *     STATUS_UNSUCCESSFUL otherwise
 * NOTES:
 *     - This function tests the error conditions itself, and boils the
 *       whole thing down to a single SUCCESS or FAILURE result
 *     - Called post-interrupt; does not interrupt
 * TODO
 *     - perhaps handle more status
 */
{
    UCHAR Buffer[2];
    int i;

    PAGED_CODE();

    if(Send_Byte(ControllerInfo, COMMAND_SENSE_INTERRUPT_STATUS) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "HwRecalibrateResult: Unable to write the controller\n");
        return STATUS_UNSUCCESSFUL;
    }

    for(i = 0; i < 2; i++)
        if(Get_Byte(ControllerInfo, &Buffer[i]) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "HwRecalibrateResult: unable to read FIFO\n");
            return STATUS_UNSUCCESSFUL;
        }

    /* Validate  that it did what we told it to */
    INFO_(FLOPPY, "HwRecalibrateResult results: ST0: 0x%x PCN: 0x%x\n", Buffer[0], Buffer[1]);

    /*
     * Buffer[0] = ST0
     * Buffer[1] = PCN
     */

    /* Is the PCN 0? */
    if(Buffer[1] != 0)
    {
        WARN_(FLOPPY, "HwRecalibrateResult: PCN not 0\n");
        return STATUS_UNSUCCESSFUL;
    }

    /* test seek complete */
    if((Buffer[0] & SR0_SEEK_COMPLETE) != SR0_SEEK_COMPLETE)
    {
        WARN_(FLOPPY, "HwRecalibrateResult: Failed to complete the seek\n");
        return STATUS_UNSUCCESSFUL;
    }

    /* Is the equipment check flag set?  Could be no disk in drive... */
    if((Buffer[0] & SR0_EQUIPMENT_CHECK) == SR0_EQUIPMENT_CHECK)
    {
        WARN_(FLOPPY, "HwRecalibrateResult: Seeked to track 0 successfully, but EC is set; returning failure\n");
        return STATUS_UNSUCCESSFUL;
    }

    return STATUS_SUCCESS;
}
예제 #25
0
/***********************************************************************
 *           NE_LoadSegment
 */
BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
{
    SEGTABLEENTRY *pSegTable, *pSeg;
    WORD *pModuleTable;
    WORD count, i, offset, next_offset;
    HMODULE16 module;
    FARPROC16 address = 0;
    HFILE hf;
    DWORD res;
    struct relocation_entry_s *rep, *reloc_entries;
    char *func_name;
    int size;
    char* mem;

    char buffer[256];
    int ordinal, additive;
    unsigned short *sp;

    pSegTable = NE_SEG_TABLE( pModule );
    pSeg = pSegTable + segnum - 1;

    if (pSeg->flags & NE_SEGFLAGS_LOADED)
    {
	/* self-loader ? -> already loaded it */
	if (pModule->flags & NE_FFLAGS_SELFLOAD)
	    return TRUE;

	/* leave, except for DGROUP, as this may be the second instance */
	if (segnum != pModule->dgroup)
            return TRUE;
    }

    if (!pSeg->filepos) return TRUE;  /* No file image, just return */

    pModuleTable = NE_MODULE_TABLE( pModule );

    hf = NE_OpenFile( pModule );
    TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n",
                    segnum, pSeg->hSeg, pSeg->flags );
    SetFilePointer( hf, pSeg->filepos << pModule->alignment, NULL, SEEK_SET );
    if (pSeg->size) size = pSeg->size;
    else size = pSeg->minsize ? pSeg->minsize : 0x10000;
    mem = GlobalLock16(pSeg->hSeg);
    if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
    {
 	/* Implement self-loading segments */
 	SELFLOADHEADER *selfloadheader;
        DWORD oldstack;
        HANDLE hFile32;
        HFILE16 hFile16;

 	selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) );
 	oldstack = NtCurrentTeb()->WOW32Reserved;
 	NtCurrentTeb()->WOW32Reserved = MAKESEGPTR(pModule->self_loading_sel,
                                               0xff00 - sizeof(STACK16FRAME));

	TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=0x%04x,segnum=%d\n",
		pModule->self,hf,segnum );
        DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32,
                         0, FALSE, DUPLICATE_SAME_ACCESS );
        hFile16 = Win32HandleToDosFileHandle( hFile32 );
 	pSeg->hSeg = NE_CallTo16_word_www( selfloadheader->LoadAppSeg,
                                           pModule->self, hFile16, segnum );
	TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg);
        _lclose16( hFile16 );
 	NtCurrentTeb()->WOW32Reserved = oldstack;
    }
    else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
        ReadFile(hf, mem, size, &res, NULL);
    else {
      /*
	 The following bit of code for "iterated segments" was written without
	 any documentation on the format of these segments. It seems to work,
	 but may be missing something. If you have any doc please either send
	 it to me or fix the code yourself. [email protected]
      */
      char* buff = HeapAlloc(GetProcessHeap(), 0, size);
      char* curr = buff;

      if(buff == NULL) {
          WARN_(dll)("Memory exausted!");
          return FALSE;
      }

      ReadFile(hf, buff, size, &res, NULL);
      while(curr < buff + size) {
	unsigned int rept = *((short*) curr);
	curr = (char *)(((short*) curr) + 1);
	unsigned int len = *((short*) curr);
	curr = (char *)(((short*) curr) + 1);
	for(; rept > 0; rept--) {
	  char* bytes = curr;
	  unsigned int byte;
	  for(byte = 0; byte < len; byte++)
	    *mem++ = *bytes++;
	}
	curr += len;
      }
      HeapFree(GetProcessHeap(), 0, buff);
    }

    pSeg->flags |= NE_SEGFLAGS_LOADED;

    /* Perform exported function prolog fixups */
    NE_FixupSegmentPrologs( pModule, segnum );

    if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
        return TRUE;  /* No relocation data, we are done */

    ReadFile(hf, &count, sizeof(count), &res, NULL);
    if (!count) return TRUE;

    TRACE_(fixup)("Fixups for %.*s, segment %d, hSeg %04x\n",
                   *((BYTE *)pModule + pModule->name_table),
                   (char *)pModule + pModule->name_table + 1,
                   segnum, pSeg->hSeg );
    TRACE_(segment)("Fixups for %.*s, segment %d, hSeg %04x\n",
                   *((BYTE *)pModule + pModule->name_table),
                   (char *)pModule + pModule->name_table + 1,
                   segnum, pSeg->hSeg );

    reloc_entries = (struct relocation_entry_s *)HeapAlloc(GetProcessHeap(), 0, count * sizeof(struct relocation_entry_s));
    if(reloc_entries == NULL) {
        WARN_(fixup)("Not enough memory for relocation entries!");
        return FALSE;
    }
    if (!ReadFile( hf, reloc_entries, count * sizeof(struct relocation_entry_s), &res, NULL) ||
        (res != count * sizeof(struct relocation_entry_s)))
    {
        WARN_(fixup)("Unable to read relocation information\n" );
        return FALSE;
    }

    /*
     * Go through the relocation table one entry at a time.
     */
    rep = reloc_entries;
    for (i = 0; i < count; i++, rep++)
    {
	/*
	 * Get the target address corresponding to this entry.
	 */

	/* If additive, there is no target chain list. Instead, add source
	   and target */
	additive = rep->relocation_type & NE_RELFLAG_ADDITIVE;
	rep->relocation_type &= 0x3;

	switch (rep->relocation_type)
	{
	  case NE_RELTYPE_ORDINAL:
            module = pModuleTable[rep->target1-1];
	    ordinal = rep->target2;
            address = NE_GetEntryPoint( module, ordinal );
            if (!address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                if (!pTarget)
                    WARN_(module)("Module not found: %04x, reference %d of module %*.*s\n",
                             module, rep->target1,
                             *((BYTE *)pModule + pModule->name_table),
                             *((BYTE *)pModule + pModule->name_table),
                             (char *)pModule + pModule->name_table + 1 );
                else
                {
                    ERR_(fixup)("No implementation for %.*s.%d, setting to 0xdeadbeef\n",
                            *((BYTE *)pTarget + pTarget->name_table),
                            (char *)pTarget + pTarget->name_table + 1,
                            ordinal );
                    address = (FARPROC16)0xdeadbeef;
                }
            }
            if (TRACE_ON(fixup))
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE_(fixup)("%d: %.*s.%d=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->name_table),
                       (char *)pTarget + pTarget->name_table + 1,
                       ordinal, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
	    break;

	  case NE_RELTYPE_NAME:
            module = pModuleTable[rep->target1-1];
            func_name = (char *)pModule + pModule->import_table + rep->target2;
            memcpy( buffer, func_name+1, *func_name );
            buffer[(BYTE)*func_name] = '\0';
            func_name = buffer;
            ordinal = NE_GetOrdinal( module, func_name );
            address = NE_GetEntryPoint( module, ordinal );

            if (ERR_ON(fixup) && !address)
            {
                NE_MODULE *pTarget = NE_GetPtr( module );
                ERR_(fixup)("No implementation for %.*s.%s, setting to 0xdeadbeef\n",
                    *((BYTE *)pTarget + pTarget->name_table),
                    (char *)pTarget + pTarget->name_table + 1, func_name );
            }
            if (!address) address = (FARPROC16) 0xdeadbeef;
            if (TRACE_ON(fixup))
            {
	        NE_MODULE *pTarget = NE_GetPtr( module );
                TRACE_(fixup)("%d: %.*s.%s=%04x:%04x %s\n", i + 1,
                       *((BYTE *)pTarget + pTarget->name_table),
                       (char *)pTarget + pTarget->name_table + 1,
                       func_name, HIWORD(address), LOWORD(address),
                       NE_GetRelocAddrName( rep->address_type, additive ) );
            }
	    break;

	  case NE_RELTYPE_INTERNAL:
	    if ((rep->target1 & 0xff) == 0xff)
	    {
		address  = NE_GetEntryPoint( pModule->self, rep->target2 );
	    }
	    else
	    {
                address = (FARPROC16)MAKESEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 );
	    }

	    TRACE_(fixup)("%d: %04x:%04x %s\n",
                   i + 1, HIWORD(address), LOWORD(address),
                   NE_GetRelocAddrName( rep->address_type, additive ) );
	    break;

	  case NE_RELTYPE_OSFIXUP:
	    /* Relocation type 7:
	     *
	     *    These appear to be used as fixups for the Windows
	     * floating point emulator.  Let's just ignore them and
	     * try to use the hardware floating point.  Linux should
	     * successfully emulate the coprocessor if it doesn't
	     * exist.
	     */
	    TRACE_(fixup)("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n",
                   i + 1, rep->relocation_type, rep->offset,
                   rep->target1, rep->target2,
                   NE_GetRelocAddrName( rep->address_type, additive ) );
	    continue;
	}

	offset  = rep->offset;

        /* Apparently, high bit of address_type is sometimes set; */
        /* we ignore it for now */
	if (rep->address_type > NE_RADDR_OFFSET32)
        {
            char module[10];
            GetModuleName16( pModule->self, module, sizeof(module) );
            ERR_(fixup)("WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
                 module, rep->address_type );
        }

        if (additive)
        {
            sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
            TRACE_(fixup)("    %04x:%04x\n", offset, *sp );
            switch (rep->address_type & 0x7f)
            {
            case NE_RADDR_LOWBYTE:
                *(BYTE *)sp += LOBYTE((int)address);
                break;
            case NE_RADDR_OFFSET16:
		*sp += LOWORD(address);
                break;
            case NE_RADDR_POINTER32:
		*sp += LOWORD(address);
		*(sp+1) = HIWORD(address);
                break;
            case NE_RADDR_SELECTOR:
		/* Borland creates additive records with offset zero. Strange, but OK */
                if (*sp)
                    ERR_(fixup)("Additive selector to %04x.Please report\n",*sp);
		else
                    *sp = HIWORD(address);
                break;
            default:
                goto unknown;
            }
        }
        else  /* non-additive fixup */
        {
            do
            {
                sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) );
                next_offset = *sp;
                TRACE_(fixup)("    %04x:%04x\n", offset, *sp );
                switch (rep->address_type & 0x7f)
                {
                case NE_RADDR_LOWBYTE:
                    *(BYTE *)sp = LOBYTE((int)address);
                    break;
                case NE_RADDR_OFFSET16:
                    *sp = LOWORD(address);
                    break;
                case NE_RADDR_POINTER32:
                    *(FARPROC16 *)sp = address;
                    break;
                case NE_RADDR_SELECTOR:
                    *sp = SELECTOROF(address);
                    break;
                default:
                    goto unknown;
                }
                if (next_offset == offset) break;  /* avoid infinite loop */
                if (next_offset >= GlobalSize16(pSeg->hSeg)) break;
                offset = next_offset;
            } while (offset != 0xffff);
        }
    }

    HeapFree(GetProcessHeap(), 0, reloc_entries);
    return TRUE;

unknown:
    WARN_(fixup)("WARNING: %d: unknown ADDR TYPE %d,  "
         "TYPE %d,  OFFSET %04x,  TARGET %04x %04x\n",
         i + 1, rep->address_type, rep->relocation_type,
         rep->offset, rep->target1, rep->target2);
    HeapFree(GetProcessHeap(), 0, reloc_entries);
    return FALSE;
}
예제 #26
0
static VOID
i8042DetectMouse(
    IN PPORT_DEVICE_EXTENSION DeviceExtension)
{
    NTSTATUS Status;
    UCHAR Value;
    UCHAR ExpectedReply[] = { MOUSE_ACK, 0xAA };
    UCHAR ReplyByte;

    /* First do a mouse line test */
    if (i8042Write(DeviceExtension, DeviceExtension->ControlPort, MOUSE_LINE_TEST))
    {
        Status = i8042ReadDataWait(DeviceExtension, &Value);

        if (!NT_SUCCESS(Status) || Value != 0)
        {
            WARN_(I8042PRT, "Mouse line test failed\n");
            goto failure;
        }
    }

    /* Now reset the mouse */
    i8042Flush(DeviceExtension);

    if(!i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE))
    {
        WARN_(I8042PRT, "Failed to write reset command to mouse\n");
        goto failure;
    }

    /* The implementation of the "Mouse Reset" command differs much from chip to chip.

       By default, the first byte is an ACK, when the mouse is plugged in and working and NACK when it's not.
       On success, the next bytes are 0xAA and 0x00.

       But on some systems (like ECS K7S5A Pro, SiS 735 chipset), we always get an ACK and 0xAA.
       Only the last byte indicates, whether a mouse is plugged in.
       It is either sent or not, so there is no byte, which indicates a failure here.

       After the Mouse Reset command was issued, it usually takes some time until we get a response.
       So get the first two bytes in a loop. */
    for (ReplyByte = 0;
         ReplyByte < sizeof(ExpectedReply) / sizeof(ExpectedReply[0]);
         ReplyByte++)
    {
        ULONG Counter = 500;

        do
        {
            Status = i8042ReadDataWait(DeviceExtension, &Value);

            if(!NT_SUCCESS(Status))
            {
                /* Wait some time before trying again */
                KeStallExecutionProcessor(50);
            }
        } while (Status == STATUS_IO_TIMEOUT && Counter--);

        if (!NT_SUCCESS(Status))
        {
            WARN_(I8042PRT, "No ACK after mouse reset, status 0x%08lx\n", Status);
            goto failure;
        }
        else if (Value != ExpectedReply[ReplyByte])
        {
            WARN_(I8042PRT, "Unexpected reply: 0x%02x (expected 0x%02x)\n", Value, ExpectedReply[ReplyByte]);
            goto failure;
        }
    }

    /* Finally get the third byte, but only try it one time (see above).
       Otherwise this takes around 45 seconds on a K7S5A Pro, when no mouse is plugged in. */
    Status = i8042ReadDataWait(DeviceExtension, &Value);

    if(!NT_SUCCESS(Status))
    {
        WARN_(I8042PRT, "Last byte was not transmitted after mouse reset, status 0x%08lx\n", Status);
        goto failure;
    }
    else if(Value != 0x00)
    {
        WARN_(I8042PRT, "Last byte after mouse reset was not 0x00, but 0x%02x\n", Value);
        goto failure;
    }

    DeviceExtension->Flags |= MOUSE_PRESENT;
    INFO_(I8042PRT, "Mouse detected\n");
    return;

failure:
    /* There is probably no mouse present. On some systems,
       the probe locks the entire keyboard controller. Let's
       try to get access to the keyboard again by sending a
       reset */
    i8042Flush(DeviceExtension);
    i8042Write(DeviceExtension, DeviceExtension->ControlPort, CTRL_SELF_TEST);
    i8042ReadDataWait(DeviceExtension, &Value);
    i8042Flush(DeviceExtension);

    INFO_(I8042PRT, "Mouse not detected\n");
}
예제 #27
0
/*
 * Runs the keyboard IOCTL dispatch.
 */
NTSTATUS NTAPI
i8042KbdDeviceControl(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp)
{
	PIO_STACK_LOCATION Stack;
	PI8042_KEYBOARD_EXTENSION DeviceExtension;
	NTSTATUS Status;

	Stack = IoGetCurrentIrpStackLocation(Irp);
	Irp->IoStatus.Information = 0;
	DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension;

	switch (Stack->Parameters.DeviceIoControl.IoControlCode)
	{
		case IOCTL_GET_SYS_BUTTON_CAPS:
		{
			/* Part of GUID_DEVICE_SYS_BUTTON interface */
			PULONG pCaps;
			TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_CAPS\n");

			if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				pCaps = (PULONG)Irp->AssociatedIrp.SystemBuffer;
				*pCaps = DeviceExtension->NewCaps;
				DeviceExtension->ReportedCaps = DeviceExtension->NewCaps;
				Irp->IoStatus.Information = sizeof(ULONG);
				Status = STATUS_SUCCESS;
			}
			break;
		}
		case IOCTL_GET_SYS_BUTTON_EVENT:
		{
			/* Part of GUID_DEVICE_SYS_BUTTON interface */
			PIRP WaitingIrp;
			TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_EVENT\n");

			if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))
				Status = STATUS_INVALID_PARAMETER;
			else
			{
				WaitingIrp = InterlockedCompareExchangePointer(
					(PVOID)&DeviceExtension->PowerIrp,
					Irp,
					NULL);
				/* Check if an Irp is already pending */
				if (WaitingIrp)
				{
					/* Unable to have a 2nd pending IRP for this IOCTL */
					WARN_(I8042PRT, "Unable to pend a second IRP for IOCTL_GET_SYS_BUTTON_EVENT\n");
					Status = STATUS_INVALID_PARAMETER;
					Irp->IoStatus.Status = Status;
					IoCompleteRequest(Irp, IO_NO_INCREMENT);
				}
				else
				{
					ULONG PowerKey;
					PowerKey = InterlockedExchange((PLONG)&DeviceExtension->LastPowerKey, 0);
					if (PowerKey != 0)
					{
						(VOID)InterlockedCompareExchangePointer((PVOID)&DeviceExtension->PowerIrp, NULL, Irp);
						*(PULONG)Irp->AssociatedIrp.SystemBuffer = PowerKey;
						Status = STATUS_SUCCESS;
						Irp->IoStatus.Status = Status;
						Irp->IoStatus.Information = sizeof(ULONG);
						IoCompleteRequest(Irp, IO_NO_INCREMENT);
					}
					else
					{
						TRACE_(I8042PRT, "Pending IOCTL_GET_SYS_BUTTON_EVENT\n");
						Status = STATUS_PENDING;
						Irp->IoStatus.Status = Status;
						IoMarkIrpPending(Irp);
					}
				}
				return Status;
			}
			break;
		}
		default:
		{
			ERR_(I8042PRT, "IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n",
				Stack->Parameters.DeviceIoControl.IoControlCode);
			ASSERT(FALSE);
			return ForwardIrpAndForget(DeviceObject, Irp);
		}
	}

	Irp->IoStatus.Status = Status;
	if (Status == STATUS_PENDING)
		IoMarkIrpPending(Irp);
	else
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

	return Status;
}
예제 #28
0
static NTSTATUS
i8042ConnectMouseInterrupt(
    IN PI8042_MOUSE_EXTENSION DeviceExtension)
{
    PPORT_DEVICE_EXTENSION PortDeviceExtension;
    KIRQL DirqlMax;
    NTSTATUS Status;

    TRACE_(I8042PRT, "i8042ConnectMouseInterrupt()\n");

    Status = i8042MouInitialize(DeviceExtension);
    if (!NT_SUCCESS(Status))
        return Status;

    PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
    DirqlMax = MAX(
        PortDeviceExtension->KeyboardInterrupt.Dirql,
        PortDeviceExtension->MouseInterrupt.Dirql);

    INFO_(I8042PRT, "MouseInterrupt.Vector         %lu\n",
        PortDeviceExtension->MouseInterrupt.Vector);
    INFO_(I8042PRT, "MouseInterrupt.Dirql          %lu\n",
        PortDeviceExtension->MouseInterrupt.Dirql);
    INFO_(I8042PRT, "MouseInterrupt.DirqlMax       %lu\n",
        DirqlMax);
    INFO_(I8042PRT, "MouseInterrupt.InterruptMode  %s\n",
        PortDeviceExtension->MouseInterrupt.InterruptMode == LevelSensitive ? "LevelSensitive" : "Latched");
    INFO_(I8042PRT, "MouseInterrupt.ShareInterrupt %s\n",
        PortDeviceExtension->MouseInterrupt.ShareInterrupt ? "yes" : "no");
    INFO_(I8042PRT, "MouseInterrupt.Affinity       0x%lx\n",
        PortDeviceExtension->MouseInterrupt.Affinity);
    Status = IoConnectInterrupt(
        &PortDeviceExtension->MouseInterrupt.Object,
        i8042MouInterruptService,
        DeviceExtension, &PortDeviceExtension->SpinLock,
        PortDeviceExtension->MouseInterrupt.Vector, PortDeviceExtension->MouseInterrupt.Dirql, DirqlMax,
        PortDeviceExtension->MouseInterrupt.InterruptMode, PortDeviceExtension->MouseInterrupt.ShareInterrupt,
        PortDeviceExtension->MouseInterrupt.Affinity, FALSE);
    if (!NT_SUCCESS(Status))
    {
        WARN_(I8042PRT, "IoConnectInterrupt() failed with status 0x%08x\n", Status);
        goto cleanup;
    }

    if (DirqlMax == PortDeviceExtension->MouseInterrupt.Dirql)
        PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->MouseInterrupt.Object;

    PortDeviceExtension->Flags |= MOUSE_INITIALIZED;
    Status = STATUS_SUCCESS;

cleanup:
    if (!NT_SUCCESS(Status))
    {
        PortDeviceExtension->Flags &= ~MOUSE_INITIALIZED;
        if (PortDeviceExtension->MouseInterrupt.Object)
        {
            IoDisconnectInterrupt(PortDeviceExtension->MouseInterrupt.Object);
            PortDeviceExtension->HighestDIRQLInterrupt = PortDeviceExtension->KeyboardInterrupt.Object;
        }
    }
    return Status;
}
예제 #29
0
BOOLEAN NTAPI
i8042KbdInterruptService(
	IN PKINTERRUPT Interrupt,
	PVOID Context)
{
	PI8042_KEYBOARD_EXTENSION DeviceExtension;
	PPORT_DEVICE_EXTENSION PortDeviceExtension;
	PKEYBOARD_INPUT_DATA InputData;
	ULONG Counter;
	UCHAR PortStatus = 0, Output = 0;
	BOOLEAN ToReturn = FALSE;
	NTSTATUS Status;

	UNREFERENCED_PARAMETER(Interrupt);

	DeviceExtension = (PI8042_KEYBOARD_EXTENSION)Context;
	PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension;
	InputData = DeviceExtension->KeyboardBuffer + DeviceExtension->KeysInBuffer;
	Counter = PortDeviceExtension->Settings.PollStatusIterations;

	while (Counter)
	{
		Status = i8042ReadStatus(PortDeviceExtension, &PortStatus);
		if (!NT_SUCCESS(Status))
		{
			WARN_(I8042PRT, "i8042ReadStatus() failed with status 0x%08lx\n", Status);
			return FALSE;
		}
		Status = i8042ReadKeyboardData(PortDeviceExtension, &Output);
		if (NT_SUCCESS(Status))
			break;
		KeStallExecutionProcessor(1);
		Counter--;
	}
	if (Counter == 0)
	{
		WARN_(I8042PRT, "Spurious i8042 keyboard interrupt\n");
		return FALSE;
	}

	INFO_(I8042PRT, "Got: 0x%02x\n", Output);

	if (PortDeviceExtension->Settings.CrashOnCtrlScroll)
	{
		/* Test for CTRL + SCROLL LOCK twice */
		static const UCHAR ScanCodes[] = { 0x1d, 0x46, 0xc6, 0x46, 0 };

		if (Output == ScanCodes[DeviceExtension->ComboPosition])
		{
			DeviceExtension->ComboPosition++;
			if (ScanCodes[DeviceExtension->ComboPosition] == 0)
				KeBugCheck(MANUALLY_INITIATED_CRASH);
		}
		else if (Output == 0xfa)
		{
		    /* Ignore ACK */
		}
		else if (Output == ScanCodes[0])
			DeviceExtension->ComboPosition = 1;
		else
			DeviceExtension->ComboPosition = 0;

		/* Test for TAB + key combination */
		if (InputData->MakeCode == 0x0F)
			DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK);
		else if (DeviceExtension->TabPressed)
		{
			DeviceExtension->TabPressed = FALSE;

            /* Check which action to do */
            if (InputData->MakeCode == 0x25)
            {
                /* k - Breakpoint */
                DbgBreakPoint();
            }
            else if (InputData->MakeCode == 0x30)
            {
                /* b - Bugcheck */
                KeBugCheck(MANUALLY_INITIATED_CRASH);
            }
            else
            {
			    /* Send request to the kernel debugger.
			     * Unknown requests will be ignored. */
			    KdSystemDebugControl(' soR',
			                         (PVOID)(ULONG_PTR)InputData->MakeCode,
			                         0,
			                         NULL,
			                         0,
			                         NULL,
			                         KernelMode);
            }
		}
	}

	if (i8042KbdCallIsrHook(DeviceExtension, PortStatus, Output, &ToReturn))
		return ToReturn;

	if (i8042PacketIsr(PortDeviceExtension, Output))
	{
		if (PortDeviceExtension->PacketComplete)
		{
			TRACE_(I8042PRT, "Packet complete\n");
			KeInsertQueueDpc(&DeviceExtension->DpcKeyboard, NULL, NULL);
		}
		TRACE_(I8042PRT, "Irq eaten by packet\n");
		return TRUE;
	}

	TRACE_(I8042PRT, "Irq is keyboard input\n");

	if (DeviceExtension->KeyboardScanState == Normal)
	{
		switch (Output)
		{
			case 0xe0:
				DeviceExtension->KeyboardScanState = GotE0;
				return TRUE;
			case 0xe1:
				DeviceExtension->KeyboardScanState = GotE1;
				return TRUE;
			default:
				break;
		}
	}

	/* Update InputData */
	InputData->Flags = 0;
	switch (DeviceExtension->KeyboardScanState)
	{
		case GotE0:
			InputData->Flags |= KEY_E0;
			break;
		case GotE1:
			InputData->Flags |= KEY_E1;
			break;
		default:
			break;
	}
	DeviceExtension->KeyboardScanState = Normal;
	if (Output & 0x80)
		InputData->Flags |= KEY_BREAK;
	else
		InputData->Flags |= KEY_MAKE;
	InputData->MakeCode = Output & 0x7f;
	InputData->Reserved = 0;

	DeviceExtension->KeyboardHook.QueueKeyboardPacket(DeviceExtension->KeyboardHook.CallContext);

	return TRUE;
}
예제 #30
0
VOID NTAPI
ReadWritePassive(PDRIVE_INFO DriveInfo, PIRP Irp)
/*
 * FUNCTION: Handle the first phase of a read or write IRP
 * ARGUMENTS:
 *     DeviceObject: DeviceObject that is the target of the IRP
 *     Irp: IRP to process
 * RETURNS:
 *     STATUS_VERIFY_REQUIRED if the media has changed and we need the filesystems to re-synch
 *     STATUS_SUCCESS otherwise
 * NOTES:
 *     - Must be called at PASSIVE_LEVEL
 *     - This function is about 250 lines longer than I wanted it to be.  Sorry.
 *
 * DETAILS:
 *  This routine manages the whole process of servicing a read or write request.  It goes like this:
 *    1) Check the DO_VERIFY_VOLUME flag and return if it's set
 *    2) Check the disk change line and notify the OS if it's set and return
 *    3) Detect the media if we haven't already
 *    4) Set up DiskByteOffset, Length, and WriteToDevice parameters
 *    5) Get DMA map registers
 *    6) Then, in a loop for each track, until all bytes are transferred:
 *      a) Compute the current CHS to set the read/write head to
 *      b) Seek to that spot
 *      c) Compute the last sector to transfer on that track
 *      d) Map the transfer through DMA
 *      e) Send the read or write command to the controller
 *      f) Read the results of the command
 */
{
    PDEVICE_OBJECT DeviceObject = DriveInfo->DeviceObject;
    PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
    BOOLEAN WriteToDevice;
    ULONG Length;
    ULONG DiskByteOffset;
    KIRQL OldIrql;
    NTSTATUS Status;
    BOOLEAN DiskChanged;
    ULONG_PTR TransferByteOffset;
    UCHAR Gap;

    PAGED_CODE();

    TRACE_(FLOPPY, "ReadWritePassive called to %s 0x%x bytes from offset 0x%x\n",
           (Stack->MajorFunction == IRP_MJ_READ ? "read" : "write"),
           (Stack->MajorFunction == IRP_MJ_READ ? Stack->Parameters.Read.Length : Stack->Parameters.Write.Length),
           (Stack->MajorFunction == IRP_MJ_READ ? Stack->Parameters.Read.ByteOffset.u.LowPart :
            Stack->Parameters.Write.ByteOffset.u.LowPart));

    /* Default return codes */
    Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
    Irp->IoStatus.Information = 0;

    /*
     * Check to see if the volume needs to be verified.  If so,
     * we can get out of here quickly.
     */
    if(DeviceObject->Flags & DO_VERIFY_VOLUME && !(Stack->Flags & SL_OVERRIDE_VERIFY_VOLUME))
    {
        INFO_(FLOPPY, "ReadWritePassive(): DO_VERIFY_VOLUME set; Completing with  STATUS_VERIFY_REQUIRED\n");
        Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return;
    }

    /*
     * Check the change line, and if it's set, return
     */
    StartMotor(DriveInfo);
    if(HwDiskChanged(DeviceObject->DeviceExtension, &DiskChanged) != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ReadWritePassive(): unable to detect disk change; Completing with STATUS_UNSUCCESSFUL\n");
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        StopMotor(DriveInfo->ControllerInfo);
        return;
    }

    if(DiskChanged)
    {
        INFO_(FLOPPY, "ReadWritePhase1(): signalling media changed; Completing with STATUS_MEDIA_CHANGED\n");

        /* The following call sets IoStatus.Status and IoStatus.Information */
        SignalMediaChanged(DeviceObject, Irp);

        /*
         * Guessing at something... see ioctl.c for more info
         */
        if(ResetChangeFlag(DriveInfo) == STATUS_NO_MEDIA_IN_DEVICE)
            Irp->IoStatus.Status = STATUS_NO_MEDIA_IN_DEVICE;

        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        StopMotor(DriveInfo->ControllerInfo);
        return;
    }

    /*
     * Figure out the media type, if we don't know it already
     */
    if(DriveInfo->DiskGeometry.MediaType == Unknown)
    {
        if(RWDetermineMediaType(DriveInfo) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "ReadWritePassive(): unable to determine media type; completing with STATUS_UNSUCCESSFUL\n");
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            StopMotor(DriveInfo->ControllerInfo);
            return;
        }

        if(DriveInfo->DiskGeometry.MediaType == Unknown)
        {
            WARN_(FLOPPY, "ReadWritePassive(): Unknown media in drive; completing with STATUS_UNRECOGNIZED_MEDIA\n");
            Irp->IoStatus.Status = STATUS_UNRECOGNIZED_MEDIA;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            StopMotor(DriveInfo->ControllerInfo);
            return;
        }
    }

    /* Set up parameters for read or write */
    if(Stack->MajorFunction == IRP_MJ_READ)
    {
        Length = Stack->Parameters.Read.Length;
        DiskByteOffset = Stack->Parameters.Read.ByteOffset.u.LowPart;
        WriteToDevice = FALSE;
    }
    else
    {
        Length = Stack->Parameters.Write.Length;
        DiskByteOffset = Stack->Parameters.Write.ByteOffset.u.LowPart;
        WriteToDevice = TRUE;
    }

    /*
     * FIXME:
     *   FloppyDeviceData.ReadWriteGapLength specify the value for the physical drive.
     *   We should set this value depend on the format of the inserted disk and possible
     *   depend on the request (read or write). A value of 0 results in one rotation
     *   between the sectors (7.2sec for reading a track).
     */
    Gap = DriveInfo->FloppyDeviceData.ReadWriteGapLength;

    /*
     * Set up DMA transfer
     *
     * This is as good of a place as any to document something that used to confuse me
     * greatly (and I even wrote some of the kernel's DMA code, so if it confuses me, it
     * probably confuses at least a couple of other people too).
     *
     * MmGetMdlVirtualAddress() returns the virtal address, as mapped in the buffer's original
     * process context, of the MDL.  In other words:  say you start with a buffer at address X, then
     * you build an MDL out of that buffer called Mdl. If you call MmGetMdlVirtualAddress(Mdl), it
     * will return X.
     *
     * There are two parameters that the function looks at to produce X again, given the MDL:  the
     * first is the StartVa, which is the base virtual address of the page that the buffer starts
     * in.  If your buffer's virtual address is 0x12345678, StartVa will be 0x12345000, assuming 4K pages
     * (which is (almost) always the case on x86).  Note well: this address is only valid in the
     * process context that you initially built the MDL from.  The physical pages that make up
     * the MDL might perhaps be mapped in other process contexts too (or even in the system space,
     * above 0x80000000 (default; 0xc0000000 on current Odyssey or /3GB Windows)), but it will
     * (possibly) be mapped at a different address.
     *
     * The second parameter is the ByteOffset.  Given an original buffer address of 0x12345678,
     * the ByteOffset would be 0x678.  Because MDLs can only describe full pages (and therefore
     * StartVa always points to the start address of a page), the ByteOffset must be used to
     * find the real start of the buffer.
     *
     * In general, if you add the StartVa and ByteOffset together, you get back your original
     * buffer pointer, which you are free to use if you're sure you're in the right process
     * context.  You could tell by accessing the (hidden and not-to-be-used) Process member of
     * the MDL, but in general, if you have to ask whether or not you are in the right context,
     * then you shouldn't be using this address for anything anyway.  There are also security implications
     * (big ones, really, I wouldn't kid about this) to directly accessing a user's buffer by VA, so
     * Don't Do That.
     *
     * There is a somewhat weird but very common use of the virtual address associated with a MDL
     * that pops up often in the context of DMA.  DMA APIs (particularly MapTransfer()) need to
     * know where the memory is that they should DMA into and out of.  This memory is described
     * by a MDL.  The controller eventually needs to know a physical address on the host side,
     * which is generally a 32-bit linear address (on x86), and not just a page address.  Therefore,
     * the DMA APIs look at the ByteOffset field of the MDL to reconstruct the real address that
     * should be programmed into the DMA controller.
     *
     * It is often the case that a transfer needs to be broken down over more than one DMA operation,
     * particularly when it is a big transfer and the HAL doesn't give you enough map registers
     * to map the whole thing at once.  Therefore, the APIs need a way to tell how far into the MDL
     * they should look to transfer the next chunk of bytes.  Now, Microsoft could have designed
     * MapTransfer to take a  "MDL offset" argument, starting with 0, for how far into the buffer to
     * start, but it didn't.  Instead, MapTransfer asks for the virtual address of the MDL as an "index" into
     * the MDL.  The way it computes how far into the page to start the transfer is by masking off all but
     * the bottom 12 bits (on x86) of the number you supply as the CurrentVa and using *that* as the
     * ByteOffset instead of the one in the MDL.  (OK, this varies a bit by OS and version, but this
     * is the effect).
     *
     * In other words, you get a number back from MmGetMdlVirtualAddress that represents the start of your
     * buffer, and you pass it to the first MapTransfer call.  Then, for each successive operation
     * on the same buffer, you increment that address to point to the next spot in the MDL that
     * you want to DMA to/from.  The fact that the virtual address you're manipulating is probably not
     * mapped into the process context that you're running in is irrelevant, since it's only being
     * used to index into the MDL.
     */

    /* Get map registers for DMA */
    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
    Status = IoAllocateAdapterChannel(DriveInfo->ControllerInfo->AdapterObject, DeviceObject,
                                      DriveInfo->ControllerInfo->MapRegisters, MapRegisterCallback, DriveInfo->ControllerInfo);
    KeLowerIrql(OldIrql);

    if(Status != STATUS_SUCCESS)
    {
        WARN_(FLOPPY, "ReadWritePassive(): unable allocate an adapter channel; completing with STATUS_UNSUCCESSFUL\n");
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        StopMotor(DriveInfo->ControllerInfo);
        return ;
    }


    /*
     * Read from (or write to) the device
     *
     * This has to be called in a loop, as you can only transfer data to/from a single track at
     * a time.
     */
    TransferByteOffset = 0;
    while(TransferByteOffset < Length)
    {
        UCHAR Cylinder;
        UCHAR Head;
        UCHAR StartSector;
        ULONG CurrentTransferBytes;
        UCHAR CurrentTransferSectors;

        INFO_(FLOPPY, "ReadWritePassive(): iterating in while (TransferByteOffset = 0x%x of 0x%x total) - allocating %d registers\n",
              TransferByteOffset, Length, DriveInfo->ControllerInfo->MapRegisters);

        KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);

        /*
         * Compute starting CHS
         */
        if(RWComputeCHS(DriveInfo, DiskByteOffset+TransferByteOffset, &Cylinder, &Head, &StartSector) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "ReadWritePassive(): unable to compute CHS; completing with STATUS_UNSUCCESSFUL\n");
            RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            StopMotor(DriveInfo->ControllerInfo);
            return;
        }

        /*
         * Seek to the right track
         */
        if(!DriveInfo->ControllerInfo->ImpliedSeeks)
        {
            if(RWSeekToCylinder(DriveInfo, Cylinder) != STATUS_SUCCESS)
            {
                WARN_(FLOPPY, "ReadWritePassive(): unable to seek; completing with STATUS_UNSUCCESSFUL\n");
                RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
                IoCompleteRequest(Irp, IO_NO_INCREMENT);
                StopMotor(DriveInfo->ControllerInfo);
                return ;
            }
        }

        /*
         * Compute last sector
         *
         * We can only ask for a transfer up to the end of the track.  Then we have to re-seek and do more.
         * TODO: Support the MT bit
         */
        INFO_(FLOPPY, "ReadWritePassive(): computing number of sectors to transfer (StartSector 0x%x): ", StartSector);

        /* 1-based sector number */
        if( (((DriveInfo->DiskGeometry.TracksPerCylinder - Head) * DriveInfo->DiskGeometry.SectorsPerTrack - StartSector) + 1 ) <
                (Length - TransferByteOffset) / DriveInfo->DiskGeometry.BytesPerSector)
        {
            CurrentTransferSectors = (UCHAR)((DriveInfo->DiskGeometry.TracksPerCylinder - Head) * DriveInfo->DiskGeometry.SectorsPerTrack - StartSector) + 1;
        }
        else
        {
            CurrentTransferSectors = (UCHAR)((Length - TransferByteOffset) / DriveInfo->DiskGeometry.BytesPerSector);
        }

        INFO_(FLOPPY, "0x%x\n", CurrentTransferSectors);

        CurrentTransferBytes = CurrentTransferSectors * DriveInfo->DiskGeometry.BytesPerSector;

        /*
         * Adjust to map registers
         * BUG: Does this take into account page crossings?
         */
        INFO_(FLOPPY, "ReadWritePassive(): Trying to transfer 0x%x bytes\n", CurrentTransferBytes);

        ASSERT(CurrentTransferBytes);

        if(BYTES_TO_PAGES(CurrentTransferBytes) > DriveInfo->ControllerInfo->MapRegisters)
        {
            CurrentTransferSectors = (UCHAR)((DriveInfo->ControllerInfo->MapRegisters * PAGE_SIZE) /
                                             DriveInfo->DiskGeometry.BytesPerSector);

            CurrentTransferBytes = CurrentTransferSectors * DriveInfo->DiskGeometry.BytesPerSector;

            INFO_(FLOPPY, "ReadWritePassive: limiting transfer to 0x%x bytes (0x%x sectors) due to map registers\n",
                  CurrentTransferBytes, CurrentTransferSectors);
        }

        /* set up this round's dma operation */
        /* param 2 is ReadOperation --> opposite of WriteToDevice that IoMapTransfer takes.  BAD MS. */
        KeFlushIoBuffers(Irp->MdlAddress, !WriteToDevice, TRUE);

        IoMapTransfer(DriveInfo->ControllerInfo->AdapterObject, Irp->MdlAddress,
                      DriveInfo->ControllerInfo->MapRegisterBase,
                      (PVOID)((ULONG_PTR)MmGetMdlVirtualAddress(Irp->MdlAddress) + TransferByteOffset),
                      &CurrentTransferBytes, WriteToDevice);

        /*
         * Read or Write
         */
        KeClearEvent(&DriveInfo->ControllerInfo->SynchEvent);

        /* Issue the read/write command to the controller.  Note that it expects the opposite of WriteToDevice. */
        if(HwReadWriteData(DriveInfo->ControllerInfo, !WriteToDevice, DriveInfo->UnitNumber, Cylinder, Head, StartSector,
                           DriveInfo->BytesPerSectorCode, DriveInfo->DiskGeometry.SectorsPerTrack, Gap, 0xff) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "ReadWritePassive(): HwReadWriteData returned failure; unable to read; completing with STATUS_UNSUCCESSFUL\n");
            RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            StopMotor(DriveInfo->ControllerInfo);
            return ;
        }

        INFO_(FLOPPY, "ReadWritePassive(): HwReadWriteData returned -- waiting on event\n");

        /*
         * At this point, we block and wait for an interrupt
         * FIXME: this seems to take too long
         */
        WaitForControllerInterrupt(DriveInfo->ControllerInfo);

        /* Read is complete; flush & free adapter channel */
        IoFlushAdapterBuffers(DriveInfo->ControllerInfo->AdapterObject, Irp->MdlAddress,
                              DriveInfo->ControllerInfo->MapRegisterBase,
                              (PVOID)((ULONG_PTR)MmGetMdlVirtualAddress(Irp->MdlAddress) + TransferByteOffset),
                              CurrentTransferBytes, WriteToDevice);

        /* Read the results from the drive */
        if(HwReadWriteResult(DriveInfo->ControllerInfo) != STATUS_SUCCESS)
        {
            WARN_(FLOPPY, "ReadWritePassive(): HwReadWriteResult returned failure; unable to read; completing with STATUS_UNSUCCESSFUL\n");
            HwDumpRegisters(DriveInfo->ControllerInfo);
            RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            StopMotor(DriveInfo->ControllerInfo);
            return ;
        }

        TransferByteOffset += CurrentTransferBytes;
    }

    RWFreeAdapterChannel(DriveInfo->ControllerInfo->AdapterObject);

    /* That's all folks! */
    INFO_(FLOPPY, "ReadWritePassive(): success; Completing with STATUS_SUCCESS\n");
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = Length;
    IoCompleteRequest(Irp, IO_DISK_INCREMENT);
    StopMotor(DriveInfo->ControllerInfo);
}