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
WmipSecurityMethod(_In_ PVOID Object,_In_ SECURITY_OPERATION_CODE OperationType,_In_ PSECURITY_INFORMATION SecurityInformation,_In_ PSECURITY_DESCRIPTOR SecurityDescriptor,_Inout_ PULONG CapturedLength,_Inout_ PSECURITY_DESCRIPTOR * ObjectSecurityDescriptor,_In_ POOL_TYPE PoolType,_In_ PGENERIC_MAPPING GenericMapping)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
WmipDeleteMethod(_In_ PVOID Object)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
WmipCloseMethod(_In_opt_ PEPROCESS Process,_In_ PVOID Object,_In_ ACCESS_MASK GrantedAccess,_In_ ULONG ProcessHandleCount,_In_ ULONG SystemHandleCount)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
WmipInitializeGuidObjectType(VOID)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
WmipGUIDFromString(_In_ PUNICODE_STRING GuidString,_Out_ PGUID Guid)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
WmipCreateGuidObject(_In_ const GUID * Guid,_Out_ PWMIP_GUID_OBJECT * OutGuidObject)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
WmipOpenGuidObject(_In_ LPCGUID Guid,_In_ ACCESS_MASK DesiredAccess,_In_ KPROCESSOR_MODE AccessMode,_Out_ PHANDLE OutGuidObjectHandle,_Outptr_ PVOID * OutGuidObject)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
WmipOpenGuidObjectByName(_In_ POBJECT_ATTRIBUTES ObjectAttributes,_In_ ACCESS_MASK DesiredAccess,_In_ KPROCESSOR_MODE AccessMode,_Out_ PHANDLE OutGuidObjectHandle,_Outptr_ PVOID * OutGuidObject)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