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