xref: /reactos/ntoskrnl/wmi/guidobj.c (revision 019f21ee)
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     KeInitializeEvent(&GuidObject->Event, NotificationEvent, FALSE);
208     GuidObject->Guid = *Guid;
209 
210     *OutGuidObject = GuidObject;
211 
212     return STATUS_SUCCESS;
213 }
214 
215 NTSTATUS
216 NTAPI
217 WmipOpenGuidObject(
218     _In_ LPCGUID Guid,
219     _In_ ACCESS_MASK DesiredAccess,
220     _In_ KPROCESSOR_MODE AccessMode,
221     _Out_ PHANDLE OutGuidObjectHandle,
222     _Outptr_ PVOID *OutGuidObject)
223 {
224     PWMIP_GUID_OBJECT GuidObject;
225     ULONG HandleAttributes;
226     NTSTATUS Status;
227 
228     /* Create the GUID object */
229     Status = WmipCreateGuidObject(Guid, &GuidObject);
230     if (!NT_SUCCESS(Status))
231     {
232         DPRINT1("Failed to create GUID object: 0x%lx\n", Status);
233         *OutGuidObject = NULL;
234         return Status;
235     }
236 
237     /* Set handle attributes */
238     HandleAttributes = (AccessMode == KernelMode) ? OBJ_KERNEL_HANDLE : 0;
239 
240     /* Get a handle for the object */
241     Status = ObOpenObjectByPointer(GuidObject,
242                                    HandleAttributes,
243                                    0,
244                                    DesiredAccess,
245                                    WmipGuidObjectType,
246                                    AccessMode,
247                                    OutGuidObjectHandle);
248     if (!NT_SUCCESS(Status))
249     {
250         DPRINT1("ObOpenObjectByPointer failed: 0x%lx\n", Status);
251         ObDereferenceObject(GuidObject);
252         GuidObject = NULL;
253     }
254 
255     *OutGuidObject = GuidObject;
256 
257     return Status;
258 }
259 
260 NTSTATUS
261 NTAPI
262 WmipOpenGuidObjectByName(
263     _In_ POBJECT_ATTRIBUTES ObjectAttributes,
264     _In_ ACCESS_MASK DesiredAccess,
265     _In_ KPROCESSOR_MODE AccessMode,
266     _Out_ PHANDLE OutGuidObjectHandle,
267     _Outptr_ PVOID *OutGuidObject)
268 {
269     static UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\WmiGuid\\");
270     UNICODE_STRING GuidString;
271     NTSTATUS Status;
272     GUID Guid;
273     PAGED_CODE();
274 
275     /* Check if we have the expected prefix */
276     if (!RtlPrefixUnicodeString(&Prefix, ObjectAttributes->ObjectName, FALSE))
277     {
278         DPRINT1("WMI: Invalid prefix for guid object '%wZ'\n",
279                 ObjectAttributes->ObjectName);
280         return STATUS_INVALID_PARAMETER;
281     }
282 
283     /* Extract the GUID string */
284     GuidString = *ObjectAttributes->ObjectName;
285     GuidString.Buffer += Prefix.Length / sizeof(WCHAR);
286     GuidString.Length -= Prefix.Length;
287 
288     /* Convert the string into a GUID structure */
289     Status = WmipGUIDFromString(&GuidString, &Guid);
290     if (!NT_SUCCESS(Status))
291     {
292         DPRINT1("WMI: Invalid uuid format for guid '%wZ'\n", &GuidString);
293         return Status;
294     }
295 
296     return WmipOpenGuidObject(&Guid,
297                               DesiredAccess,
298                               AccessMode,
299                               OutGuidObjectHandle,
300                               OutGuidObject);
301 }
302 
303