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