xref: /reactos/drivers/input/i8042prt/misc.c (revision 9393fc32)
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:     Miscellaneous 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 }
115