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

api.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/api.c
00005  * PURPOSE:         KS API functions
00006  * PROGRAMMER:      Johannes Anderwald
00007  */
00008 
00009 
00010 #include "priv.h"
00011 
00012 const GUID GUID_NULL              = {0x00000000L, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
00013 const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
00014 
00015 /*
00016     @implemented
00017 */
00018 KSDDKAPI
00019 NTSTATUS
00020 NTAPI
00021 KsAcquireResetValue(
00022     IN  PIRP Irp,
00023     OUT KSRESET* ResetValue)
00024 {
00025     PIO_STACK_LOCATION IoStack;
00026     KSRESET* Value;
00027     NTSTATUS Status = STATUS_SUCCESS;
00028 
00029     /* get current irp stack */
00030     IoStack = IoGetCurrentIrpStackLocation(Irp);
00031 
00032     /* check if there is reset value provided */
00033     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSRESET))
00034         return STATUS_INVALID_PARAMETER;
00035 
00036     if (Irp->RequestorMode == UserMode)
00037     {
00038         /* need to probe the buffer */
00039         _SEH2_TRY
00040         {
00041             ProbeForRead(IoStack->Parameters.DeviceIoControl.Type3InputBuffer, sizeof(KSRESET), sizeof(UCHAR));
00042             Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
00043             *ResetValue = *Value;
00044         }
00045         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00046         {
00047             /* Exception, get the error code */
00048             Status = _SEH2_GetExceptionCode();
00049         }
00050         _SEH2_END;
00051     }
00052     else
00053     {
00054         Value = (KSRESET*)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
00055         *ResetValue = *Value;
00056     }
00057 
00058     return Status;
00059 }
00060 
00061 /*
00062     @implemented
00063 */
00064 KSDDKAPI
00065 VOID
00066 NTAPI
00067 KsAcquireDeviceSecurityLock(
00068     IN KSDEVICE_HEADER DevHeader,
00069     IN BOOLEAN Exclusive)
00070 {
00071     PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
00072 
00073     KeEnterCriticalRegion();
00074 
00075     if (Exclusive)
00076     {
00077         ExAcquireResourceExclusiveLite(&Header->SecurityLock, TRUE);
00078     }
00079     else
00080     {
00081         ExAcquireResourceSharedLite(&Header->SecurityLock, TRUE);
00082     }
00083 }
00084 
00085 /*
00086     @implemented
00087 */
00088 KSDDKAPI
00089 VOID
00090 NTAPI
00091 KsReleaseDeviceSecurityLock(
00092     IN KSDEVICE_HEADER DevHeader)
00093 {
00094     PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
00095 
00096     DPRINT("KsReleaseDevice\n");
00097 
00098     ExReleaseResourceLite(&Header->SecurityLock);
00099     KeLeaveCriticalRegion();
00100 }
00101 
00102 /*
00103     @implemented
00104 */
00105 KSDDKAPI
00106 NTSTATUS
00107 NTAPI
00108 KsDefaultDispatchPnp(
00109     IN  PDEVICE_OBJECT DeviceObject,
00110     IN  PIRP Irp)
00111 {
00112     PDEVICE_EXTENSION DeviceExtension;
00113     PKSIDEVICE_HEADER DeviceHeader;
00114     PIO_STACK_LOCATION IoStack;
00115     PDEVICE_OBJECT PnpDeviceObject;
00116     NTSTATUS Status;
00117     ULONG MinorFunction;
00118 
00119     /* get current irp stack */
00120     IoStack = IoGetCurrentIrpStackLocation(Irp);
00121 
00122     /* caller wants to add the target device */
00123     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00124 
00125     /* get device header */
00126     DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00127 
00128     /* backup PnpBaseObject */
00129     PnpDeviceObject = DeviceHeader->PnpDeviceObject;
00130 
00131 
00132     /* backup minor function code */
00133     MinorFunction = IoStack->MinorFunction;
00134 
00135     if(MinorFunction == IRP_MN_REMOVE_DEVICE)
00136     {
00137         /* remove the device */
00138         KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
00139     }
00140 
00141     /* skip current irp stack */
00142     IoSkipCurrentIrpStackLocation(Irp);
00143 
00144     /* call attached pnp device object */
00145     Status = IoCallDriver(PnpDeviceObject, Irp);
00146 
00147     if (MinorFunction == IRP_MN_REMOVE_DEVICE)
00148     {
00149         /* time is over */
00150         IoDetachDevice(PnpDeviceObject);
00151         /* delete device */
00152         IoDeleteDevice(DeviceObject);
00153     }
00154     /* done */
00155     return Status;
00156 }
00157 
00158 /*
00159     @implemented
00160 */
00161 KSDDKAPI
00162 NTSTATUS
00163 NTAPI
00164 KsDefaultDispatchPower(
00165     IN  PDEVICE_OBJECT DeviceObject,
00166     IN  PIRP Irp)
00167 {
00168     PDEVICE_EXTENSION DeviceExtension;
00169     PKSIDEVICE_HEADER DeviceHeader;
00170     PKSIOBJECT_HEADER ObjectHeader;
00171     //PIO_STACK_LOCATION IoStack;
00172     PLIST_ENTRY ListEntry;
00173     NTSTATUS Status;
00174 
00175     /* get current irp stack */
00176     //IoStack = IoGetCurrentIrpStackLocation(Irp);
00177 
00178     /* caller wants to add the target device */
00179     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00180 
00181     /* get device header */
00182     DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00183 
00184     /* FIXME locks */
00185 
00186     /* loop our power dispatch list and call registered notification functions */
00187     ListEntry = DeviceHeader->PowerDispatchList.Flink;
00188     /* let's go */
00189     while(ListEntry != &DeviceHeader->PowerDispatchList)
00190     {
00191         /* get object header */
00192         ObjectHeader = (PKSIOBJECT_HEADER)CONTAINING_RECORD(ListEntry, KSIOBJECT_HEADER, PowerDispatchEntry);
00193 
00194         /* does it have still a cb */
00195         if (ObjectHeader->PowerDispatch)
00196         {
00197             /* call the power cb */
00198             Status = ObjectHeader->PowerDispatch(ObjectHeader->PowerContext, Irp);
00199             ASSERT(NT_SUCCESS(Status));
00200         }
00201 
00202         /* iterate to next entry */
00203         ListEntry = ListEntry->Flink;
00204     }
00205 
00206     /* start next power irp */
00207     PoStartNextPowerIrp(Irp);
00208 
00209     /* skip current irp stack location */
00210     IoSkipCurrentIrpStackLocation(Irp);
00211 
00212     /* let's roll */
00213     Status = PoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
00214 
00215     /* done */
00216     return Status;
00217 }
00218 
00219 /*
00220     @implemented
00221 */
00222 KSDDKAPI
00223 NTSTATUS
00224 NTAPI
00225 KsDefaultForwardIrp(
00226     IN PDEVICE_OBJECT DeviceObject,
00227     IN PIRP Irp)
00228 {
00229     PDEVICE_EXTENSION DeviceExtension;
00230     PKSIDEVICE_HEADER DeviceHeader;
00231     //PIO_STACK_LOCATION IoStack;
00232     NTSTATUS Status;
00233 
00234     /* get current irp stack */
00235     //IoStack = IoGetCurrentIrpStackLocation(Irp);
00236 
00237     /* caller wants to add the target device */
00238     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
00239 
00240     /* get device header */
00241     DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00242 
00243     /* forward the request to the PDO */
00244     Status = IoCallDriver(DeviceHeader->PnpDeviceObject, Irp);
00245 
00246     return Status;
00247 }
00248 
00249 /*
00250     @implemented
00251 */
00252 KSDDKAPI
00253 VOID
00254 NTAPI
00255 KsSetDevicePnpAndBaseObject(
00256     IN  KSDEVICE_HEADER Header,
00257     IN  PDEVICE_OBJECT PnpDeviceObject,
00258     IN  PDEVICE_OBJECT BaseDevice)
00259 {
00260     PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
00261 
00262     DeviceHeader->PnpDeviceObject = PnpDeviceObject;
00263     DeviceHeader->BaseDevice = BaseDevice;
00264 }
00265 
00266 /*
00267     @implemented
00268 */
00269 KSDDKAPI
00270 PDEVICE_OBJECT
00271 NTAPI
00272 KsQueryDevicePnpObject(
00273     IN  KSDEVICE_HEADER Header)
00274 {
00275     PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
00276 
00277     /* return PnpDeviceObject */
00278     return DeviceHeader->PnpDeviceObject;
00279 
00280 }
00281 
00282 /*
00283     @implemented
00284 */
00285 KSDDKAPI
00286 ACCESS_MASK
00287 NTAPI
00288 KsQueryObjectAccessMask(
00289     IN KSOBJECT_HEADER Header)
00290 {
00291     PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
00292 
00293     /* return access mask */
00294     return ObjectHeader->AccessMask;
00295 
00296 }
00297 
00298 /*
00299     @unimplemented
00300 */
00301 KSDDKAPI
00302 VOID
00303 NTAPI
00304 KsRecalculateStackDepth(
00305     IN  KSDEVICE_HEADER Header,
00306     IN  BOOLEAN ReuseStackLocation)
00307 {
00308     UNIMPLEMENTED;
00309 }
00310 
00311 
00312 /*
00313     @implemented
00314 */
00315 KSDDKAPI
00316 VOID
00317 NTAPI
00318 KsSetTargetState(
00319     IN  KSOBJECT_HEADER Header,
00320     IN  KSTARGET_STATE TargetState)
00321 {
00322     PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
00323 
00324     /* set target state */
00325     DeviceHeader->TargetState = TargetState;
00326 }
00327 
00328 /*
00329     @implemented
00330 */
00331 KSDDKAPI
00332 VOID
00333 NTAPI
00334 KsSetTargetDeviceObject(
00335     IN  KSOBJECT_HEADER Header,
00336     IN  PDEVICE_OBJECT TargetDevice OPTIONAL)
00337 {
00338     PDEVICE_EXTENSION DeviceExtension;
00339     PKSIDEVICE_HEADER DeviceHeader;
00340     PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
00341 
00342     if(ObjectHeader->TargetDevice)
00343     {
00344         /* there is already a target device set */
00345         if (!TargetDevice)
00346         {
00347             /* caller wants to remove the target device */
00348             DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->TargetDevice->DeviceExtension;
00349 
00350             /* get device header */
00351             DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00352 
00353             /* acquire lock */
00354             KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
00355 
00356             /* remove entry */
00357             RemoveEntryList(&ObjectHeader->TargetDeviceListEntry);
00358 
00359             /* remove device pointer */
00360             ObjectHeader->TargetDevice = NULL;
00361 
00362             /* release lock */
00363             KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
00364         }
00365     }
00366     else
00367     {
00368         /* no target device yet set */
00369         if (TargetDevice)
00370         {
00371             /* caller wants to add the target device */
00372             DeviceExtension = (PDEVICE_EXTENSION)TargetDevice->DeviceExtension;
00373 
00374             /* get device header */
00375             DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00376 
00377             /* acquire lock */
00378             KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
00379 
00380             /* insert list entry */
00381             InsertTailList(&DeviceHeader->TargetDeviceList, &ObjectHeader->TargetDeviceListEntry);
00382 
00383             /* store target device */
00384             ObjectHeader->TargetDevice = TargetDevice;
00385 
00386             /* release lock */
00387             KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
00388         }
00389     }
00390 
00391 }
00392 
00393 /*
00394     @implemented
00395 */
00396 KSDDKAPI
00397 VOID
00398 NTAPI
00399 KsSetPowerDispatch(
00400     IN  KSOBJECT_HEADER Header,
00401     IN  PFNKSCONTEXT_DISPATCH PowerDispatch OPTIONAL,
00402     IN  PVOID PowerContext OPTIONAL)
00403 {
00404     PDEVICE_EXTENSION DeviceExtension;
00405     PKSIDEVICE_HEADER DeviceHeader;
00406     PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
00407 
00408     /* caller wants to add the target device */
00409     DeviceExtension = (PDEVICE_EXTENSION)ObjectHeader->ParentDeviceObject->DeviceExtension;
00410 
00411     /* get device header */
00412     DeviceHeader = (PKSIDEVICE_HEADER)DeviceExtension->DeviceHeader;
00413 
00414     /* acquire lock */
00415     KsAcquireDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader, FALSE);
00416 
00417     if (PowerDispatch)
00418     {
00419         /* add power dispatch entry */
00420         InsertTailList(&DeviceHeader->PowerDispatchList, &ObjectHeader->PowerDispatchEntry);
00421 
00422        /* store function and context */
00423        ObjectHeader->PowerDispatch = PowerDispatch;
00424        ObjectHeader->PowerContext = PowerContext;
00425     }
00426     else
00427     {
00428         /* remove power dispatch entry */
00429         RemoveEntryList(&ObjectHeader->PowerDispatchEntry);
00430 
00431        /* store function and context */
00432        ObjectHeader->PowerDispatch = NULL;
00433        ObjectHeader->PowerContext = NULL;
00434 
00435     }
00436 
00437     /* release lock */
00438     KsReleaseDeviceSecurityLock((KSDEVICE_HEADER)DeviceHeader);
00439 }
00440 
00441 
00442 /*
00443     @implemented
00444 */
00445 KSDDKAPI
00446 PKSOBJECT_CREATE_ITEM
00447 NTAPI
00448 KsQueryObjectCreateItem(
00449     IN KSOBJECT_HEADER Header)
00450 {
00451     PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER)Header;
00452     return ObjectHeader->OriginalCreateItem;
00453 }
00454 
00455 NTSTATUS
00456 KspAddCreateItemToList(
00457     OUT PLIST_ENTRY ListHead,
00458     IN ULONG ItemsCount,
00459     IN  PKSOBJECT_CREATE_ITEM ItemsList)
00460 {
00461     ULONG Index;
00462     PCREATE_ITEM_ENTRY Entry;
00463 
00464     /* add the items */
00465     for(Index = 0; Index < ItemsCount; Index++)
00466     {
00467         /* allocate item */
00468         Entry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
00469         if (!Entry)
00470         {
00471             /* no memory */
00472             return STATUS_INSUFFICIENT_RESOURCES;
00473         }
00474 
00475         /* initialize entry */
00476         InitializeListHead(&Entry->ObjectItemList);
00477         Entry->CreateItem = &ItemsList[Index];
00478         Entry->ReferenceCount = 0;
00479         Entry->ItemFreeCallback = NULL;
00480 
00481         InsertTailList(ListHead, &Entry->Entry);
00482     }
00483     return STATUS_SUCCESS;
00484 }
00485 
00486 VOID
00487 KspFreeCreateItems(
00488     PLIST_ENTRY ListHead)
00489 {
00490     PCREATE_ITEM_ENTRY Entry;
00491 
00492     while(!IsListEmpty(ListHead))
00493     {
00494         /* remove create item from list */
00495         Entry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(RemoveHeadList(ListHead), CREATE_ITEM_ENTRY, Entry);
00496 
00497         /* caller shouldnt have any references */
00498         //ASSERT(Entry->ReferenceCount == 0);
00499         //ASSERT(IsListEmpty(&Entry->ObjectItemList));
00500 
00501         /* does the creator wish notification */
00502         if (Entry->ItemFreeCallback)
00503         {
00504             /* notify creator */
00505             Entry->ItemFreeCallback(Entry->CreateItem);
00506         }
00507 
00508         /* free create item entry */
00509          FreeItem(Entry);
00510     }
00511 
00512 }
00513 
00514 /*
00515     @implemented
00516 */
00517 KSDDKAPI
00518 NTSTATUS
00519 NTAPI
00520 KsAllocateDeviceHeader(
00521     OUT KSDEVICE_HEADER* OutHeader,
00522     IN  ULONG ItemsCount,
00523     IN  PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL)
00524 {
00525     NTSTATUS Status = STATUS_SUCCESS;
00526     PKSIDEVICE_HEADER Header;
00527 
00528     if (!OutHeader)
00529         return STATUS_INVALID_PARAMETER;
00530 
00531     /* allocate a device header */
00532     Header = AllocateItem(PagedPool, sizeof(KSIDEVICE_HEADER));
00533 
00534     /* check for success */
00535     if (!Header)
00536         return STATUS_INSUFFICIENT_RESOURCES;
00537 
00538     /* clear all memory */
00539     RtlZeroMemory(Header, sizeof(KSIDEVICE_HEADER));
00540 
00541     /* initialize device mutex */
00542     KeInitializeMutex(&Header->DeviceMutex, 0);
00543 
00544     /* initialize target device list */
00545     InitializeListHead(&Header->TargetDeviceList);
00546     /* initialize power dispatch list */
00547     InitializeListHead(&Header->PowerDispatchList);
00548     /* initialize object bag lists */
00549     InitializeListHead(&Header->ObjectBags);
00550 
00551     /* initialize create item list */
00552     InitializeListHead(&Header->ItemList);
00553 
00554     /* initialize basic header */
00555     Header->BasicHeader.Type = KsObjectTypeDevice;
00556     Header->BasicHeader.KsDevice = &Header->KsDevice;
00557     Header->BasicHeader.Parent.KsDevice = &Header->KsDevice;
00558 
00559     /* are there any create items provided */
00560     if (ItemsCount && ItemsList)
00561     {
00562         Status = KspAddCreateItemToList(&Header->ItemList, ItemsCount, ItemsList);
00563 
00564         if (NT_SUCCESS(Status))
00565         {
00566             /* store item count */
00567             Header->ItemListCount = ItemsCount;
00568         }
00569         else
00570         {
00571             /* release create items */
00572             KspFreeCreateItems(&Header->ItemList);
00573         }
00574     }
00575 
00576     /* store result */
00577     *OutHeader = Header;
00578 
00579     return Status;
00580 }
00581 
00582 /*
00583     @implemented
00584 */
00585 KSDDKAPI
00586 VOID
00587 NTAPI
00588 KsFreeDeviceHeader(
00589     IN  KSDEVICE_HEADER DevHeader)
00590 {
00591     PKSIDEVICE_HEADER Header;
00592 
00593     Header = (PKSIDEVICE_HEADER)DevHeader;
00594 
00595     if (!DevHeader)
00596         return;
00597 
00598     KspFreeCreateItems(&Header->ItemList);
00599     FreeItem(Header);
00600 }
00601 
00602 /*
00603     @implemented
00604 */
00605 KSDDKAPI
00606 NTSTATUS
00607 NTAPI
00608 KsAllocateObjectHeader(
00609     OUT KSOBJECT_HEADER *Header,
00610     IN  ULONG ItemsCount,
00611     IN  PKSOBJECT_CREATE_ITEM ItemsList OPTIONAL,
00612     IN  PIRP Irp,
00613     IN  KSDISPATCH_TABLE* Table)
00614 {
00615     PIO_STACK_LOCATION IoStack;
00616     //PDEVICE_EXTENSION DeviceExtension;
00617     //PKSIDEVICE_HEADER DeviceHeader;
00618     PKSIOBJECT_HEADER ObjectHeader;
00619     //PKSOBJECT_CREATE_ITEM CreateItem;
00620     NTSTATUS Status;
00621 
00622     if (!Header)
00623         return STATUS_INVALID_PARAMETER_1;
00624 
00625     if (!Irp)
00626         return STATUS_INVALID_PARAMETER_4;
00627 
00628     if (!Table)
00629         return STATUS_INVALID_PARAMETER_5;
00630 
00631     /* get current stack location */
00632     IoStack = IoGetCurrentIrpStackLocation(Irp);
00633     /* get device extension */
00634     //DeviceExtension = (PDEVICE_EXTENSION)IoStack->DeviceObject->DeviceExtension;
00635     /* get device header */
00636     //DeviceHeader = DeviceExtension->DeviceHeader;
00637 
00638     /* sanity check */
00639     ASSERT(IoStack->FileObject);
00640     /* check for an file object */
00641 
00642     /* allocate the object header */
00643     ObjectHeader = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_HEADER));
00644     if (!ObjectHeader)
00645         return STATUS_INSUFFICIENT_RESOURCES;
00646 
00647     /* initialize object header */
00648     RtlZeroMemory(ObjectHeader, sizeof(KSIOBJECT_HEADER));
00649 
00650     /* initialize create item list */
00651     InitializeListHead(&ObjectHeader->ItemList);
00652 
00653     /* get create item */
00654     //CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
00655 
00656     /* do we have a name */
00657     if (IoStack->FileObject->FileName.Buffer)
00658     {
00659         /* copy object class */
00660         ObjectHeader->ObjectClass.MaximumLength = IoStack->FileObject->FileName.MaximumLength;
00661         ObjectHeader->ObjectClass.Buffer = AllocateItem(NonPagedPool, ObjectHeader->ObjectClass.MaximumLength);
00662         if (!ObjectHeader->ObjectClass.Buffer)
00663         {
00664             FreeItem(ObjectHeader);
00665             return STATUS_INSUFFICIENT_RESOURCES;
00666         }
00667         RtlCopyUnicodeString(&ObjectHeader->ObjectClass, &IoStack->FileObject->FileName);
00668     }
00669 
00670     /* copy dispatch table */
00671     RtlCopyMemory(&ObjectHeader->DispatchTable, Table, sizeof(KSDISPATCH_TABLE));
00672 
00673     /* store create items */
00674     if (ItemsCount && ItemsList)
00675     {
00676         Status = KspAddCreateItemToList(&ObjectHeader->ItemList, ItemsCount, ItemsList);
00677 
00678         if (NT_SUCCESS(Status))
00679         {
00680             /* store item count */
00681             ObjectHeader->ItemListCount = ItemsCount;
00682         }
00683         else
00684         {
00685             /* destroy header*/
00686             KsFreeObjectHeader(ObjectHeader);
00687             return Status;
00688         }
00689     }
00690     /* store the object in the file object */
00691     IoStack->FileObject->FsContext2 = ObjectHeader;
00692 
00693     /* store parent device */
00694     ObjectHeader->ParentDeviceObject = IoGetRelatedDeviceObject(IoStack->FileObject);
00695 
00696     /* store originating create item */
00697     ObjectHeader->OriginalCreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
00698 
00699     /* FIXME store access mask see KsQueryObjectAccessMask */
00700     ObjectHeader->AccessMask = IoStack->Parameters.Create.SecurityContext->DesiredAccess;
00701 
00702 
00703     /* store result */
00704     *Header = ObjectHeader;
00705 
00706     DPRINT("KsAllocateObjectHeader ObjectClass %S FileObject %p, ObjectHeader %p\n", ObjectHeader->ObjectClass.Buffer, IoStack->FileObject, ObjectHeader);
00707 
00708     return STATUS_SUCCESS;
00709 
00710 }
00711 
00712 /*
00713     @implemented
00714 */
00715 KSDDKAPI
00716 VOID
00717 NTAPI
00718 KsFreeObjectHeader(
00719     IN  PVOID Header)
00720 {
00721     PKSIOBJECT_HEADER ObjectHeader = (PKSIOBJECT_HEADER) Header;
00722 
00723     DPRINT("KsFreeObjectHeader Header %p Class %wZ\n", Header, &ObjectHeader->ObjectClass);
00724 
00725     if (ObjectHeader->ObjectClass.Buffer)
00726     {
00727         /* release object class buffer */
00728         FreeItem(ObjectHeader->ObjectClass.Buffer);
00729     }
00730 
00731     if (ObjectHeader->Unknown)
00732     {
00733         /* release associated object */
00734         ObjectHeader->Unknown->lpVtbl->Release(ObjectHeader->Unknown);
00735     }
00736 
00737     /* free create items */
00738     KspFreeCreateItems(&ObjectHeader->ItemList);
00739 
00740     /* free object header */
00741     FreeItem(ObjectHeader);
00742 
00743 }
00744 
00745 NTSTATUS
00746 KspAddObjectCreateItemToList(
00747     PLIST_ENTRY ListHead,
00748     IN  PDRIVER_DISPATCH Create,
00749     IN  PVOID Context,
00750     IN  PWCHAR ObjectClass,
00751     IN  PSECURITY_DESCRIPTOR SecurityDescriptor)
00752 {
00753    PLIST_ENTRY Entry;
00754    PCREATE_ITEM_ENTRY CreateEntry;
00755 
00756     /* point to first entry */
00757     Entry = ListHead->Flink;
00758 
00759     while(Entry != ListHead)
00760     {
00761         /* get create entry */
00762         CreateEntry = (PCREATE_ITEM_ENTRY)CONTAINING_RECORD(Entry, CREATE_ITEM_ENTRY, Entry);
00763         /* if the create item has no create routine, then it is free to use */
00764         if (CreateEntry->CreateItem->Create == NULL)
00765         {
00766             /* sanity check */
00767             ASSERT(IsListEmpty(&CreateEntry->ObjectItemList));
00768             ASSERT(CreateEntry->ReferenceCount == 0);
00769             /* use free entry */
00770             CreateEntry->CreateItem->Context = Context;
00771             CreateEntry->CreateItem->Create = Create;
00772             RtlInitUnicodeString(&CreateEntry->CreateItem->ObjectClass, ObjectClass);
00773             CreateEntry->CreateItem->SecurityDescriptor = SecurityDescriptor;
00774 
00775             return STATUS_SUCCESS;
00776         }
00777 
00778         if (!wcsicmp(ObjectClass, CreateEntry->CreateItem->ObjectClass.Buffer))
00779         {
00780             /* the same object class already exists */
00781             return STATUS_OBJECT_NAME_COLLISION;
00782         }
00783 
00784         /* iterate to next entry */
00785         Entry = Entry->Flink;
00786     }
00787     return STATUS_ALLOTTED_SPACE_EXCEEDED;
00788 }
00789 
00790 /*
00791     @implemented
00792 */
00793 KSDDKAPI
00794 NTSTATUS
00795 NTAPI
00796 KsAddObjectCreateItemToDeviceHeader(
00797     IN  KSDEVICE_HEADER DevHeader,
00798     IN  PDRIVER_DISPATCH Create,
00799     IN  PVOID Context,
00800     IN  PWCHAR ObjectClass,
00801     IN  PSECURITY_DESCRIPTOR SecurityDescriptor)
00802 {
00803     PKSIDEVICE_HEADER Header;
00804     NTSTATUS Status;
00805 
00806     Header = (PKSIDEVICE_HEADER)DevHeader;
00807 
00808     DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
00809 
00810      /* check if a device header has been provided */
00811     if (!DevHeader)
00812         return STATUS_INVALID_PARAMETER_1;
00813 
00814     /* check if a create item has been provided */
00815     if (!Create)
00816         return STATUS_INVALID_PARAMETER_2;
00817 
00818     /* check if a object class has been provided */
00819     if (!ObjectClass)
00820         return STATUS_INVALID_PARAMETER_4;
00821 
00822     /* let others do the work */
00823     Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
00824 
00825     if (NT_SUCCESS(Status))
00826     {
00827         /* increment create item count */
00828         InterlockedIncrement(&Header->ItemListCount);
00829     }
00830     DPRINT("KsAddObjectCreateItemToDeviceHeader Status %x\n", Status);
00831     return Status;
00832 }
00833 
00834 /*
00835     @implemented
00836 */
00837 KSDDKAPI
00838 NTSTATUS
00839 NTAPI
00840 KsAddObjectCreateItemToObjectHeader(
00841     IN  KSOBJECT_HEADER ObjectHeader,
00842     IN  PDRIVER_DISPATCH Create,
00843     IN  PVOID Context,
00844     IN  PWCHAR ObjectClass,
00845     IN  PSECURITY_DESCRIPTOR SecurityDescriptor)
00846 {
00847     PKSIOBJECT_HEADER Header;
00848     NTSTATUS Status;
00849 
00850     Header = (PKSIOBJECT_HEADER)ObjectHeader;
00851 
00852     DPRINT("KsAddObjectCreateItemToDeviceHeader entered\n");
00853 
00854      /* check if a device header has been provided */
00855     if (!Header)
00856         return STATUS_INVALID_PARAMETER_1;
00857 
00858     /* check if a create item has been provided */
00859     if (!Create)
00860         return STATUS_INVALID_PARAMETER_2;
00861 
00862     /* check if a object class has been provided */
00863     if (!ObjectClass)
00864         return STATUS_INVALID_PARAMETER_4;
00865 
00866     /* let's work */
00867     Status = KspAddObjectCreateItemToList(&Header->ItemList, Create, Context, ObjectClass, SecurityDescriptor);
00868 
00869     if (NT_SUCCESS(Status))
00870     {
00871         /* increment create item count */
00872         InterlockedIncrement(&Header->ItemListCount);
00873     }
00874 
00875     return Status;
00876 }
00877 
00878 /*
00879     @implemented
00880 */
00881 KSDDKAPI
00882 NTSTATUS
00883 NTAPI
00884 KsAllocateObjectCreateItem(
00885     IN  KSDEVICE_HEADER DevHeader,
00886     IN  PKSOBJECT_CREATE_ITEM CreateItem,
00887     IN  BOOLEAN AllocateEntry,
00888     IN  PFNKSITEMFREECALLBACK ItemFreeCallback OPTIONAL)
00889 {
00890     PCREATE_ITEM_ENTRY CreateEntry;
00891     PKSIDEVICE_HEADER Header;
00892     PKSOBJECT_CREATE_ITEM Item;
00893 
00894     Header = (PKSIDEVICE_HEADER)DevHeader;
00895 
00896     if (!DevHeader)
00897         return STATUS_INVALID_PARAMETER_1;
00898 
00899     if (!CreateItem)
00900         return STATUS_INVALID_PARAMETER_2;
00901 
00902     /* first allocate a create entry */
00903     CreateEntry = AllocateItem(NonPagedPool, sizeof(CREATE_ITEM_ENTRY));
00904 
00905     /* check for allocation success */
00906     if (!CreateEntry)
00907     {
00908         /* not enough resources */
00909         return STATUS_INSUFFICIENT_RESOURCES;
00910     }
00911 
00912 
00913     if (AllocateEntry)
00914     {
00915         /* allocate create item */
00916         Item = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
00917         if (!Item)
00918         {
00919             /* no memory */
00920             FreeItem(CreateEntry);
00921             return STATUS_INSUFFICIENT_RESOURCES;
00922         }
00923 
00924         /* initialize descriptor */
00925         Item->Context = CreateItem->Context;
00926         Item->Create = CreateItem->Create;
00927         Item->Flags = CreateItem->Flags;
00928         Item->SecurityDescriptor = CreateItem->SecurityDescriptor;
00929         Item->ObjectClass.Length = 0;
00930         Item->ObjectClass.MaximumLength = CreateItem->ObjectClass.MaximumLength;
00931 
00932         /* copy object class */
00933         Item->ObjectClass.Buffer = AllocateItem(NonPagedPool, Item->ObjectClass.MaximumLength);
00934         if (!Item->ObjectClass.Buffer)
00935         {
00936             /* release resources */
00937             FreeItem(Item);
00938             FreeItem(CreateEntry);
00939 
00940             return STATUS_INSUFFICIENT_RESOURCES;
00941         }
00942         RtlCopyUnicodeString(&Item->ObjectClass, &CreateItem->ObjectClass);
00943     }
00944     else
00945     {
00946         if (ItemFreeCallback)
00947         {
00948             /* callback is only accepted when the create item is copied */
00949             ItemFreeCallback = NULL;
00950         }
00951         /* use passed create item */
00952         Item = CreateItem;
00953     }
00954 
00955     /* initialize create item entry */
00956     InitializeListHead(&CreateEntry->ObjectItemList);
00957     CreateEntry->ItemFreeCallback = ItemFreeCallback;
00958     CreateEntry->CreateItem = Item;
00959     CreateEntry->ReferenceCount = 0;
00960 
00961     /* now insert the create item entry */
00962     InsertTailList(&Header->ItemList, &CreateEntry->Entry);
00963 
00964     /* increment item count */
00965     InterlockedIncrement(&Header->ItemListCount);
00966 
00967     return STATUS_SUCCESS;
00968 }
00969 
00970 NTSTATUS
00971 KspObjectFreeCreateItems(
00972     IN  KSDEVICE_HEADER Header,
00973     IN  PKSOBJECT_CREATE_ITEM CreateItem)
00974 {
00975     UNIMPLEMENTED
00976     return STATUS_NOT_IMPLEMENTED;
00977 }
00978 
00979 /*
00980     @implemented
00981 */
00982 KSDDKAPI
00983 NTSTATUS
00984 NTAPI
00985 KsFreeObjectCreateItem(
00986     IN  KSDEVICE_HEADER Header,
00987     IN  PUNICODE_STRING CreateItem)
00988 {
00989     KSOBJECT_CREATE_ITEM Item;
00990 
00991     RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
00992     RtlInitUnicodeString(&Item.ObjectClass, CreateItem->Buffer);
00993 
00994     return KspObjectFreeCreateItems(Header, &Item);
00995 }
00996 
00997 
00998 /*
00999     @implemented
01000 */
01001 KSDDKAPI
01002 NTSTATUS
01003 NTAPI
01004 KsFreeObjectCreateItemsByContext(
01005     IN  KSDEVICE_HEADER Header,
01006     IN  PVOID Context)
01007 {
01008     KSOBJECT_CREATE_ITEM Item;
01009 
01010     RtlZeroMemory(&Item, sizeof(KSOBJECT_CREATE_ITEM));
01011 
01012     Item.Context = Context;
01013 
01014     return KspObjectFreeCreateItems(Header, &Item);
01015 }
01016 
01017 /*
01018     @implemented
01019 */
01020 KSDDKAPI
01021 NTSTATUS
01022 NTAPI
01023 KsCreateDefaultSecurity(
01024     IN PSECURITY_DESCRIPTOR ParentSecurity OPTIONAL,
01025     OUT PSECURITY_DESCRIPTOR* DefaultSecurity)
01026 {
01027     PGENERIC_MAPPING Mapping;
01028     SECURITY_SUBJECT_CONTEXT SubjectContext;
01029     NTSTATUS Status;
01030 
01031     /* start capturing security context of calling thread */
01032     SeCaptureSubjectContext(&SubjectContext);
01033     /* get generic mapping */
01034     Mapping = IoGetFileObjectGenericMapping();
01035     /* build new descriptor */
01036     Status = SeAssignSecurity(ParentSecurity, NULL, DefaultSecurity, FALSE, &SubjectContext, Mapping, NonPagedPool);
01037     /* release security descriptor */
01038     SeReleaseSubjectContext(&SubjectContext);
01039     /* done */
01040     return Status;
01041 }
01042 
01043 /*
01044     @unimplemented
01045 */
01046 KSDDKAPI
01047 NTSTATUS
01048 NTAPI
01049 KsForwardIrp(
01050     IN  PIRP Irp,
01051     IN  PFILE_OBJECT FileObject,
01052     IN  BOOLEAN ReuseStackLocation)
01053 {
01054     UNIMPLEMENTED;
01055     return STATUS_UNSUCCESSFUL;
01056 }
01057 
01058 
01059 /*
01060     @unimplemented
01061 */
01062 KSDDKAPI
01063 NTSTATUS
01064 NTAPI
01065 KsForwardAndCatchIrp(
01066     IN  PDEVICE_OBJECT DeviceObject,
01067     IN  PIRP Irp,
01068     IN  PFILE_OBJECT FileObject,
01069     IN  KSSTACK_USE StackUse)
01070 {
01071     UNIMPLEMENTED;
01072     return STATUS_UNSUCCESSFUL;
01073 }
01074 
01075 
01076 NTSTATUS
01077 NTAPI
01078 KspSynchronousIoControlDeviceCompletion(
01079     IN PDEVICE_OBJECT  DeviceObject,
01080     IN PIRP  Irp,
01081     IN PVOID  Context)
01082 {
01083     PIO_STATUS_BLOCK IoStatusBlock = (PIO_STATUS_BLOCK)Context;
01084 
01085     IoStatusBlock->Information = Irp->IoStatus.Information;
01086     IoStatusBlock->Status = Irp->IoStatus.Status;
01087 
01088     return STATUS_SUCCESS;
01089 }
01090 
01091 /*
01092     @implemented
01093 */
01094 KSDDKAPI
01095 NTSTATUS
01096 NTAPI
01097 KsSynchronousIoControlDevice(
01098     IN  PFILE_OBJECT FileObject,
01099     IN  KPROCESSOR_MODE RequestorMode,
01100     IN  ULONG IoControl,
01101     IN  PVOID InBuffer,
01102     IN  ULONG InSize,
01103     OUT PVOID OutBuffer,
01104     IN  ULONG OutSize,
01105     OUT PULONG BytesReturned)
01106 {
01107     PKSIOBJECT_HEADER ObjectHeader;
01108     PDEVICE_OBJECT DeviceObject;
01109     KEVENT Event;
01110     PIRP Irp;
01111     IO_STATUS_BLOCK IoStatusBlock;
01112     PIO_STACK_LOCATION IoStack;
01113     NTSTATUS Status;
01114 
01115     /* check for valid file object */
01116     if (!FileObject)
01117         return STATUS_INVALID_PARAMETER;
01118 
01119     /* get device object to send the request to */
01120     DeviceObject = IoGetRelatedDeviceObject(FileObject);
01121     if (!DeviceObject)
01122         return STATUS_UNSUCCESSFUL;
01123 
01124 
01125     /* get object header */
01126     ObjectHeader = (PKSIOBJECT_HEADER)FileObject->FsContext2;
01127 
01128     /* check if there is fast device io function */
01129     if (ObjectHeader && ObjectHeader->DispatchTable.FastDeviceIoControl)
01130     {
01131         IoStatusBlock.Status = STATUS_UNSUCCESSFUL;
01132         IoStatusBlock.Information = 0;
01133 
01134         /* send the request */
01135         Status = ObjectHeader->DispatchTable.FastDeviceIoControl(FileObject, TRUE, InBuffer, InSize, OutBuffer, OutSize, IoControl, &IoStatusBlock, DeviceObject);
01136         /* check if the request was handled */
01137         //DPRINT("Handled %u Status %x Length %u\n", Status, IoStatusBlock.Status, IoStatusBlock.Information);
01138         if (Status)
01139         {
01140             /* store bytes returned */
01141             *BytesReturned = IoStatusBlock.Information;
01142             /* return status */
01143             return IoStatusBlock.Status;
01144         }
01145     }
01146 
01147     /* initialize the event */
01148     KeInitializeEvent(&Event, NotificationEvent, FALSE);
01149 
01150     /* create the irp */
01151     Irp =  IoBuildDeviceIoControlRequest(IoControl, DeviceObject, InBuffer, InSize, OutBuffer, OutSize, FALSE, &Event, &IoStatusBlock);
01152 
01153     if (!Irp)
01154     {
01155         /* no memory to allocate the irp */
01156         return STATUS_INSUFFICIENT_RESOURCES;
01157     }
01158 
01159 
01160     /* Store Fileobject */
01161     IoStack = IoGetNextIrpStackLocation(Irp);
01162     IoStack->FileObject = FileObject;
01163 
01164     if (IoControl == IOCTL_KS_WRITE_STREAM)
01165     {
01166         Irp->AssociatedIrp.SystemBuffer = OutBuffer;
01167     }
01168     else if (IoControl == IOCTL_KS_READ_STREAM)
01169     {
01170         Irp->AssociatedIrp.SystemBuffer = InBuffer;
01171     }
01172 
01173     IoSetCompletionRoutine(Irp, KspSynchronousIoControlDeviceCompletion, (PVOID)&IoStatusBlock, TRUE, TRUE, TRUE);
01174 
01175     Status = IoCallDriver(DeviceObject, Irp);
01176     if (Status == STATUS_PENDING)
01177     {
01178         KeWaitForSingleObject(&Event, Executive, RequestorMode, FALSE, NULL);
01179         Status = IoStatusBlock.Status;
01180     }
01181 
01182     *BytesReturned = IoStatusBlock.Information;
01183     return Status;
01184 }
01185 
01186 /*
01187     @unimplemented
01188 */
01189 KSDDKAPI
01190 NTSTATUS
01191 NTAPI
01192 KsUnserializeObjectPropertiesFromRegistry(
01193     IN PFILE_OBJECT FileObject,
01194     IN HANDLE ParentKey OPTIONAL,
01195     IN PUNICODE_STRING RegistryPath OPTIONAL)
01196 {
01197     UNIMPLEMENTED
01198     return STATUS_NOT_IMPLEMENTED;
01199 }
01200 
01201 
01202 /*
01203     @implemented
01204 */
01205 KSDDKAPI
01206 NTSTATUS
01207 NTAPI
01208 KsCacheMedium(
01209     IN  PUNICODE_STRING SymbolicLink,
01210     IN  PKSPIN_MEDIUM Medium,
01211     IN  ULONG PinDirection)
01212 {
01213     HANDLE hKey;
01214     UNICODE_STRING Path;
01215     UNICODE_STRING BasePath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\MediumCache\\");
01216     UNICODE_STRING GuidString;
01217     NTSTATUS Status;
01218     OBJECT_ATTRIBUTES ObjectAttributes;
01219     BOOLEAN PathAdjusted = FALSE;
01220     ULONG Value = 0;
01221 
01222     /* first check if the medium is standard */
01223     if (IsEqualGUIDAligned(&KSMEDIUMSETID_Standard, &Medium->Set) ||
01224         IsEqualGUIDAligned(&GUID_NULL, &Medium->Set))
01225     {
01226         /* no need to cache that */
01227         return STATUS_SUCCESS;
01228     }
01229 
01230     /* convert guid to string */
01231     Status = RtlStringFromGUID(&Medium->Set, &GuidString);
01232     if (!NT_SUCCESS(Status))
01233         return Status;
01234 
01235     /* allocate path buffer */
01236     Path.Length = 0;
01237     Path.MaximumLength = BasePath.MaximumLength + GuidString.MaximumLength + 10 * sizeof(WCHAR);
01238     Path.Buffer = AllocateItem(PagedPool, Path.MaximumLength);
01239     if (!Path.Buffer)
01240     {
01241         /* not enough resources */
01242         RtlFreeUnicodeString(&GuidString);
01243         return STATUS_INSUFFICIENT_RESOURCES;
01244     }
01245 
01246     RtlAppendUnicodeStringToString(&Path, &BasePath);
01247     RtlAppendUnicodeStringToString(&Path, &GuidString);
01248     RtlAppendUnicodeToString(&Path, L"-");
01249     /* FIXME append real instance id */
01250     RtlAppendUnicodeToString(&Path, L"0");
01251     RtlAppendUnicodeToString(&Path, L"-");
01252     /* FIXME append real instance id */
01253     RtlAppendUnicodeToString(&Path, L"0");
01254 
01255     /* free guid string */
01256     RtlFreeUnicodeString(&GuidString);
01257 
01258     /* initialize object attributes */
01259     InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
01260     /* create the key */
01261     Status = ZwCreateKey(&hKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL);
01262 
01263     /* free path buffer */
01264     FreeItem(Path.Buffer);
01265 
01266     if (NT_SUCCESS(Status))
01267     {
01268         /* store symbolic link */
01269         if (SymbolicLink->Buffer[1] == L'?' && SymbolicLink->Buffer[2] == L'?')
01270         {
01271             /* replace kernel path with user mode path */
01272             SymbolicLink->Buffer[1] = L'\\';
01273             PathAdjusted = TRUE;
01274         }
01275 
01276         /* store the key */
01277         Status = ZwSetValueKey(hKey, SymbolicLink, 0, REG_DWORD, &Value, sizeof(ULONG));
01278 
01279         if (PathAdjusted)
01280         {
01281             /* restore kernel path */
01282             SymbolicLink->Buffer[1] = L'?';
01283         }
01284 
01285         ZwClose(hKey);
01286     }
01287 
01288     /* done */
01289     return Status;
01290 }
01291 
01292 /*
01293     @implemented
01294 */
01295 NTSTATUS
01296 NTAPI
01297 DllInitialize(
01298     PUNICODE_STRING  RegistryPath)
01299 {
01300     return STATUS_SUCCESS;
01301 }
01302 
01303 
01304 NTSTATUS
01305 NTAPI
01306 KopDispatchClose(
01307     IN PDEVICE_OBJECT DeviceObject,
01308     IN PIRP Irp)
01309 {
01310     PKO_OBJECT_HEADER Header;
01311     PIO_STACK_LOCATION IoStack;
01312     PDEVICE_EXTENSION DeviceExtension;
01313 
01314     /* get current irp stack location */
01315     IoStack = IoGetCurrentIrpStackLocation(Irp);
01316 
01317     /* get ko object header */
01318     Header = (PKO_OBJECT_HEADER)IoStack->FileObject->FsContext2;
01319 
01320     /* free ks object header */
01321     KsFreeObjectHeader(Header->ObjectHeader);
01322 
01323     /* free ko object header */
01324     FreeItem(Header);
01325 
01326     /* get device extension */
01327     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
01328 
01329     /* release bus object */
01330     KsDereferenceBusObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
01331 
01332     /* complete request */
01333     Irp->IoStatus.Status = STATUS_SUCCESS;
01334     CompleteRequest(Irp, IO_NO_INCREMENT);
01335 
01336     return STATUS_SUCCESS;
01337 }
01338 
01339 
01340 
01341 static KSDISPATCH_TABLE KoDispatchTable =
01342 {
01343     KsDispatchInvalidDeviceRequest,
01344     KsDispatchInvalidDeviceRequest,
01345     KsDispatchInvalidDeviceRequest,
01346     KsDispatchInvalidDeviceRequest,
01347     KopDispatchClose,
01348     KsDispatchQuerySecurity,
01349     KsDispatchSetSecurity,
01350     KsDispatchFastIoDeviceControlFailure,
01351     KsDispatchFastReadFailure,
01352     KsDispatchFastReadFailure,
01353 };
01354 
01355 
01356 NTSTATUS
01357 NTAPI
01358 KopDispatchCreate(
01359     IN PDEVICE_OBJECT DeviceObject,
01360     IN PIRP Irp)
01361 {
01362     PKO_OBJECT_HEADER Header = NULL;
01363     PIO_STACK_LOCATION IoStack;
01364     PKO_DRIVER_EXTENSION DriverObjectExtension;
01365     NTSTATUS Status;
01366 
01367     /* get current irp stack location */
01368     IoStack = IoGetCurrentIrpStackLocation(Irp);
01369 
01370     if (!IoStack->FileObject)
01371     {
01372         DPRINT1("FileObject not attached!\n");
01373         Status = STATUS_UNSUCCESSFUL;
01374         goto cleanup;
01375     }
01376 
01377     /* get driver object extension */
01378     DriverObjectExtension = (PKO_DRIVER_EXTENSION)IoGetDriverObjectExtension(DeviceObject->DriverObject, (PVOID)KoDriverInitialize);
01379     if (!DriverObjectExtension)
01380     {
01381         DPRINT1("No DriverObjectExtension!\n");
01382         Status = STATUS_UNSUCCESSFUL;
01383         goto cleanup;
01384     }
01385 
01386     /* allocate ko object header */
01387     Header = (PKO_OBJECT_HEADER)AllocateItem(NonPagedPool, sizeof(KO_OBJECT_HEADER));
01388     if (!Header)
01389     {
01390         DPRINT1("failed to allocate KO_OBJECT_HEADER\n");
01391         Status = STATUS_INSUFFICIENT_RESOURCES;
01392         goto cleanup;
01393     }
01394 
01395     /* initialize create item */
01396     Header->CreateItem.Create = KopDispatchCreate;
01397     RtlInitUnicodeString(&Header->CreateItem.ObjectClass, KOSTRING_CreateObject);
01398 
01399 
01400     /* now allocate the object header */
01401     Status = KsAllocateObjectHeader(&Header->ObjectHeader, 1, &Header->CreateItem, Irp, &KoDispatchTable);
01402     if (!NT_SUCCESS(Status))
01403     {
01404         /* failed */
01405         goto cleanup;
01406     }
01407 
01408     /* FIXME
01409      * extract clsid and interface id from irp
01410      * call the standard create handler
01411      */
01412 
01413     UNIMPLEMENTED
01414 
01415     IoStack->FileObject->FsContext2 = (PVOID)Header;
01416 
01417     Irp->IoStatus.Status = Status;
01418     CompleteRequest(Irp, IO_NO_INCREMENT);
01419 
01420     return Status;
01421 
01422 cleanup:
01423 
01424     if (Header && Header->ObjectHeader)
01425         KsFreeObjectHeader(Header->ObjectHeader);
01426 
01427     if (Header)
01428         FreeItem(Header);
01429 
01430     Irp->IoStatus.Status = Status;
01431     CompleteRequest(Irp, IO_NO_INCREMENT);
01432     return Status;
01433 }
01434 
01435 
01436 
01437 NTSTATUS
01438 NTAPI
01439 KopAddDevice(
01440     IN PDRIVER_OBJECT DriverObject,
01441     IN PDEVICE_OBJECT PhysicalDeviceObject)
01442 {
01443     NTSTATUS Status = STATUS_DEVICE_REMOVED;
01444     PDEVICE_OBJECT FunctionalDeviceObject= NULL;
01445     PDEVICE_OBJECT NextDeviceObject;
01446     PDEVICE_EXTENSION DeviceExtension;
01447     PKSOBJECT_CREATE_ITEM CreateItem;
01448 
01449     /* create the device object */
01450     Status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_KS, FILE_DEVICE_SECURE_OPEN, FALSE, &FunctionalDeviceObject);
01451     if (!NT_SUCCESS(Status))
01452         return Status;
01453 
01454     /* allocate the create item */
01455     CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM));
01456 
01457     if (!CreateItem)
01458     {
01459         /* not enough memory */
01460         IoDeleteDevice(FunctionalDeviceObject);
01461         return STATUS_INSUFFICIENT_RESOURCES;
01462     }
01463 
01464     /* initialize create item */
01465     CreateItem->Create = KopDispatchCreate;
01466     RtlInitUnicodeString(&CreateItem->ObjectClass, KOSTRING_CreateObject);
01467 
01468     /* get device extension */
01469     DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
01470 
01471     /* now allocate the device header */
01472     Status = KsAllocateDeviceHeader((KSDEVICE_HEADER*)&DeviceExtension->DeviceHeader, 1, CreateItem);
01473     if (!NT_SUCCESS(Status))
01474     {
01475         /* failed */
01476         IoDeleteDevice(FunctionalDeviceObject);
01477         FreeItem(CreateItem);
01478         return Status;
01479     }
01480 
01481     /* now attach to device stack */
01482     NextDeviceObject = IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject);
01483     if (NextDeviceObject)
01484     {
01485         /* store pnp base object */
01486          KsSetDevicePnpAndBaseObject((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, NextDeviceObject, FunctionalDeviceObject);
01487         /* set device flags */
01488         FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
01489         FunctionalDeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
01490     }
01491     else
01492     {
01493         /* failed */
01494         KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader);
01495         FreeItem(CreateItem);
01496         IoDeleteDevice(FunctionalDeviceObject);
01497         Status =  STATUS_DEVICE_REMOVED;
01498     }
01499 
01500     /* return result */
01501     return Status;
01502 }
01503 
01504 
01505 /*
01506     @implemented
01507 */
01508 COMDDKAPI
01509 NTSTATUS
01510 NTAPI
01511 KoDeviceInitialize(
01512     IN PDEVICE_OBJECT DeviceObject)
01513 {
01514     PDEVICE_EXTENSION DeviceExtension;
01515 
01516     /* get device extension */
01517     DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
01518 
01519     return KsAddObjectCreateItemToDeviceHeader((KSDEVICE_HEADER)DeviceExtension->DeviceHeader, KopDispatchCreate, NULL, KOSTRING_CreateObject, NULL);
01520 }
01521 
01522 /*
01523     @implemented
01524 */
01525 COMDDKAPI
01526 NTSTATUS
01527 NTAPI
01528 KoDriverInitialize(
01529     IN PDRIVER_OBJECT DriverObject,
01530     IN PUNICODE_STRING RegistryPathName,
01531     IN KoCreateObjectHandler CreateObjectHandler)
01532 {
01533     PKO_DRIVER_EXTENSION DriverObjectExtension;
01534     NTSTATUS Status;
01535 
01536     /* allocate driver object extension */
01537     Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KoDriverInitialize, sizeof(KO_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
01538 
01539     /* did it work */
01540     if (NT_SUCCESS(Status))
01541     {
01542         /* store create handler */
01543         DriverObjectExtension->CreateObjectHandler = CreateObjectHandler;
01544 
01545          /* Setting our IRP handlers */
01546         DriverObject->MajorFunction[IRP_MJ_PNP] = KsDefaultDispatchPnp;
01547         DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
01548         DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
01549 
01550         /* The driver unload routine */
01551         DriverObject->DriverUnload = KsNullDriverUnload;
01552 
01553         /* The driver-supplied AddDevice */
01554         DriverObject->DriverExtension->AddDevice = KopAddDevice;
01555 
01556         /* KS handles these */
01557         DPRINT1("Setting KS function handlers\n");
01558         KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
01559         KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
01560         KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
01561 
01562     }
01563 
01564     return Status;
01565 }
01566 
01567 /*
01568     @unimplemented
01569 */
01570 COMDDKAPI
01571 VOID
01572 NTAPI
01573 KoRelease(
01574     IN REFCLSID ClassId)
01575 {
01576 
01577 }
01578 
01579 /*
01580     @implemented
01581 */
01582 KSDDKAPI
01583 VOID
01584 NTAPI
01585 KsAcquireControl(
01586     IN PVOID Object)
01587 {
01588     PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
01589 
01590     /* sanity check */
01591     ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
01592 
01593     KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
01594 
01595 }
01596 
01597 /*
01598     @implemented
01599 */
01600 VOID
01601 NTAPI
01602 KsReleaseControl(
01603     IN PVOID  Object)
01604 {
01605     PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
01606 
01607     /* sanity check */
01608     ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
01609 
01610     KeReleaseMutex(BasicHeader->ControlMutex, FALSE);
01611 }
01612 
01613 
01614 
01615 /*
01616     @implemented
01617 */
01618 KSDDKAPI
01619 VOID
01620 NTAPI
01621 KsAcquireDevice(
01622     IN PKSDEVICE Device)
01623 {
01624     IKsDevice *KsDevice;
01625     PKSIDEVICE_HEADER DeviceHeader;
01626 
01627     DPRINT("KsAcquireDevice\n");
01628     DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
01629 
01630     /* get device interface*/
01631     KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
01632 
01633     /* acquire device mutex */
01634     KsDevice->lpVtbl->AcquireDevice(KsDevice);
01635 }
01636 
01637 /*
01638     @implemented
01639 */
01640 VOID
01641 NTAPI
01642 KsReleaseDevice(
01643     IN PKSDEVICE  Device)
01644 {
01645     IKsDevice *KsDevice;
01646     PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
01647 
01648     /* get device interface*/
01649     KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
01650 
01651     /* release device mutex */
01652     KsDevice->lpVtbl->ReleaseDevice(KsDevice);
01653 }
01654 
01655 /*
01656     @implemented
01657 */
01658 KSDDKAPI
01659 VOID
01660 NTAPI
01661 KsTerminateDevice(
01662     IN PDEVICE_OBJECT DeviceObject)
01663 {
01664     IKsDevice *KsDevice;
01665     PKSIDEVICE_HEADER DeviceHeader;
01666     PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
01667 
01668     /* get device header */
01669     DeviceHeader = DeviceExtension->DeviceHeader;
01670 
01671     /* get device interface*/
01672     KsDevice = (IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown;
01673 
01674     /* now free device header */
01675     KsFreeDeviceHeader((KSDEVICE_HEADER)DeviceHeader);
01676 
01677     /* release interface when available */
01678     if (KsDevice)
01679     {
01680         /* delete IKsDevice interface */
01681         KsDevice->lpVtbl->Release(KsDevice);
01682     }
01683 }
01684 
01685 /*
01686     @implemented
01687 */
01688 KSDDKAPI
01689 VOID
01690 NTAPI
01691 KsCompletePendingRequest(
01692     IN PIRP Irp)
01693 {
01694     PIO_STACK_LOCATION IoStack;
01695 
01696     /* get current irp stack location */
01697     IoStack = IoGetCurrentIrpStackLocation(Irp);
01698 
01699     /* sanity check */
01700     ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
01701 
01702     if (IoStack->MajorFunction != IRP_MJ_CLOSE)
01703     {
01704         /* can be completed immediately */
01705         CompleteRequest(Irp, IO_NO_INCREMENT);
01706         return;
01707     }
01708 
01709     /* did close operation fail */
01710     if (!NT_SUCCESS(Irp->IoStatus.Status))
01711     {
01712         /* closing failed, complete irp */
01713         CompleteRequest(Irp, IO_NO_INCREMENT);
01714         return;
01715     }
01716 
01717     /* FIXME 
01718      * delete object / device header 
01719      * remove dead pin / filter instance
01720      */
01721     UNIMPLEMENTED
01722 
01723 }
01724 
01725 NTSTATUS
01726 NTAPI
01727 KspSetGetBusDataCompletion(
01728     IN PDEVICE_OBJECT  DeviceObject,
01729     IN PIRP  Irp,
01730     IN PVOID  Context)
01731 {
01732     /* signal completion */
01733     KeSetEvent((PRKEVENT)Context, IO_NO_INCREMENT, FALSE);
01734 
01735     /* more work needs be done, so dont free the irp */
01736     return STATUS_MORE_PROCESSING_REQUIRED;
01737 
01738 }
01739 
01740 NTSTATUS
01741 KspDeviceSetGetBusData(
01742     IN PDEVICE_OBJECT DeviceObject,
01743     IN ULONG DataType,
01744     IN PVOID Buffer,
01745     IN ULONG Offset,
01746     IN ULONG Length,
01747     IN BOOL bGet)
01748 {
01749     PIO_STACK_LOCATION IoStack;
01750     PIRP Irp;
01751     NTSTATUS Status;
01752     KEVENT Event;
01753 
01754     /* allocate the irp */
01755     Irp = IoAllocateIrp(1, /*FIXME */
01756                         FALSE);
01757 
01758     if (!Irp)
01759         return STATUS_INSUFFICIENT_RESOURCES;
01760 
01761     /* initialize the event */
01762     KeInitializeEvent(&Event, NotificationEvent, FALSE);
01763 
01764     /* get next stack location */
01765     IoStack = IoGetNextIrpStackLocation(Irp);
01766 
01767     /* setup a completion routine */
01768     IoSetCompletionRoutine(Irp, KspSetGetBusDataCompletion, (PVOID)&Event, TRUE, TRUE, TRUE);
01769 
01770     /* setup parameters */
01771     IoStack->Parameters.ReadWriteConfig.Buffer = Buffer;
01772     IoStack->Parameters.ReadWriteConfig.Length = Length;
01773     IoStack->Parameters.ReadWriteConfig.Offset = Offset;
01774     IoStack->Parameters.ReadWriteConfig.WhichSpace = DataType;
01775     /* setup function code */
01776     IoStack->MajorFunction = IRP_MJ_PNP;
01777     IoStack->MinorFunction = (bGet ? IRP_MN_READ_CONFIG : IRP_MN_WRITE_CONFIG);
01778 
01779     /* lets call the driver */
01780     Status = IoCallDriver(DeviceObject, Irp);
01781 
01782     /* is the request still pending */
01783     if (Status == STATUS_PENDING) 
01784     {
01785         /* have a nap */
01786         KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
01787         /* update status */
01788         Status = Irp->IoStatus.Status;
01789     }
01790 
01791     /* free the irp */
01792     IoFreeIrp(Irp);
01793     /* done */
01794     return Status;
01795 }
01796 
01797 /*
01798     @implemented
01799 */
01800 KSDDKAPI
01801 ULONG
01802 NTAPI
01803 KsDeviceSetBusData(
01804     IN PKSDEVICE Device,
01805     IN ULONG DataType,
01806     IN PVOID Buffer,
01807     IN ULONG Offset,
01808     IN ULONG Length)
01809 {
01810     return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
01811                                   DataType, Buffer, Offset, Length, FALSE);
01812 }
01813 
01814 
01815 /*
01816     @implemented
01817 */
01818 KSDDKAPI
01819 ULONG
01820 NTAPI
01821 KsDeviceGetBusData(
01822     IN PKSDEVICE Device,
01823     IN ULONG DataType,
01824     IN PVOID Buffer,
01825     IN ULONG Offset,
01826     IN ULONG Length)
01827 {
01828     return KspDeviceSetGetBusData(Device->PhysicalDeviceObject, /* is this right? */
01829                                   DataType, Buffer, Offset, Length, TRUE);
01830 
01831 }
01832 
01833 /*
01834     @implemented
01835 */
01836 KSDDKAPI
01837 void
01838 NTAPI
01839 KsDeviceRegisterAdapterObject(
01840     IN PKSDEVICE Device,
01841     IN PADAPTER_OBJECT AdapterObject,
01842     IN ULONG MaxMappingsByteCount,
01843     IN ULONG MappingTableStride)
01844 {
01845     PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
01846 
01847     DeviceHeader->AdapterObject = AdapterObject;
01848     DeviceHeader->MaxMappingsByteCount = MaxMappingsByteCount;
01849     DeviceHeader->MappingTableStride = MappingTableStride;
01850 
01851 }
01852 
01853 
01854 /*
01855     @implemented
01856 */
01857 KSDDKAPI
01858 PVOID
01859 NTAPI
01860 KsGetFirstChild(
01861     IN PVOID Object)
01862 {
01863     PKSBASIC_HEADER BasicHeader;
01864 
01865     /* get the basic header */
01866     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
01867 
01868     /* type has to be either a device or a filter factory */
01869     ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory);
01870 
01871     return (PVOID)BasicHeader->FirstChild.Filter;
01872 }
01873 
01874 /*
01875     @implemented
01876 */
01877 KSDDKAPI
01878 PVOID
01879 NTAPI
01880 KsGetNextSibling(
01881     IN PVOID Object)
01882 {
01883     PKSBASIC_HEADER BasicHeader;
01884 
01885     /* get the basic header */
01886     BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
01887 
01888     ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 
01889            BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
01890 
01891     return (PVOID)BasicHeader->Next.Pin;
01892 }
01893 
01894 ULONG
01895 KspCountMethodSets(
01896     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
01897     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL)
01898 {
01899     ULONG Index, SubIndex, Count;
01900     BOOL bFound;
01901 
01902     if (!AutomationTableA)
01903         return AutomationTableB->MethodSetsCount;
01904 
01905     if (!AutomationTableB)
01906         return AutomationTableA->MethodSetsCount;
01907 
01908 
01909     DPRINT("AutomationTableA MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableA->MethodItemSize, AutomationTableA->MethodSetsCount);
01910     DPRINT("AutomationTableB MethodItemSize %lu MethodSetsCount %lu\n", AutomationTableB->MethodItemSize, AutomationTableB->MethodSetsCount);
01911 
01912     if (AutomationTableA->MethodItemSize && AutomationTableB->MethodItemSize)
01913     {
01914         /* sanity check */
01915         ASSERT(AutomationTableA->MethodItemSize  == AutomationTableB->MethodItemSize);
01916     }
01917 
01918     /* now iterate all property sets and compare their guids */
01919     Count = AutomationTableA->MethodSetsCount;
01920 
01921     for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
01922     {
01923         /* set found to false */
01924         bFound = FALSE;
01925 
01926         for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
01927         {
01928             if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
01929             {
01930                 /* same property set found */
01931                 bFound = TRUE;
01932                 break;
01933             }
01934         }
01935 
01936         if (!bFound)
01937             Count++;
01938     }
01939 
01940     return Count;
01941 }
01942 
01943 ULONG
01944 KspCountEventSets(
01945     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
01946     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL)
01947 {
01948     ULONG Index, SubIndex, Count;
01949     BOOL bFound;
01950 
01951     if (!AutomationTableA)
01952         return AutomationTableB->EventSetsCount;
01953 
01954     if (!AutomationTableB)
01955         return AutomationTableA->EventSetsCount;
01956 
01957     DPRINT("AutomationTableA EventItemSize %lu EventSetsCount %lu\n", AutomationTableA->EventItemSize, AutomationTableA->EventSetsCount);
01958     DPRINT("AutomationTableB EventItemSize %lu EventSetsCount %lu\n", AutomationTableB->EventItemSize, AutomationTableB->EventSetsCount);
01959 
01960     if (AutomationTableA->EventItemSize && AutomationTableB->EventItemSize)
01961     {
01962         /* sanity check */
01963         ASSERT(AutomationTableA->EventItemSize == AutomationTableB->EventItemSize);
01964     }
01965 
01966     /* now iterate all Event sets and compare their guids */
01967     Count = AutomationTableA->EventSetsCount;
01968 
01969     for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
01970     {
01971         /* set found to false */
01972         bFound = FALSE;
01973 
01974         for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
01975         {
01976             if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
01977             {
01978                 /* same Event set found */
01979                 bFound = TRUE;
01980                 break;
01981             }
01982         }
01983 
01984         if (!bFound)
01985             Count++;
01986     }
01987 
01988     return Count;
01989 }
01990 
01991 
01992 ULONG
01993 KspCountPropertySets(
01994     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
01995     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL)
01996 {
01997     ULONG Index, SubIndex, Count;
01998     BOOL bFound;
01999 
02000     if (!AutomationTableA)
02001         return AutomationTableB->PropertySetsCount;
02002 
02003     if (!AutomationTableB)
02004         return AutomationTableA->PropertySetsCount;
02005 
02006     /* sanity check */
02007     DPRINT("AutomationTableA PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableA->PropertyItemSize, AutomationTableA->PropertySetsCount);
02008     DPRINT("AutomationTableB PropertyItemSize %lu PropertySetsCount %lu\n", AutomationTableB->PropertyItemSize, AutomationTableB->PropertySetsCount);
02009     ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
02010 
02011     /* now iterate all property sets and compare their guids */
02012     Count = AutomationTableA->PropertySetsCount;
02013 
02014     for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
02015     {
02016         /* set found to false */
02017         bFound = FALSE;
02018 
02019         for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
02020         {
02021             if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
02022             {
02023                 /* same property set found */
02024                 bFound = TRUE;
02025                 break;
02026             }
02027         }
02028 
02029         if (!bFound)
02030             Count++;
02031     }
02032 
02033     return Count;
02034 }
02035 
02036 NTSTATUS
02037 KspCopyMethodSets(
02038     OUT PKSAUTOMATION_TABLE  Table,
02039     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
02040     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL)
02041 {
02042     ULONG Index, SubIndex, Count;
02043     BOOL bFound;
02044 
02045     if (!AutomationTableA)
02046     {
02047         /* copy of property set */
02048         RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableB->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableB->MethodSetsCount);
02049         return STATUS_SUCCESS;
02050     }
02051     else if (!AutomationTableB)
02052     {
02053         /* copy of property set */
02054         RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
02055         return STATUS_SUCCESS;
02056     }
02057 
02058     /* first copy all property items from dominant table */
02059     RtlMoveMemory((PVOID)Table->MethodSets, AutomationTableA->MethodSets, sizeof(KSMETHOD_SET) * AutomationTableA->MethodSetsCount);
02060     /* set counter */
02061     Count = AutomationTableA->MethodSetsCount;
02062 
02063     /* now copy entries which arent available in the dominant table */
02064     for(Index = 0; Index < AutomationTableB->MethodSetsCount; Index++)
02065     {
02066         /* set found to false */
02067         bFound = FALSE;
02068 
02069         for(SubIndex = 0; SubIndex < AutomationTableA->MethodSetsCount; SubIndex++)
02070         {
02071             if (IsEqualGUIDAligned(AutomationTableB->MethodSets[Index].Set, AutomationTableA->MethodSets[SubIndex].Set))
02072             {
02073                 /* same property set found */
02074                 bFound = TRUE;
02075                 break;
02076             }
02077         }
02078 
02079         if (!bFound)
02080         {
02081             /* copy new property item set */
02082             RtlMoveMemory((PVOID)&Table->MethodSets[Count], &AutomationTableB->MethodSets[Index], sizeof(KSMETHOD_SET));
02083             Count++;
02084         }
02085     }
02086 
02087     return STATUS_SUCCESS;
02088 }
02089 
02090 VOID
02091 KspAddPropertyItem(
02092     OUT PKSPROPERTY_SET OutPropertySet,
02093     IN PKSPROPERTY_ITEM PropertyItem,
02094     IN ULONG PropertyItemSize)
02095 {
02096     PKSPROPERTY_ITEM CurrentPropertyItem;
02097     ULONG Index;
02098 
02099     // check if the property item is already present
02100     CurrentPropertyItem = (PKSPROPERTY_ITEM)OutPropertySet->PropertyItem;
02101     for(Index = 0; Index < OutPropertySet->PropertiesCount; Index++)
02102     {
02103         if (CurrentPropertyItem->PropertyId == PropertyItem->PropertyId)
02104         {
02105             // item already present
02106             return;
02107         }
02108 
02109         // next item
02110         CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + PropertyItemSize);
02111     }
02112     // add item
02113     RtlCopyMemory(CurrentPropertyItem, PropertyItem, PropertyItemSize);
02114     OutPropertySet->PropertiesCount++;
02115 }
02116 
02117 NTSTATUS
02118 KspMergePropertySet(
02119     OUT PKSAUTOMATION_TABLE  Table,
02120     OUT PKSPROPERTY_SET OutPropertySet,
02121     IN PKSPROPERTY_SET PropertySetA,
02122     IN PKSPROPERTY_SET PropertySetB,
02123     IN KSOBJECT_BAG  Bag OPTIONAL)
02124 {
02125     ULONG PropertyCount, Index;
02126     PKSPROPERTY_ITEM PropertyItem, CurrentPropertyItem;
02127     NTSTATUS Status;
02128 
02129     // max properties 
02130     PropertyCount = PropertySetA->PropertiesCount + PropertySetB->PropertiesCount;
02131 
02132     // allocate items
02133     PropertyItem = AllocateItem(NonPagedPool, Table->PropertyItemSize * PropertyCount);
02134     if (!PropertyItem)
02135         return STATUS_INSUFFICIENT_RESOURCES;
02136 
02137     if (Bag)
02138     {
02139         /* add table to object bag */
02140         Status = KsAddItemToObjectBag(Bag, PropertyItem, NULL);
02141         /* check for success */
02142         if (!NT_SUCCESS(Status))
02143         {
02144             /* free table */
02145             FreeItem(Table);
02146             return Status;
02147         }
02148     }
02149 
02150     // copy entries from dominant table
02151     RtlCopyMemory(PropertyItem, PropertySetA->PropertyItem, Table->PropertyItemSize * PropertySetA->PropertiesCount);
02152 
02153     // init property set
02154     OutPropertySet->PropertiesCount = PropertySetA->PropertiesCount;
02155     OutPropertySet->PropertyItem = PropertyItem;
02156 
02157     // copy other entries
02158     CurrentPropertyItem = (PKSPROPERTY_ITEM)PropertySetB->PropertyItem;
02159     for(Index = 0; Index < PropertySetB->PropertiesCount; Index++)
02160     {
02161 
02162         // add entries
02163         KspAddPropertyItem(OutPropertySet, CurrentPropertyItem, Table->PropertyItemSize);
02164 
02165         // next entry
02166         CurrentPropertyItem = (PKSPROPERTY_ITEM)((ULONG_PTR)CurrentPropertyItem + Table->PropertyItemSize);
02167     }
02168 
02169     // done
02170     return STATUS_SUCCESS;
02171 }
02172 
02173 
02174 NTSTATUS
02175 KspCopyPropertySets(
02176     OUT PKSAUTOMATION_TABLE  Table,
02177     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
02178     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL,
02179     IN KSOBJECT_BAG  Bag OPTIONAL)
02180 {
02181     ULONG Index, SubIndex, Count;
02182     BOOL bFound;
02183     NTSTATUS Status;
02184 
02185     if (!AutomationTableA)
02186     {
02187         /* copy of property set */
02188         RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableB->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableB->PropertySetsCount);
02189         return STATUS_SUCCESS;
02190     }
02191     else if (!AutomationTableB)
02192     {
02193         /* copy of property set */
02194         RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
02195         return STATUS_SUCCESS;
02196     }
02197 
02198     /* first copy all property items from dominant table */
02199     RtlMoveMemory((PVOID)Table->PropertySets, AutomationTableA->PropertySets, sizeof(KSPROPERTY_SET) * AutomationTableA->PropertySetsCount);
02200     /* set counter */
02201     Count = AutomationTableA->PropertySetsCount;
02202 
02203     /* now copy entries which arent available in the dominant table */
02204     for(Index = 0; Index < AutomationTableB->PropertySetsCount; Index++)
02205     {
02206         /* set found to false */
02207         bFound = FALSE;
02208 
02209         for(SubIndex = 0; SubIndex < AutomationTableA->PropertySetsCount; SubIndex++)
02210         {
02211             if (IsEqualGUIDAligned(AutomationTableB->PropertySets[Index].Set, AutomationTableA->PropertySets[SubIndex].Set))
02212             {
02213                 /* same property set found */
02214                 bFound = TRUE;
02215                 break;
02216             }
02217         }
02218 
02219         if (!bFound)
02220         {
02221             /* copy new property item set */
02222             RtlMoveMemory((PVOID)&Table->PropertySets[Count], &AutomationTableB->PropertySets[Index], sizeof(KSPROPERTY_SET));
02223             Count++;
02224         }
02225         else
02226         {
02227             // merge property sets
02228             Status = KspMergePropertySet(Table, (PKSPROPERTY_SET)&Table->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableA->PropertySets[SubIndex], (PKSPROPERTY_SET)&AutomationTableB->PropertySets[Index], Bag);
02229             if (!NT_SUCCESS(Status))
02230             {
02231                 // failed to merge
02232                 DPRINT1("[KS] Failed to merge %x\n", Status);
02233                 return Status;
02234             }
02235         }
02236     }
02237 
02238     return STATUS_SUCCESS;
02239 }
02240 
02241 NTSTATUS
02242 KspCopyEventSets(
02243     OUT PKSAUTOMATION_TABLE  Table,
02244     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
02245     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL)
02246 {
02247     ULONG Index, SubIndex, Count;
02248     BOOL bFound;
02249 
02250     if (!AutomationTableA)
02251     {
02252         /* copy of Event set */
02253         RtlMoveMemory((PVOID)Table->EventSets, AutomationTableB->EventSets, sizeof(KSEVENT_SET) * AutomationTableB->EventSetsCount);
02254         return STATUS_SUCCESS;
02255     }
02256     else if (!AutomationTableB)
02257     {
02258         /* copy of Event set */
02259         RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
02260         return STATUS_SUCCESS;
02261     }
02262 
02263     /* first copy all Event items from dominant table */
02264     RtlMoveMemory((PVOID)Table->EventSets, AutomationTableA->EventSets, sizeof(KSEVENT_SET) * AutomationTableA->EventSetsCount);
02265     /* set counter */
02266     Count = AutomationTableA->EventSetsCount;
02267 
02268     /* now copy entries which arent available in the dominant table */
02269     for(Index = 0; Index < AutomationTableB->EventSetsCount; Index++)
02270     {
02271         /* set found to false */
02272         bFound = FALSE;
02273 
02274         for(SubIndex = 0; SubIndex < AutomationTableA->EventSetsCount; SubIndex++)
02275         {
02276             if (IsEqualGUIDAligned(AutomationTableB->EventSets[Index].Set, AutomationTableA->EventSets[SubIndex].Set))
02277             {
02278                 /* same Event set found */
02279                 bFound = TRUE;
02280                 break;
02281             }
02282         }
02283 
02284         if (!bFound)
02285         {
02286             /* copy new Event item set */
02287             RtlMoveMemory((PVOID)&Table->EventSets[Count], &AutomationTableB->EventSets[Index], sizeof(KSEVENT_SET));
02288             Count++;
02289         }
02290     }
02291 
02292     return STATUS_SUCCESS;
02293 }
02294 
02295 
02296 /*
02297     @implemented
02298 */
02299 NTSTATUS
02300 NTAPI
02301 KsMergeAutomationTables(
02302     OUT PKSAUTOMATION_TABLE  *AutomationTableAB,
02303     IN PKSAUTOMATION_TABLE  AutomationTableA OPTIONAL,
02304     IN PKSAUTOMATION_TABLE  AutomationTableB OPTIONAL,
02305     IN KSOBJECT_BAG  Bag OPTIONAL)
02306 {
02307     PKSAUTOMATION_TABLE Table;
02308     NTSTATUS Status = STATUS_SUCCESS;
02309 
02310     if (!AutomationTableA && !AutomationTableB)
02311     {
02312         /* nothing to merge */
02313         return STATUS_SUCCESS;
02314     }
02315 
02316     /* allocate an automation table */
02317     Table = AllocateItem(NonPagedPool, sizeof(KSAUTOMATION_TABLE));
02318     if (!Table)
02319         return STATUS_INSUFFICIENT_RESOURCES;
02320 
02321     if (Bag)
02322     {
02323         /* add table to object bag */
02324         Status = KsAddItemToObjectBag(Bag, Table, NULL);
02325         /* check for success */
02326         if (!NT_SUCCESS(Status))
02327         {
02328             /* free table */
02329             FreeItem(Table);
02330             return Status;
02331         }
02332     }
02333 
02334     /* count property sets */
02335     Table->PropertySetsCount = KspCountPropertySets(AutomationTableA, AutomationTableB);
02336 
02337     if (Table->PropertySetsCount)
02338     {
02339         if (AutomationTableA)
02340         {
02341             /* use item size from dominant automation table */
02342             Table->PropertyItemSize = AutomationTableA->PropertyItemSize;
02343         }
02344         else
02345         {
02346             /* use item size from 2nd automation table */
02347             Table->PropertyItemSize = AutomationTableB->PropertyItemSize;
02348         }
02349 
02350         if (AutomationTableA && AutomationTableB)
02351         {
02352             // FIXME handle different propery item sizes
02353             ASSERT(AutomationTableA->PropertyItemSize == AutomationTableB->PropertyItemSize);
02354         }
02355 
02356         /* now allocate the property sets */
02357         Table->PropertySets = AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * Table->PropertySetsCount);
02358 
02359         if (!Table->PropertySets)
02360         {
02361             /* not enough memory */
02362             goto cleanup;
02363         }
02364 
02365         if (Bag)
02366         {
02367             /* add set to property bag */
02368             Status = KsAddItemToObjectBag(Bag, (PVOID)Table->PropertySets, NULL);
02369             /* check for success */
02370             if (!NT_SUCCESS(Status))
02371             {
02372                 /* cleanup table */
02373                 goto cleanup;
02374             }
02375         }
02376         /* now copy the property sets */
02377         Status = KspCopyPropertySets(Table, AutomationTableA, AutomationTableB, Bag);
02378         if(!NT_SUCCESS(Status))
02379             goto cleanup;
02380 
02381     }
02382 
02383     /* now count the method sets */
02384     Table->MethodSetsCount = KspCountMethodSets(AutomationTableA, AutomationTableB);
02385 
02386     if (Table->MethodSetsCount)
02387     {
02388         if (AutomationTableA)
02389         {
02390             /* use item size from dominant automation table */
02391             Table->MethodItemSize  = AutomationTableA->MethodItemSize;
02392         }
02393         else
02394         {
02395             /* use item size from 2nd automation table */
02396             Table->MethodItemSize = AutomationTableB->MethodItemSize;
02397         }
02398 
02399         /* now allocate the property sets */
02400         Table->MethodSets = AllocateItem(NonPagedPool, sizeof(KSMETHOD_SET) * Table->MethodSetsCount);
02401 
02402         if (!Table->MethodSets)
02403         {
02404             /* not enough memory */
02405             goto cleanup;
02406         }
02407 
02408         if (Bag)
02409         {
02410             /* add set to property bag */
02411             Status = KsAddItemToObjectBag(Bag, (PVOID)Table->MethodSets, NULL);
02412             /* check for success */
02413             if (!NT_SUCCESS(Status))
02414             {
02415                 /* cleanup table */
02416                 goto cleanup;
02417             }
02418         }
02419         /* now copy the property sets */
02420         Status = KspCopyMethodSets(Table, AutomationTableA, AutomationTableB);
02421         if(!NT_SUCCESS(Status))
02422             goto cleanup;
02423     }
02424 
02425 
02426     /* now count the event sets */
02427     Table->EventSetsCount = KspCountEventSets(AutomationTableA, AutomationTableB);
02428 
02429     if (Table->EventSetsCount)
02430     {
02431         if (AutomationTableA)
02432         {
02433             /* use item size from dominant automation table */
02434             Table->EventItemSize  = AutomationTableA->EventItemSize;
02435         }
02436         else
02437         {
02438             /* use item size from 2nd automation table */
02439             Table->EventItemSize = AutomationTableB->EventItemSize;
02440         }
02441 
02442         /* now allocate the property sets */
02443         Table->EventSets = AllocateItem(NonPagedPool, sizeof(KSEVENT_SET) * Table->EventSetsCount);
02444 
02445         if (!Table->EventSets)
02446         {
02447             /* not enough memory */
02448             goto cleanup;
02449         }
02450 
02451         if (Bag)
02452         {
02453             /* add set to property bag */
02454             Status = KsAddItemToObjectBag(Bag, (PVOID)Table->EventSets, NULL);
02455             /* check for success */
02456             if (!NT_SUCCESS(Status))
02457             {
02458                 /* cleanup table */
02459                 goto cleanup;
02460             }
02461         }
02462         /* now copy the property sets */
02463         Status = KspCopyEventSets(Table, AutomationTableA, AutomationTableB);
02464         if(!NT_SUCCESS(Status))
02465             goto cleanup;
02466     }
02467 
02468     /* store result */
02469     *AutomationTableAB = Table;
02470 
02471     return Status;
02472 
02473 
02474 cleanup:
02475 
02476     if (Table)
02477     {
02478         if (Table->PropertySets)
02479         {
02480             /* clean property sets */
02481             if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->PropertySets, TRUE)))
02482                 FreeItem((PVOID)Table->PropertySets);
02483         }
02484 
02485         if (Table->MethodSets)
02486         {
02487             /* clean property sets */
02488             if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->MethodSets, TRUE)))
02489                 FreeItem((PVOID)Table->MethodSets);
02490         }
02491 
02492         if (Table->EventSets)
02493         {
02494             /* clean property sets */
02495             if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, (PVOID)Table->EventSets, TRUE)))
02496                 FreeItem((PVOID)Table->EventSets);
02497         }
02498 
02499         if (!Bag || !NT_SUCCESS(KsRemoveItemFromObjectBag(Bag, Table, TRUE)))
02500                 FreeItem(Table);
02501     }
02502 
02503     return STATUS_INSUFFICIENT_RESOURCES;
02504 }
02505 
02506 /*
02507     @unimplemented
02508 */
02509 KSDDKAPI
02510 PUNKNOWN
02511 NTAPI
02512 KsRegisterAggregatedClientUnknown(
02513     IN PVOID  Object,
02514     IN PUNKNOWN  ClientUnknown)
02515 {
02516     PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
02517 
02518     /* sanity check */
02519     ASSERT(BasicHeader->Type == KsObjectTypeDevice || BasicHeader->Type == KsObjectTypeFilterFactory || 
02520            BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
02521 
02522     if (BasicHeader->ClientAggregate)
02523     {
02524         /* release existing aggregate */
02525         BasicHeader->ClientAggregate->lpVtbl->Release(BasicHeader->ClientAggregate);
02526     }
02527 
02528     /* increment reference count */
02529     ClientUnknown->lpVtbl->AddRef(ClientUnknown);
02530 
02531     /* store client aggregate */
02532     BasicHeader->ClientAggregate = ClientUnknown;
02533 
02534     /* return objects outer unknown */
02535     return BasicHeader->OuterUnknown;
02536 }
02537 
02538 /*
02539     @unimplemented
02540 */
02541 NTSTATUS
02542 NTAPI
02543 KsRegisterFilterWithNoKSPins(
02544     IN PDEVICE_OBJECT  DeviceObject,
02545     IN const GUID*  InterfaceClassGUID,
02546     IN ULONG  PinCount,
02547     IN BOOL*  PinDirection,
02548     IN KSPIN_MEDIUM*  MediumList,
02549     IN GUID*  CategoryList OPTIONAL)
02550 {
02551     ULONG Size, Index;
02552     NTSTATUS Status;
02553     PWSTR SymbolicLinkList;
02554     //PUCHAR Buffer;
02555     HANDLE hKey;
02556     UNICODE_STRING InterfaceString;
02557     //UNICODE_STRING FilterData = RTL_CONSTANT_STRING(L"FilterData");
02558 
02559     if (!InterfaceClassGUID || !PinCount || !PinDirection || !MediumList)
02560     {
02561         /* all these parameters are required */
02562         return STATUS_INVALID_PARAMETER;
02563     }
02564 
02565     /* calculate filter data value size */
02566     Size = PinCount * sizeof(KSPIN_MEDIUM);
02567     if (CategoryList)
02568     {
02569         /* add category list */
02570         Size += PinCount * sizeof(GUID);
02571     }
02572 
02573     /* FIXME generate filter data blob */
02574     UNIMPLEMENTED
02575 
02576     /* get symbolic link list */
02577     Status = IoGetDeviceInterfaces(InterfaceClassGUID, DeviceObject, DEVICE_INTERFACE_INCLUDE_NONACTIVE, &SymbolicLinkList);
02578     if (NT_SUCCESS(Status))
02579     {
02580         /* initialize first symbolic link */
02581         RtlInitUnicodeString(&InterfaceString, SymbolicLinkList);
02582 
02583         /* open first device interface registry key */
02584         Status = IoOpenDeviceInterfaceRegistryKey(&InterfaceString, GENERIC_WRITE, &hKey);
02585 
02586         if (NT_SUCCESS(Status))
02587         {
02588             /* write filter data */
02589             //Status = ZwSetValueKey(hKey, &FilterData, 0, REG_BINARY, Buffer, Size);
02590 
02591             /* close the key */
02592             ZwClose(hKey);
02593         }
02594 
02595         if (PinCount)
02596         {
02597             /* update medium cache */
02598             for(Index = 0; Index < PinCount; Index++)
02599             {
02600                 KsCacheMedium(&InterfaceString, &MediumList[Index], PinDirection[Index]);
02601             }
02602         }
02603 
02604         /* free the symbolic link list */
02605         FreeItem(SymbolicLinkList);
02606     }
02607 
02608     return Status;
02609 }

Generated on Sat May 26 2012 04:21:02 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.