ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

property.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.