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

methods.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/methods.c
00005  * PURPOSE:         KS Allocator functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 #include "priv.h"
00010 
00011 NTSTATUS
00012 FindMethodHandler(
00013     IN PIO_STATUS_BLOCK IoStatus,
00014     IN  const KSMETHOD_SET* MethodSet,
00015     IN ULONG MethodSetCount,
00016     IN PKSMETHOD Method,
00017     IN ULONG InputBufferLength,
00018     IN ULONG OutputBufferLength,
00019     OUT PVOID OutputBuffer,
00020     OUT PFNKSHANDLER *MethodHandler,
00021     OUT PKSMETHOD_SET * Set)
00022 {
00023     ULONG Index, ItemIndex;
00024 
00025     for(Index = 0; Index < MethodSetCount; Index++)
00026     {
00027         ASSERT(MethodSet[Index].Set);
00028 
00029         if (IsEqualGUIDAligned(&Method->Set, MethodSet[Index].Set))
00030         {
00031             for(ItemIndex = 0; ItemIndex < MethodSet[Index].MethodsCount; ItemIndex++)
00032             {
00033                 if (MethodSet[Index].MethodItem[ItemIndex].MethodId == Method->Id)
00034                 {
00035                     if (MethodSet[Index].MethodItem[ItemIndex].MinMethod > InputBufferLength)
00036                     {
00037                         /* too small input buffer */
00038                         IoStatus->Information = MethodSet[Index].MethodItem[ItemIndex].MinMethod;
00039                         return STATUS_INVALID_PARAMETER;
00040                     }
00041 
00042                     if (MethodSet[Index].MethodItem[ItemIndex].MinData > OutputBufferLength)
00043                     {
00044                         /* too small output buffer */
00045                         IoStatus->Information = MethodSet[Index].MethodItem[ItemIndex].MinData;
00046                         return STATUS_MORE_ENTRIES;
00047                     }
00048                     if (Method->Flags & KSMETHOD_TYPE_BASICSUPPORT)
00049                     {
00050                         PULONG Flags;
00051                         PKSPROPERTY_DESCRIPTION Description;
00052 
00053                         if (sizeof(ULONG) > OutputBufferLength)
00054                         {
00055                             /* too small buffer */
00056                             return STATUS_INVALID_PARAMETER;
00057                         }
00058 
00059                         /* get output buffer */
00060                         Flags = (PULONG)OutputBuffer;
00061 
00062                         /* set flags flags */
00063                         *Flags = MethodSet[Index].MethodItem[ItemIndex].Flags;
00064 
00065                         IoStatus->Information = sizeof(ULONG);
00066 
00067                         if (OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
00068                         {
00069                             /* get output buffer */
00070                             Description = (PKSPROPERTY_DESCRIPTION)OutputBuffer;
00071 
00072                             /* store result */
00073                             Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
00074                             Description->PropTypeSet.Set = KSPROPTYPESETID_General;
00075                             Description->PropTypeSet.Id = 0;
00076                             Description->PropTypeSet.Flags = 0;
00077                             Description->MembersListCount = 0;
00078                             Description->Reserved = 0;
00079 
00080                             IoStatus->Information = sizeof(KSPROPERTY_DESCRIPTION);
00081                         }
00082                         return STATUS_SUCCESS;
00083                     }
00084                     *MethodHandler = MethodSet[Index].MethodItem[ItemIndex].MethodHandler;
00085                     *Set = (PKSMETHOD_SET)&MethodSet[Index];
00086                     return STATUS_SUCCESS;
00087                 }
00088             }
00089         }
00090     }
00091     return STATUS_NOT_FOUND;
00092 }
00093 
00094 NTSTATUS
00095 NTAPI
00096 KspMethodHandlerWithAllocator(
00097     IN  PIRP Irp,
00098     IN  ULONG MethodSetsCount,
00099     IN  const KSMETHOD_SET *MethodSet,
00100     IN  PFNKSALLOCATOR Allocator OPTIONAL,
00101     IN  ULONG MethodItemSize OPTIONAL)
00102 {
00103     PKSMETHOD Method;
00104     PKSMETHOD_SET Set;
00105     PIO_STACK_LOCATION IoStack;
00106     NTSTATUS Status;
00107     PFNKSHANDLER MethodHandler = NULL;
00108     ULONG Index;
00109     LPGUID Guid;
00110 
00111     /* get current irp stack */
00112     IoStack = IoGetCurrentIrpStackLocation(Irp);
00113 
00114     /* check if inputbuffer at least holds KSMETHOD item */
00115     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSMETHOD))
00116     {
00117         /* invalid parameter */
00118         Irp->IoStatus.Information = sizeof(KSPROPERTY);
00119         return STATUS_INVALID_BUFFER_SIZE;
00120     }
00121 
00122     /* FIXME probe the input / output buffer if from user mode */
00123 
00124     /* get input property request */
00125     Method = (PKSMETHOD)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
00126 
00127 //    DPRINT("KspMethodHandlerWithAllocator Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
00128 
00129     /* sanity check */
00130     ASSERT(MethodItemSize == 0 || MethodItemSize == sizeof(KSMETHOD_ITEM));
00131 
00132     /* find the method handler */
00133     Status = FindMethodHandler(&Irp->IoStatus, MethodSet, MethodSetsCount, Method, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Irp->UserBuffer, &MethodHandler, &Set);
00134 
00135     if (NT_SUCCESS(Status) && MethodHandler)
00136     {
00137         /* call method handler */
00138         KSMETHOD_SET_IRP_STORAGE(Irp) = Set;
00139         Status = MethodHandler(Irp, Method, Irp->UserBuffer);
00140 
00141         if (Status == STATUS_BUFFER_TOO_SMALL)
00142         {
00143             /* output buffer is too small */
00144             if (Allocator)
00145             {
00146                 /* allocate the requested amount */
00147                 Status = Allocator(Irp, Irp->IoStatus.Information, FALSE);
00148 
00149                 /* check if the block was allocated */
00150                 if (!NT_SUCCESS(Status))
00151                 {
00152                     /* no memory */
00153                     return STATUS_INSUFFICIENT_RESOURCES;
00154                 }
00155 
00156                 /* re-call method handler */
00157                 Status = MethodHandler(Irp, Method, Irp->UserBuffer);
00158             }
00159         }
00160     }
00161     else if (IsEqualGUIDAligned(&Method->Set, &GUID_NULL) && Method->Id == 0 && Method->Flags == KSMETHOD_TYPE_SETSUPPORT)
00162     {
00163         // store output size
00164         Irp->IoStatus.Information = sizeof(GUID) * MethodSetsCount;
00165         if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * MethodSetsCount)
00166         {
00167             // buffer too small
00168             return STATUS_MORE_ENTRIES;
00169         }
00170 
00171         // get output buffer
00172         Guid = (LPGUID)Irp->UserBuffer;
00173 
00174        // copy property guids from property sets
00175        for(Index = 0; Index < MethodSetsCount; Index++)
00176        {
00177            RtlMoveMemory(&Guid[Index], MethodSet[Index].Set, sizeof(GUID));
00178        }
00179        return STATUS_SUCCESS;
00180     }
00181 
00182     /* done */
00183     return Status;
00184 }
00185 
00186 /*
00187     @implemented
00188 */
00189 KSDDKAPI
00190 NTSTATUS
00191 NTAPI
00192 KsMethodHandler(
00193     IN  PIRP Irp,
00194     IN  ULONG MethodSetsCount,
00195     IN  PKSMETHOD_SET MethodSet)
00196 {
00197     return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, NULL, 0);
00198 }
00199 
00200 /*
00201     @implemented
00202 */
00203 KSDDKAPI
00204 NTSTATUS
00205 NTAPI
00206 KsMethodHandlerWithAllocator(
00207     IN  PIRP Irp,
00208     IN  ULONG MethodSetsCount,
00209     IN  PKSMETHOD_SET MethodSet,
00210     IN  PFNKSALLOCATOR Allocator OPTIONAL,
00211     IN  ULONG MethodItemSize OPTIONAL)
00212 {
00213     return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, Allocator, MethodItemSize);
00214 }
00215 
00216 
00217 NTSTATUS
00218 FindFastMethodHandler(
00219     IN ULONG FastIoCount,
00220     IN const KSFASTMETHOD_ITEM * FastIoTable,
00221     IN PKSMETHOD MethodId,
00222     OUT PFNKSFASTHANDLER * FastPropertyHandler)
00223 {
00224     ULONG Index;
00225 
00226     /* iterate through all items */
00227     for(Index = 0; Index < FastIoCount; Index++)
00228     {
00229         if (MethodId->Id == FastIoTable[Index].MethodId)
00230         {
00231             if (FastIoTable[Index].MethodSupported)
00232             {
00233                 *FastPropertyHandler = FastIoTable[Index].MethodHandler;
00234                 return STATUS_SUCCESS;
00235             }
00236         }
00237 
00238     }
00239     /* no fast property handler found */
00240     return STATUS_NOT_FOUND;
00241 }
00242 
00243 
00244 /*
00245     @implemented
00246 */
00247 KSDDKAPI
00248 BOOLEAN
00249 NTAPI
00250 KsFastMethodHandler(
00251     IN  PFILE_OBJECT FileObject,
00252     IN  PKSMETHOD UNALIGNED Method,
00253     IN  ULONG MethodLength,
00254     IN  OUT PVOID UNALIGNED Data,
00255     IN  ULONG DataLength,
00256     OUT PIO_STATUS_BLOCK IoStatus,
00257     IN  ULONG MethodSetsCount,
00258     IN  const KSMETHOD_SET* MethodSet)
00259 {
00260     KSMETHOD MethodRequest;
00261     KPROCESSOR_MODE Mode;
00262     NTSTATUS Status = STATUS_SUCCESS;
00263     ULONG Index;
00264     PFNKSFASTHANDLER FastMethodHandler;
00265 
00266     if (MethodLength < sizeof(KSPROPERTY))
00267     {
00268         /* invalid request */
00269         return FALSE;
00270     }
00271 
00272     /* get previous mode */
00273     Mode = ExGetPreviousMode();
00274 
00275     if (Mode == KernelMode)
00276     {
00277         /* just copy it */
00278         RtlMoveMemory(&MethodRequest, Method, sizeof(KSMETHOD));
00279     }
00280     else
00281     {
00282         /* need to probe the buffer */
00283         _SEH2_TRY
00284         {
00285             ProbeForRead(Method, sizeof(KSPROPERTY), sizeof(UCHAR));
00286             RtlMoveMemory(&MethodRequest, Method, sizeof(KSMETHOD));
00287         }
00288         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00289         {
00290             /* Exception, get the error code */
00291             Status = _SEH2_GetExceptionCode();
00292         }_SEH2_END;
00293 
00294         if (!NT_SUCCESS(Status))
00295             return FALSE;
00296     }
00297 
00298     /* are there any property sets provided */
00299     if (MethodSetsCount)
00300     {
00301         /* iterate through all property sets count */
00302         Index = 0;
00303         do
00304         {
00305             /* does the property id match */
00306             if (IsEqualGUIDAligned(MethodSet[Index].Set, &MethodRequest.Set))
00307             {
00308                 /* try to find a fast property handler */
00309                 Status = FindFastMethodHandler(MethodSet[Index].FastIoCount, MethodSet[Index].FastIoTable, &MethodRequest, &FastMethodHandler);
00310 
00311                 if (NT_SUCCESS(Status))
00312                 {
00313                     /* call fast property handler */
00314                     ASSERT(MethodLength == sizeof(KSMETHOD)); /* FIXME check if property length is bigger -> copy params */
00315                     ASSERT(Mode == KernelMode); /* FIXME need to probe usermode output buffer */
00316                     return FastMethodHandler(FileObject, &MethodRequest, sizeof(KSMETHOD), Data, DataLength, IoStatus);
00317                 }
00318             }
00319             /* move to next item */
00320             Index++;
00321         }while(Index < MethodSetsCount);
00322     }
00323     return FALSE;
00324 }

Generated on Sun May 27 2012 04:27:53 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.