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