ReactOS  0.4.13-dev-249-gcba1a2f
methods.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: See COPYING in the top level directory
3  * PROJECT: ReactOS Kernel Streaming
4  * FILE: drivers/ksfilter/ks/methods.c
5  * PURPOSE: KS Allocator functions
6  * PROGRAMMER: Johannes Anderwald
7  */
8 
9 #include "precomp.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
17  IN const KSMETHOD_SET* MethodSet,
18  IN ULONG MethodSetCount,
19  IN PKSMETHOD Method,
23  OUT PFNKSHANDLER *MethodHandler,
24  OUT PKSMETHOD_SET * Set)
25 {
26  ULONG Index, ItemIndex;
27 
28  for(Index = 0; Index < MethodSetCount; Index++)
29  {
30  ASSERT(MethodSet[Index].Set);
31 
32  if (IsEqualGUIDAligned(&Method->Set, MethodSet[Index].Set))
33  {
34  for(ItemIndex = 0; ItemIndex < MethodSet[Index].MethodsCount; ItemIndex++)
35  {
36  if (MethodSet[Index].MethodItem[ItemIndex].MethodId == Method->Id)
37  {
38  if (MethodSet[Index].MethodItem[ItemIndex].MinMethod > InputBufferLength)
39  {
40  /* too small input buffer */
41  IoStatus->Information = MethodSet[Index].MethodItem[ItemIndex].MinMethod;
43  }
44 
45  if (MethodSet[Index].MethodItem[ItemIndex].MinData > OutputBufferLength)
46  {
47  /* too small output buffer */
48  IoStatus->Information = MethodSet[Index].MethodItem[ItemIndex].MinData;
49  return STATUS_MORE_ENTRIES;
50  }
51  if (Method->Flags & KSMETHOD_TYPE_BASICSUPPORT)
52  {
53  PULONG Flags;
55 
56  if (sizeof(ULONG) > OutputBufferLength)
57  {
58  /* too small buffer */
60  }
61 
62  /* get output buffer */
64 
65  /* set flags flags */
66  *Flags = MethodSet[Index].MethodItem[ItemIndex].Flags;
67 
68  IoStatus->Information = sizeof(ULONG);
69 
71  {
72  /* get output buffer */
74 
75  /* store result */
76  Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
77  Description->PropTypeSet.Set = KSPROPTYPESETID_General;
78  Description->PropTypeSet.Id = 0;
79  Description->PropTypeSet.Flags = 0;
80  Description->MembersListCount = 0;
81  Description->Reserved = 0;
82 
83  IoStatus->Information = sizeof(KSPROPERTY_DESCRIPTION);
84  }
85  return STATUS_SUCCESS;
86  }
87  *MethodHandler = MethodSet[Index].MethodItem[ItemIndex].MethodHandler;
88  *Set = (PKSMETHOD_SET)&MethodSet[Index];
89  return STATUS_SUCCESS;
90  }
91  }
92  }
93  }
94  return STATUS_NOT_FOUND;
95 }
96 
98 NTAPI
100  IN PIRP Irp,
101  IN ULONG MethodSetsCount,
102  IN const KSMETHOD_SET *MethodSet,
103  IN PFNKSALLOCATOR Allocator OPTIONAL,
104  IN ULONG MethodItemSize OPTIONAL)
105 {
106  PKSMETHOD Method;
107  PKSMETHOD_SET Set;
108  PIO_STACK_LOCATION IoStack;
110  PFNKSHANDLER MethodHandler = NULL;
111  ULONG Index;
112  LPGUID Guid;
113 
114  /* get current irp stack */
116 
117  /* check if inputbuffer at least holds KSMETHOD item */
118  if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSMETHOD))
119  {
120  /* invalid parameter */
121  Irp->IoStatus.Information = sizeof(KSPROPERTY);
123  }
124 
125  /* FIXME probe the input / output buffer if from user mode */
126 
127  /* get input property request */
128  Method = (PKSMETHOD)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
129 
130 // DPRINT("KspMethodHandlerWithAllocator Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
131 
132  /* sanity check */
133  ASSERT(MethodItemSize == 0 || MethodItemSize == sizeof(KSMETHOD_ITEM));
134 
135  /* find the method handler */
136  Status = FindMethodHandler(&Irp->IoStatus, MethodSet, MethodSetsCount, Method, IoStack->Parameters.DeviceIoControl.InputBufferLength, IoStack->Parameters.DeviceIoControl.OutputBufferLength, Irp->UserBuffer, &MethodHandler, &Set);
137 
138  if (NT_SUCCESS(Status) && MethodHandler)
139  {
140  /* call method handler */
141  KSMETHOD_SET_IRP_STORAGE(Irp) = Set;
142  Status = MethodHandler(Irp, Method, Irp->UserBuffer);
143 
145  {
146  /* output buffer is too small */
147  if (Allocator)
148  {
149  /* allocate the requested amount */
150  Status = Allocator(Irp, (ULONG)Irp->IoStatus.Information, FALSE);
151 
152  /* check if the block was allocated */
153  if (!NT_SUCCESS(Status))
154  {
155  /* no memory */
157  }
158 
159  /* re-call method handler */
160  Status = MethodHandler(Irp, Method, Irp->UserBuffer);
161  }
162  }
163  }
164  else if (IsEqualGUIDAligned(&Method->Set, &GUID_NULL) && Method->Id == 0 && Method->Flags == KSMETHOD_TYPE_SETSUPPORT)
165  {
166  // store output size
167  Irp->IoStatus.Information = sizeof(GUID) * MethodSetsCount;
168  if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GUID) * MethodSetsCount)
169  {
170  // buffer too small
171  return STATUS_MORE_ENTRIES;
172  }
173 
174  // get output buffer
175  Guid = (LPGUID)Irp->UserBuffer;
176 
177  // copy property guids from property sets
178  for(Index = 0; Index < MethodSetsCount; Index++)
179  {
180  RtlMoveMemory(&Guid[Index], MethodSet[Index].Set, sizeof(GUID));
181  }
182  return STATUS_SUCCESS;
183  }
184 
185  /* done */
186  return Status;
187 }
188 
189 /*
190  @implemented
191 */
193 KSDDKAPI
194 NTSTATUS
195 NTAPI
196 KsMethodHandler(
197  _In_ PIRP Irp,
198  _In_ ULONG MethodSetsCount,
199  _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet)
200 {
201  return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, NULL, 0);
202 }
203 
204 /*
205  @implemented
206 */
208 KSDDKAPI
209 NTSTATUS
210 NTAPI
211 KsMethodHandlerWithAllocator(
212  _In_ PIRP Irp,
213  _In_ ULONG MethodSetsCount,
214  _In_reads_(MethodSetsCount) const KSMETHOD_SET* MethodSet,
215  _In_opt_ PFNKSALLOCATOR Allocator,
216  _In_opt_ ULONG MethodItemSize)
217 {
218  return KspMethodHandlerWithAllocator(Irp, MethodSetsCount, MethodSet, Allocator, MethodItemSize);
219 }
220 
221 
222 NTSTATUS
224  IN ULONG FastIoCount,
225  IN const KSFASTMETHOD_ITEM * FastIoTable,
227  OUT PFNKSFASTHANDLER * FastPropertyHandler)
228 {
229  ULONG Index;
230 
231  /* iterate through all items */
232  for(Index = 0; Index < FastIoCount; Index++)
233  {
234  if (MethodId->Id == FastIoTable[Index].MethodId)
235  {
236  if (FastIoTable[Index].MethodSupported)
237  {
238  *FastPropertyHandler = FastIoTable[Index].MethodHandler;
239  return STATUS_SUCCESS;
240  }
241  }
242 
243  }
244  /* no fast property handler found */
245  return STATUS_NOT_FOUND;
246 }
247 
248 
249 /*
250  @implemented
251 */
252 KSDDKAPI
253 BOOLEAN
254 NTAPI
257  IN PKSMETHOD UNALIGNED Method,
258  IN ULONG MethodLength,
262  IN ULONG MethodSetsCount,
263  IN const KSMETHOD_SET* MethodSet)
264 {
265  KSMETHOD MethodRequest;
268  ULONG Index;
269  PFNKSFASTHANDLER FastMethodHandler;
270 
271  if (MethodLength < sizeof(KSPROPERTY))
272  {
273  /* invalid request */
274  return FALSE;
275  }
276 
277  /* get previous mode */
279 
280  if (Mode == KernelMode)
281  {
282  /* just copy it */
283  RtlMoveMemory(&MethodRequest, Method, sizeof(KSMETHOD));
284  }
285  else
286  {
287  /* need to probe the buffer */
288  _SEH2_TRY
289  {
290  ProbeForRead(Method, sizeof(KSPROPERTY), sizeof(UCHAR));
291  RtlMoveMemory(&MethodRequest, Method, sizeof(KSMETHOD));
292  }
294  {
295  /* Exception, get the error code */
297  }_SEH2_END;
298 
299  if (!NT_SUCCESS(Status))
300  return FALSE;
301  }
302 
303  /* are there any property sets provided */
304  if (MethodSetsCount)
305  {
306  /* iterate through all property sets count */
307  Index = 0;
308  do
309  {
310  /* does the property id match */
311  if (IsEqualGUIDAligned(MethodSet[Index].Set, &MethodRequest.Set))
312  {
313  /* try to find a fast property handler */
314  Status = FindFastMethodHandler(MethodSet[Index].FastIoCount, MethodSet[Index].FastIoTable, &MethodRequest, &FastMethodHandler);
315 
316  if (NT_SUCCESS(Status))
317  {
318  /* call fast property handler */
319  ASSERT(MethodLength == sizeof(KSMETHOD)); /* FIXME check if property length is bigger -> copy params */
320  ASSERT(Mode == KernelMode); /* FIXME need to probe usermode output buffer */
321  return FastMethodHandler(FileObject, &MethodRequest, sizeof(KSMETHOD), Data, DataLength, IoStatus);
322  }
323  }
324  /* move to next item */
325  Index++;
326  }while(Index < MethodSetsCount);
327  }
328  return FALSE;
329 }
struct KSIDENTIFIER KSPROPERTY
#define IN
Definition: typedefs.h:38
NTSTATUS NTAPI KspMethodHandlerWithAllocator(IN PIRP Irp, IN ULONG MethodSetsCount, IN const KSMETHOD_SET *MethodSet, IN PFNKSALLOCATOR Allocator OPTIONAL, IN ULONG MethodItemSize OPTIONAL)
Definition: methods.c:99
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS FindMethodHandler(IN PIO_STATUS_BLOCK IoStatus, IN const KSMETHOD_SET *MethodSet, IN ULONG MethodSetCount, IN PKSMETHOD Method, IN ULONG InputBufferLength, IN ULONG OutputBufferLength, OUT PVOID OutputBuffer, OUT PFNKSHANDLER *MethodHandler, OUT PKSMETHOD_SET *Set)
Definition: methods.c:15
_In_ ULONG Mode
Definition: hubbusif.h:303
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
_In_ PIRP Irp
Definition: csq.h:116
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define _In_reads_(size)
Definition: no_sal2.h:228
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG _In_ ULONG OutputBufferLength
Definition: fltkernel.h:1374
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:2982
const GUID KSPROPTYPESETID_General
Definition: property.c:17
static const WCHAR Description[]
Definition: oid.c:1266
#define KSDDKAPI
Definition: ks.h:40
GUID Set
Definition: dmksctrl.h:76
#define _In_opt_
Definition: no_sal2.h:213
static BOOL Set
Definition: pageheap.c:10
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
KSDDKAPI BOOLEAN NTAPI KsFastMethodHandler(IN PFILE_OBJECT FileObject, IN PKSMETHOD UNALIGNED Method, IN ULONG MethodLength, IN OUT PVOID UNALIGNED Data, IN ULONG DataLength, OUT PIO_STATUS_BLOCK IoStatus, IN ULONG MethodSetsCount, IN const KSMETHOD_SET *MethodSet)
Definition: methods.c:255
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
_SEH2_TRY
Definition: create.c:4250
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:233
#define KSMETHOD_TYPE_BASICSUPPORT
Definition: dmksctrl.h:41
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
static GUID * Guid
Definition: apphelp.c:93
smooth NULL
Definition: ftsmooth.c:416
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
#define STATUS_INVALID_BUFFER_SIZE
Definition: ntstatus.h:636
_In_ PIRP _In_ ULONG _In_ ULONG MethodId
Definition: classpnp.h:429
#define UNALIGNED
Definition: crtdefs.h:132
_IRQL_requires_max_(PASSIVE_LEVEL)
Definition: methods.c:192
#define STATUS_NOT_FOUND
Definition: shellext.h:67
ULONG Id
Definition: dmksctrl.h:77
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct KSIDENTIFIER * PKSMETHOD
static const UCHAR Index[8]
Definition: usbohci.c:18
NTSTATUS FindFastMethodHandler(IN ULONG FastIoCount, IN const KSFASTMETHOD_ITEM *FastIoTable, IN PKSMETHOD MethodId, OUT PFNKSFASTHANDLER *FastPropertyHandler)
Definition: methods.c:223
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
* PFILE_OBJECT
Definition: iotypes.h:1954
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONG Flags
Definition: dmksctrl.h:78
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define GUID_NULL
Definition: ks.h:106
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define STATUS_MORE_ENTRIES
Definition: udferr_usr.h:124
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
Status
Definition: gdiplustypes.h:24
#define _In_
Definition: no_sal2.h:204
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
struct _GUID GUID
_SEH2_END
Definition: create.c:4424
#define KSMETHOD_TYPE_SETSUPPORT
Definition: dmksctrl.h:40
unsigned int * PULONG
Definition: retypes.h:1
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
return STATUS_SUCCESS
Definition: btrfs.c:2745
struct KSPROPERTY_DESCRIPTION * PKSPROPERTY_DESCRIPTION
GUID * LPGUID
Definition: guiddef.h:76
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68