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 302