[CLASS2]: Fix status code on too small as exposed by kernel32:DeviceIoControl
[reactos.git] / ntoskrnl / wmi / guidobj.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/wmi/guidobj.c
5 * PURPOSE: I/O Windows Management Instrumentation (WMI) Support
6 * PROGRAMMERS: Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #include <wmistr.h>
13 #include "wmip.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18
19 /* GLOBALS ******************************************************************/
20
21 POBJECT_TYPE WmipGuidObjectType;
22 GENERIC_MAPPING WmipGenericMapping =
23 {
24 WMIGUID_QUERY,
25 WMIGUID_SET,
26 WMIGUID_EXECUTE,
27 WMIGUID_ALL_ACCESS
28 };
29
30
31 /* FUNCTIONS *****************************************************************/
32
33 NTSTATUS
34 NTAPI
35 WmipSecurityMethod(
36 _In_ PVOID Object,
37 _In_ SECURITY_OPERATION_CODE OperationType,
38 _In_ PSECURITY_INFORMATION SecurityInformation,
39 _In_ PSECURITY_DESCRIPTOR SecurityDescriptor,
40 _Inout_ PULONG CapturedLength,
41 _Inout_ PSECURITY_DESCRIPTOR *ObjectSecurityDescriptor,
42 _In_ POOL_TYPE PoolType,
43 _In_ PGENERIC_MAPPING GenericMapping)
44 {
45 PAGED_CODE();
46
47 ASSERT((PoolType == PagedPool) || (PoolType == NonPagedPool));
48 ASSERT((OperationType == QuerySecurityDescriptor) ||
49 (OperationType == SetSecurityDescriptor) ||
50 (OperationType == AssignSecurityDescriptor) ||
51 (OperationType == DeleteSecurityDescriptor));
52
53 if (OperationType == QuerySecurityDescriptor)
54 {
55 return ObQuerySecurityDescriptorInfo(Object,
56 SecurityInformation,
57 SecurityDescriptor,
58 CapturedLength,
59 ObjectSecurityDescriptor);
60 }
61 else if (OperationType == SetSecurityDescriptor)
62 {
63 return ObSetSecurityDescriptorInfo(Object,
64 SecurityInformation,
65 SecurityDescriptor,
66 ObjectSecurityDescriptor,
67 PoolType,
68 GenericMapping);
69 }
70 else if (OperationType == AssignSecurityDescriptor)
71 {
72 ObAssignObjectSecurityDescriptor(Object, SecurityDescriptor, PoolType);
73 return STATUS_SUCCESS;
74 }
75 else if (OperationType == DeleteSecurityDescriptor)
76 {
77 return ObDeassignSecurity(ObjectSecurityDescriptor);
78 }
79
80 ASSERT(FALSE);
81 return STATUS_INVALID_PARAMETER;
82 }
83
84 VOID
85 NTAPI
86 WmipDeleteMethod(
87 _In_ PVOID Object)
88 {
89 PWMIP_GUID_OBJECT GuidObject = Object;
90
91 /* Check if the object is attached to an IRP */
92 if (GuidObject->Irp != NULL)
93 {
94 /* This is not supported yet */
95 ASSERT(FALSE);
96 }
97 }
98
99 VOID
100 NTAPI
101 WmipCloseMethod(
102 _In_opt_ PEPROCESS Process,
103 _In_ PVOID Object,
104 _In_ ACCESS_MASK GrantedAccess,
105 _In_ ULONG ProcessHandleCount,
106 _In_ ULONG SystemHandleCount)
107 {
108 /* For now nothing */
109 }
110
111 NTSTATUS
112 NTAPI
113 WmipInitializeGuidObjectType(
114 VOID)
115 {
116 static UNICODE_STRING GuidObjectName = RTL_CONSTANT_STRING(L"WmiGuid");
117 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
118 NTSTATUS Status;
119
120 /* Setup the object type initializer */
121 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
122 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
123 ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
124 ObjectTypeInitializer.GenericMapping = WmipGenericMapping;
125 ObjectTypeInitializer.PoolType = NonPagedPool;
126 ObjectTypeInitializer.MaintainHandleCount = FALSE;
127 ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_ALL | 0xFFF;
128 ObjectTypeInitializer.SecurityRequired = TRUE;
129 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(WMIP_GUID_OBJECT);
130 ObjectTypeInitializer.SecurityProcedure = WmipSecurityMethod;
131 ObjectTypeInitializer.DeleteProcedure = WmipDeleteMethod;
132 ObjectTypeInitializer.CloseProcedure = WmipCloseMethod;
133
134 /* Create the object type */
135 Status = ObCreateObjectType(&GuidObjectName,
136 &ObjectTypeInitializer,
137 0,
138 &WmipGuidObjectType);
139 if (!NT_SUCCESS(Status))
140 {
141 DPRINT1("ObCreateObjectType failed: 0x%lx\n", Status);
142 }
143
144 return Status;
145 }
146
147 static
148 NTSTATUS
149 WmipGUIDFromString(
150 _In_ PUNICODE_STRING GuidString,
151 _Out_ PGUID Guid)
152 {
153 WCHAR Buffer[GUID_STRING_LENGTH + 2];
154 UNICODE_STRING String;
155
156 /* Validate string length */
157 if (GuidString->Length != GUID_STRING_LENGTH * sizeof(WCHAR))
158 {
159 return STATUS_INVALID_PARAMETER;
160 }
161
162 /* Copy the string and wrap it in {} */
163 RtlCopyMemory(&Buffer[1], GuidString->Buffer, GuidString->Length);
164 Buffer[0] = L'{';
165 Buffer[GUID_STRING_LENGTH + 1] = L'}';
166
167 String.Buffer = Buffer;
168 String.Length = String.MaximumLength = sizeof(Buffer);
169
170 return RtlGUIDFromString(&String, Guid);
171 }
172
173 static
174 NTSTATUS
175 WmipCreateGuidObject(
176 _In_ const GUID *Guid,
177 _Out_ PWMIP_GUID_OBJECT *OutGuidObject)
178 {
179 OBJECT_ATTRIBUTES ObjectAttributes;
180 PWMIP_GUID_OBJECT GuidObject;
181 NTSTATUS Status;
182
183 /* Initialize object attributes for an unnamed object */
184 InitializeObjectAttributes(&ObjectAttributes,
185 NULL,
186 0,
187 NULL,
188 NULL); // FIXME: security descriptor!
189
190 /* Create the GUID object */
191 Status = ObCreateObject(KernelMode,
192 WmipGuidObjectType,
193 &ObjectAttributes,
194 KernelMode,
195 NULL,
196 sizeof(WMIP_GUID_OBJECT),
197 0,
198 0,
199 (PVOID*)&GuidObject);
200 if (!NT_SUCCESS(Status))
201 {
202 DPRINT1("WMI: failed to create GUID object: 0x%lx\n", Status);
203 return Status;
204 }
205
206 RtlZeroMemory(GuidObject, sizeof(*GuidObject));
207 GuidObject->Guid = *Guid;
208
209 *OutGuidObject = GuidObject;
210
211 return STATUS_SUCCESS;
212 }
213
214 NTSTATUS
215 NTAPI
216 WmipOpenGuidObject(
217 _In_ LPCGUID Guid,
218 _In_ ACCESS_MASK DesiredAccess,
219 _In_ KPROCESSOR_MODE AccessMode,
220 _Out_ PHANDLE OutGuidObjectHandle,
221 _Outptr_ PVOID *OutGuidObject)
222 {
223 PWMIP_GUID_OBJECT GuidObject;
224 ULONG HandleAttributes;
225 NTSTATUS Status;
226
227 /* Create the GUID object */
228 Status = WmipCreateGuidObject(Guid, &GuidObject);
229 if (!NT_SUCCESS(Status))
230 {
231 DPRINT1("Failed to create GUID object: 0x%lx\n", Status);
232 *OutGuidObject = NULL;
233 return Status;
234 }
235
236 /* Set handle attributes */
237 HandleAttributes = (AccessMode == KernelMode) ? OBJ_KERNEL_HANDLE : 0;
238
239 /* Get a handle for the object */
240 Status = ObOpenObjectByPointer(GuidObject,
241 HandleAttributes,
242 0,
243 DesiredAccess,
244 WmipGuidObjectType,
245 AccessMode,
246 OutGuidObjectHandle);
247 if (!NT_SUCCESS(Status))
248 {
249 DPRINT1("ObOpenObjectByPointer failed: 0x%lx\n", Status);
250 ObfDereferenceObject(GuidObject);
251 GuidObject = NULL;
252 }
253
254 *OutGuidObject = GuidObject;
255
256 return Status;
257 }
258
259 NTSTATUS
260 NTAPI
261 WmipOpenGuidObjectByName(
262 _In_ POBJECT_ATTRIBUTES ObjectAttributes,
263 _In_ ACCESS_MASK DesiredAccess,
264 _In_ KPROCESSOR_MODE AccessMode,
265 _Out_ PHANDLE OutGuidObjectHandle,
266 _Outptr_ PVOID *OutGuidObject)
267 {
268 static UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\WmiGuid\\");
269 UNICODE_STRING GuidString;
270 NTSTATUS Status;
271 GUID Guid;
272 PAGED_CODE();
273
274 /* Check if we have the expected prefix */
275 if (!RtlPrefixUnicodeString(&Prefix, ObjectAttributes->ObjectName, FALSE))
276 {
277 DPRINT1("WMI: Invalid prefix for guid object '%wZ'\n",
278 ObjectAttributes->ObjectName);
279 return STATUS_INVALID_PARAMETER;
280 }
281
282 /* Extract the GUID string */
283 GuidString = *ObjectAttributes->ObjectName;
284 GuidString.Buffer += Prefix.Length / sizeof(WCHAR);
285 GuidString.Length -= Prefix.Length;
286
287 /* Convert the string into a GUID structure */
288 Status = WmipGUIDFromString(&GuidString, &Guid);
289 if (!NT_SUCCESS(Status))
290 {
291 DPRINT1("WMI: Invalid uuid format for guid '%wZ'\n", &GuidString);
292 return Status;
293 }
294
295 return WmipOpenGuidObject(&Guid,
296 DesiredAccess,
297 AccessMode,
298 OutGuidObjectHandle,
299 OutGuidObject);
300 }
301