Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenproperty.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: drivers/ksfilter/ks/event.c 00005 * PURPOSE: KS property handling functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "priv.h" 00010 00011 const GUID KSPROPTYPESETID_General = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; 00012 00013 NTSTATUS 00014 FindPropertyHandler( 00015 IN PIO_STATUS_BLOCK IoStatus, 00016 IN const KSPROPERTY_SET* PropertySet, 00017 IN ULONG PropertySetCount, 00018 IN PKSPROPERTY Property, 00019 IN ULONG InputBufferLength, 00020 IN ULONG OutputBufferLength, 00021 OUT PVOID OutputBuffer, 00022 OUT PFNKSHANDLER *PropertyHandler, 00023 OUT PKSPROPERTY_SET * Set, 00024 OUT PKSPROPERTY_ITEM *PropertyItem) 00025 { 00026 ULONG Index, ItemIndex; 00027 00028 for(Index = 0; Index < PropertySetCount; Index++) 00029 { 00030 ASSERT(PropertySet[Index].Set); 00031 00032 if (IsEqualGUIDAligned(&Property->Set, PropertySet[Index].Set)) 00033 { 00034 for(ItemIndex = 0; ItemIndex < PropertySet[Index].PropertiesCount; ItemIndex++) 00035 { 00036 if (PropertySet[Index].PropertyItem[ItemIndex].PropertyId == Property->Id) 00037 { 00038 if (PropertySet[Index].PropertyItem[ItemIndex].MinProperty > InputBufferLength) 00039 { 00040 /* too small input buffer */ 00041 IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinProperty; 00042 return STATUS_INVALID_PARAMETER; 00043 } 00044 00045 if (PropertySet[Index].PropertyItem[ItemIndex].MinData > OutputBufferLength) 00046 { 00047 /* too small output buffer */ 00048 IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinData; 00049 return STATUS_MORE_ENTRIES; 00050 } 00051 00052 /* store property set */ 00053 *Set = (PKSPROPERTY_SET)&PropertySet[Index]; 00054 *PropertyItem = (PKSPROPERTY_ITEM)&PropertySet[Index].PropertyItem[ItemIndex]; 00055 00056 if (Property->Flags & KSPROPERTY_TYPE_SET) 00057 { 00058 /* store property handler */ 00059 *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler; 00060 return STATUS_SUCCESS; 00061 } 00062 00063 if (Property->Flags & KSPROPERTY_TYPE_GET) 00064 { 00065 /* store property handler */ 00066 *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler; 00067 return STATUS_SUCCESS; 00068 } 00069 00070 00071 if (Property->Flags & KSPROPERTY_TYPE_BASICSUPPORT) 00072 { 00073 PULONG Flags; 00074 PKSPROPERTY_DESCRIPTION Description; 00075 00076 if (sizeof(ULONG) > OutputBufferLength) 00077 { 00078 /* too small buffer */ 00079 return STATUS_INVALID_PARAMETER; 00080 } 00081 00082 /* get output buffer */ 00083 Flags = (PULONG)OutputBuffer; 00084 00085 /* clear flags */ 00086 *Flags = 0; 00087 00088 IoStatus->Information = sizeof(ULONG); 00089 00090 if (PropertySet[Index].PropertyItem[ItemIndex].SupportHandler) 00091 { 00092 /* use support handler from driver */ 00093 *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SupportHandler; 00094 return STATUS_SUCCESS; 00095 } 00096 00097 if (PropertySet[Index].PropertyItem[ItemIndex].GetSupported) 00098 *Flags |= KSPROPERTY_TYPE_GET; 00099 00100 if (PropertySet[Index].PropertyItem[ItemIndex].SetSupported) 00101 *Flags |= KSPROPERTY_TYPE_SET; 00102 00103 if (OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION)) 00104 { 00105 /* get output buffer */ 00106 Description = (PKSPROPERTY_DESCRIPTION)OutputBuffer; 00107 00108 /* store result */ 00109 Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION); 00110 Description->PropTypeSet.Set = KSPROPTYPESETID_General; 00111 Description->PropTypeSet.Id = 0; 00112 Description->PropTypeSet.Flags = 0; 00113 Description->MembersListCount = 0; 00114 Description->Reserved = 0; 00115 00116 IoStatus->Information = sizeof(KSPROPERTY_DESCRIPTION); 00117 } 00118 return STATUS_SUCCESS; 00119 } 00120 } 00121 } 00122 } 00123 } 00124 return STATUS_NOT_FOUND; 00125 } 00126 00127 00128 NTSTATUS 00129 KspPropertyHandler( 00130 IN PIRP Irp, 00131 IN ULONG PropertySetsCount, 00132 IN const KSPROPERTY_SET* PropertySet, 00133 IN PFNKSALLOCATOR Allocator OPTIONAL, 00134 IN ULONG PropertyItemSize OPTIONAL) 00135 { 00136 PKSPROPERTY Property; 00137 PKSPROPERTY_ITEM PropertyItem; 00138 PKSPROPERTY_SET Set; 00139 PIO_STACK_LOCATION IoStack; 00140 NTSTATUS Status; 00141 PFNKSHANDLER PropertyHandler = NULL; 00142 ULONG Index, InputBufferLength, OutputBufferLength, TotalSize; 00143 LPGUID Guid; 00144 //UNICODE_STRING GuidBuffer; 00145 00146 /* get current irp stack */ 00147 IoStack = IoGetCurrentIrpStackLocation(Irp); 00148 00149 /* get parameters */ 00150 OutputBufferLength = (IoStack->Parameters.DeviceIoControl.OutputBufferLength + 7) & ~7; 00151 InputBufferLength = IoStack->Parameters.DeviceIoControl.InputBufferLength; 00152 00153 /* check for invalid buffer length size */ 00154 if (OutputBufferLength < IoStack->Parameters.DeviceIoControl.OutputBufferLength) 00155 { 00156 /* unsigned overflow */ 00157 return STATUS_INVALID_BUFFER_SIZE; 00158 } 00159 00160 /* check for integer overflow */ 00161 if (InputBufferLength + OutputBufferLength < IoStack->Parameters.DeviceIoControl.OutputBufferLength) 00162 { 00163 /* overflow */ 00164 return STATUS_INVALID_BUFFER_SIZE; 00165 } 00166 00167 /* check if inputbuffer at least holds KSPROPERTY item */ 00168 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY)) 00169 { 00170 /* invalid parameter */ 00171 return STATUS_INVALID_BUFFER_SIZE; 00172 } 00173 00174 /* get total size */ 00175 TotalSize = InputBufferLength + OutputBufferLength; 00176 00177 /* get input property request */ 00178 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; 00179 00180 /* have the parameters been checked yet */ 00181 if (!Irp->AssociatedIrp.SystemBuffer) 00182 { 00183 /* is it from user mode */ 00184 if (Irp->RequestorMode == UserMode) 00185 { 00186 /* probe user buffer */ 00187 ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, InputBufferLength, 1); 00188 } 00189 00190 /* do we have an allocator */ 00191 if ((Allocator) && (Property->Flags & (KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_SET))) 00192 { 00193 /* call allocator */ 00194 Status = Allocator(Irp, TotalSize, (Property->Flags & KSPROPERTY_TYPE_GET)); 00195 00196 /* check for success */ 00197 if (!NT_SUCCESS(Status)) 00198 return Status; 00199 } 00200 else 00201 { 00202 /* allocate buffer */ 00203 Irp->AssociatedIrp.SystemBuffer = AllocateItem(NonPagedPool, TotalSize); 00204 00205 /* sanity check */ 00206 ASSERT(Irp->AssociatedIrp.SystemBuffer != NULL); 00207 00208 /* mark irp as buffered so that changes the stream headers are propagated back */ 00209 Irp->Flags |= IRP_DEALLOCATE_BUFFER | IRP_BUFFERED_IO; 00210 } 00211 00212 /* now copy the buffer */ 00213 RtlCopyMemory((PVOID)((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer + OutputBufferLength), IoStack->Parameters.DeviceIoControl.Type3InputBuffer, InputBufferLength); 00214 00215 /* use new property buffer */ 00216 Property = (PKSPROPERTY)((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer + OutputBufferLength); 00217 00218 /* is it a set operation */ 00219 if (Property->Flags & KSPROPERTY_TYPE_SET) 00220 { 00221 /* for set operations, the output parameters need to be copied */ 00222 if (Irp->RequestorMode == UserMode) 00223 { 00224 /* probe user parameter */ 00225 ProbeForRead(Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, 1); 00226 } 00227 00228 /* copy parameters, needs un-aligned parameter length */ 00229 RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength); 00230 } 00231 00232 /* is there an output buffer */ 00233 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength) 00234 { 00235 /* is it from user mode */ 00236 if (Irp->RequestorMode == UserMode) 00237 { 00238 /* probe buffer for writing */ 00239 ProbeForWrite(Irp->UserBuffer, IoStack->Parameters.DeviceIoControl.OutputBufferLength, 1); 00240 } 00241 00242 if (!Allocator || !(Property->Flags & KSPROPERTY_TYPE_GET)) 00243 { 00244 /* it is an input operation */ 00245 Irp->Flags |= IRP_INPUT_OPERATION; 00246 } 00247 } 00248 } 00249 else 00250 { 00251 /* use new property buffer */ 00252 Property = (PKSPROPERTY)((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer + OutputBufferLength); 00253 } 00254 00255 //RtlStringFromGUID(&Property->Set, &GuidBuffer); 00256 00257 //DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM)); 00258 //DPRINT("PropertyId %lu PropertyFlags %x Guid %S\n", Property->Id, Property->Flags, GuidBuffer.Buffer); 00259 00260 //RtlFreeUnicodeString(&GuidBuffer); 00261 00262 /* sanity check */ 00263 ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM)); 00264 00265 /* find the property handler */ 00266 Status = FindPropertyHandler(&Irp->IoStatus, PropertySet, PropertySetsCount, Property, InputBufferLength, OutputBufferLength, Irp->AssociatedIrp.SystemBuffer, &PropertyHandler, &Set, &PropertyItem); 00267 00268 if (NT_SUCCESS(Status) && PropertyHandler) 00269 { 00270 /* store set */ 00271 KSPROPERTY_SET_IRP_STORAGE(Irp) = Set; 00272 00273 /* are any custom property item sizes used */ 00274 if (PropertyItemSize) 00275 { 00276 /* store custom property item */ 00277 KSPROPERTY_ITEM_IRP_STORAGE(Irp) = PropertyItem; 00278 } 00279 00280 /* call property handler */ 00281 Status = PropertyHandler(Irp, Property, (OutputBufferLength > 0 ? Irp->AssociatedIrp.SystemBuffer : NULL)); 00282 00283 if (Status == STATUS_BUFFER_TOO_SMALL) 00284 { 00285 /* output buffer is too small */ 00286 if (Allocator) 00287 { 00288 /* allocate the requested amount */ 00289 Status = Allocator(Irp, Irp->IoStatus.Information, FALSE); 00290 00291 /* check if the block was allocated */ 00292 if (!NT_SUCCESS(Status)) 00293 { 00294 /* no memory */ 00295 return STATUS_INSUFFICIENT_RESOURCES; 00296 } 00297 00298 /* re-call property handler */ 00299 Status = PropertyHandler(Irp, Property, Irp->AssociatedIrp.SystemBuffer); 00300 } 00301 } 00302 } 00303 else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && (Property->Flags & KSPROPERTY_TYPE_SETSUPPORT) == KSPROPERTY_TYPE_SETSUPPORT) 00304 { 00305 // store output size 00306 Irp->IoStatus.Information = sizeof(GUID) * PropertySetsCount; 00307 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * PropertySetsCount) 00308 { 00309 // buffer too small 00310 return STATUS_MORE_ENTRIES; 00311 } 00312 00313 // get output buffer 00314 Guid = (LPGUID)Irp->AssociatedIrp.SystemBuffer; 00315 00316 // copy property guids from property sets 00317 for(Index = 0; Index < PropertySetsCount; Index++) 00318 { 00319 RtlMoveMemory(&Guid[Index], PropertySet[Index].Set, sizeof(GUID)); 00320 } 00321 Status = STATUS_SUCCESS; 00322 } 00323 00324 /* done */ 00325 return Status; 00326 } 00327 00328 /* 00329 @implemented 00330 */ 00331 KSDDKAPI 00332 NTSTATUS 00333 NTAPI 00334 KsPropertyHandler( 00335 IN PIRP Irp, 00336 IN ULONG PropertySetsCount, 00337 IN const KSPROPERTY_SET* PropertySet) 00338 { 00339 return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, NULL, 0); 00340 } 00341 00342 00343 /* 00344 @implemented 00345 */ 00346 KSDDKAPI 00347 NTSTATUS 00348 NTAPI 00349 KsPropertyHandlerWithAllocator( 00350 IN PIRP Irp, 00351 IN ULONG PropertySetsCount, 00352 IN PKSPROPERTY_SET PropertySet, 00353 IN PFNKSALLOCATOR Allocator OPTIONAL, 00354 IN ULONG PropertyItemSize OPTIONAL) 00355 { 00356 return KspPropertyHandler(Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize); 00357 } 00358 00359 NTSTATUS 00360 FindFastPropertyHandler( 00361 IN ULONG FastIoCount, 00362 IN const KSFASTPROPERTY_ITEM * FastIoTable, 00363 IN PKSPROPERTY PropertyId, 00364 OUT PFNKSFASTHANDLER * FastPropertyHandler) 00365 { 00366 ULONG Index; 00367 00368 /* iterate through all items */ 00369 for(Index = 0; Index < FastIoCount; Index++) 00370 { 00371 if (PropertyId->Id == FastIoTable[Index].PropertyId) 00372 { 00373 if (PropertyId->Flags & KSPROPERTY_TYPE_SET) 00374 { 00375 if (FastIoTable[Index].SetSupported) 00376 { 00377 *FastPropertyHandler = FastIoTable[Index].SetPropertyHandler; 00378 return STATUS_SUCCESS; 00379 } 00380 } 00381 00382 if (PropertyId->Flags & KSPROPERTY_TYPE_GET) 00383 { 00384 if (FastIoTable[Index].GetSupported) 00385 { 00386 *FastPropertyHandler = FastIoTable[Index].GetPropertyHandler; 00387 return STATUS_SUCCESS; 00388 } 00389 } 00390 } 00391 00392 } 00393 /* no fast property handler found */ 00394 return STATUS_NOT_FOUND; 00395 } 00396 00397 00398 /* 00399 @implemented 00400 */ 00401 KSDDKAPI 00402 BOOLEAN 00403 NTAPI 00404 KsFastPropertyHandler( 00405 IN PFILE_OBJECT FileObject, 00406 IN PKSPROPERTY UNALIGNED Property, 00407 IN ULONG PropertyLength, 00408 IN OUT PVOID UNALIGNED Data, 00409 IN ULONG DataLength, 00410 OUT PIO_STATUS_BLOCK IoStatus, 00411 IN ULONG PropertySetsCount, 00412 IN const KSPROPERTY_SET* PropertySet) 00413 { 00414 KSPROPERTY PropRequest; 00415 KPROCESSOR_MODE Mode; 00416 NTSTATUS Status = STATUS_SUCCESS; 00417 ULONG Index; 00418 PFNKSFASTHANDLER FastPropertyHandler; 00419 00420 if (PropertyLength < sizeof(KSPROPERTY)) 00421 { 00422 /* invalid request */ 00423 return FALSE; 00424 } 00425 00426 /* get previous mode */ 00427 Mode = ExGetPreviousMode(); 00428 00429 if (Mode == KernelMode) 00430 { 00431 /* just copy it */ 00432 RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY)); 00433 } 00434 else 00435 { 00436 /* need to probe the buffer */ 00437 _SEH2_TRY 00438 { 00439 ProbeForRead(Property, sizeof(KSPROPERTY), sizeof(UCHAR)); 00440 RtlMoveMemory(&PropRequest, Property, sizeof(KSPROPERTY)); 00441 } 00442 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00443 { 00444 /* Exception, get the error code */ 00445 Status = _SEH2_GetExceptionCode(); 00446 }_SEH2_END; 00447 00448 if (!NT_SUCCESS(Status)) 00449 return FALSE; 00450 } 00451 00452 /* are there any property sets provided */ 00453 if (PropertySetsCount) 00454 { 00455 /* iterate through all property sets count */ 00456 Index = 0; 00457 do 00458 { 00459 /* does the property id match */ 00460 if (IsEqualGUIDAligned(PropertySet[Index].Set, &PropRequest.Set)) 00461 { 00462 /* try to find a fast property handler */ 00463 Status = FindFastPropertyHandler(PropertySet[Index].FastIoCount, PropertySet[Index].FastIoTable, &PropRequest, &FastPropertyHandler); 00464 00465 if (NT_SUCCESS(Status)) 00466 { 00467 /* call fast property handler */ 00468 ASSERT(PropertyLength == sizeof(KSPROPERTY)); /* FIXME check if property length is bigger -> copy params */ 00469 ASSERT(Mode == KernelMode); /* FIXME need to probe usermode output buffer */ 00470 return FastPropertyHandler(FileObject, &PropRequest, sizeof(KSPROPERTY), Data, DataLength, IoStatus); 00471 } 00472 } 00473 /* move to next item */ 00474 Index++; 00475 }while(Index < PropertySetsCount); 00476 } 00477 return FALSE; 00478 } 00479 00480 /* 00481 @implemented 00482 */ 00483 KSDDKAPI 00484 NTSTATUS 00485 NTAPI 00486 KsDispatchSpecificProperty( 00487 IN PIRP Irp, 00488 IN PFNKSHANDLER Handler) 00489 { 00490 PIO_STACK_LOCATION IoStack; 00491 00492 /* get current irp stack location */ 00493 IoStack = IoGetCurrentIrpStackLocation(Irp); 00494 00495 return Handler(Irp, IoStack->Parameters.DeviceIoControl.Type3InputBuffer, Irp->UserBuffer); 00496 } 00497 Generated on Mon May 28 2012 04:21:14 for ReactOS by
1.7.6.1
|