Sync with trunk (aka 'I want my virtualbox mouse integration too')
[reactos.git] / drivers / input / mouclass / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Mouse class driver
4 * FILE: drivers/input/mouclass/misc.c
5 * PURPOSE: Misceallenous operations
6 *
7 * PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.org)
8 */
9
10 #include "mouclass.h"
11
12 static IO_COMPLETION_ROUTINE ForwardIrpAndWaitCompletion;
13
14 static NTSTATUS NTAPI
15 ForwardIrpAndWaitCompletion(
16 IN PDEVICE_OBJECT DeviceObject,
17 IN PIRP Irp,
18 IN PVOID Context)
19 {
20 if (Irp->PendingReturned)
21 KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
22 return STATUS_MORE_PROCESSING_REQUIRED;
23 }
24
25 NTSTATUS
26 ForwardIrpAndWait(
27 IN PDEVICE_OBJECT DeviceObject,
28 IN PIRP Irp)
29 {
30 PDEVICE_OBJECT LowerDevice;
31 KEVENT Event;
32 NTSTATUS Status;
33
34 ASSERT(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO);
35 LowerDevice = ((PPORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
36
37 KeInitializeEvent(&Event, NotificationEvent, FALSE);
38 IoCopyCurrentIrpStackLocationToNext(Irp);
39
40 TRACE_(CLASS_NAME, "Calling lower device %p\n", LowerDevice);
41 IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
42
43 Status = IoCallDriver(LowerDevice, Irp);
44 if (Status == STATUS_PENDING)
45 {
46 Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
47 if (NT_SUCCESS(Status))
48 Status = Irp->IoStatus.Status;
49 }
50
51 return Status;
52 }
53
54 NTSTATUS NTAPI
55 ForwardIrpAndForget(
56 IN PDEVICE_OBJECT DeviceObject,
57 IN PIRP Irp)
58 {
59 PDEVICE_OBJECT LowerDevice;
60
61 ASSERT(!((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsClassDO);
62 LowerDevice = ((PPORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
63
64 IoSkipCurrentIrpStackLocation(Irp);
65 return IoCallDriver(LowerDevice, Irp);
66 }
67
68 NTSTATUS
69 DuplicateUnicodeString(
70 IN ULONG Flags,
71 IN PCUNICODE_STRING SourceString,
72 OUT PUNICODE_STRING DestinationString)
73 {
74 if (SourceString == NULL || DestinationString == NULL
75 || SourceString->Length > SourceString->MaximumLength
76 || (SourceString->Length == 0 && SourceString->MaximumLength > 0 && SourceString->Buffer == NULL)
77 || Flags == RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING || Flags >= 4)
78 {
79 return STATUS_INVALID_PARAMETER;
80 }
81
82
83 if ((SourceString->Length == 0)
84 && (Flags != (RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE |
85 RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING)))
86 {
87 DestinationString->Length = 0;
88 DestinationString->MaximumLength = 0;
89 DestinationString->Buffer = NULL;
90 }
91 else
92 {
93 USHORT DestMaxLength = SourceString->Length;
94
95 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
96 DestMaxLength += sizeof(UNICODE_NULL);
97
98 DestinationString->Buffer = ExAllocatePoolWithTag(PagedPool, DestMaxLength, CLASS_TAG);
99 if (DestinationString->Buffer == NULL)
100 return STATUS_NO_MEMORY;
101
102 RtlCopyMemory(DestinationString->Buffer, SourceString->Buffer, SourceString->Length);
103 DestinationString->Length = SourceString->Length;
104 DestinationString->MaximumLength = DestMaxLength;
105
106 if (Flags & RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE)
107 DestinationString->Buffer[DestinationString->Length / sizeof(WCHAR)] = 0;
108 }
109
110 return STATUS_SUCCESS;
111 }