xref: /reactos/drivers/input/mouclass/misc.c (revision c2c66aff)
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:         Miscellaneous operations
6  *
7  * PROGRAMMERS:     Herv� Poussineau (hpoussin@reactos.org)
8  */
9 
10 #include "mouclass.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 }
114