//--------------------------------------------------------------------------- // // Module: clock.c // // Description: // // //@@BEGIN_MSINTERNAL // Development Team: // Mike McLaughlin // // History: Date Author Comment // // To Do: Date Author Comment // //@@END_MSINTERNAL // // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR // PURPOSE. // // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved. // //--------------------------------------------------------------------------- #include "common.h" //--------------------------------------------------------------------------- DEFINE_KSDISPATCH_TABLE( ClockDispatchTable, CClockInstance::ClockDispatchIoControl, // Ioctl DispatchInvalidDeviceRequest, // Read DispatchInvalidDeviceRequest, // Write DispatchInvalidDeviceRequest, // Flush CInstance::DispatchClose, // Close DispatchInvalidDeviceRequest, // QuerySecurity DispatchInvalidDeviceRequest, // SetSeturity DispatchFastIoDeviceControlFailure, // FastDeviceIoControl DispatchFastReadFailure, // FastRead DispatchFastWriteFailure // FastWrite ); DEFINE_KSPROPERTY_TABLE(ClockPropertyItems) { DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE( CClockInstance::ClockGetFunctionTable ) }; DEFINE_KSPROPERTY_SET_TABLE(ClockPropertySets) { DEFINE_KSPROPERTY_SET( &KSPROPSETID_Clock, SIZEOF_ARRAY(ClockPropertyItems), ClockPropertyItems, 0, NULL ) }; KSCLOCK_FUNCTIONTABLE ClockFunctionTable = { CClockInstance::ClockGetTime, CClockInstance::ClockGetPhysicalTime, CClockInstance::ClockGetCorrelatedTime, CClockInstance::ClockGetCorrelatedPhysicalTime, }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- CClockInstance::CClockInstance( IN PPARENT_INSTANCE pParentInstance ) : CInstance(pParentInstance) { } NTSTATUS CClockInstance::ClockDispatchCreate( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PSTART_NODE_INSTANCE pStartNodeInstance; PCLOCK_INSTANCE pClockInstance = NULL; PKSCLOCK_CREATE pClockCreate; KSPROPERTY Property; ULONG BytesReturned; NTSTATUS Status; ::GrabMutex(); Status = GetRelatedStartNodeInstance(pIrp, &pStartNodeInstance); if(!NT_SUCCESS(Status)) { goto exit; } Assert(pStartNodeInstance); Status = KsValidateClockCreateRequest( pIrp, &pClockCreate); if(!NT_SUCCESS(Status)) { DPF1(5, "ClockDispatchCreate: KsValidateClockCreateRequest FAILED %08x", Status); goto exit; } // Allocate per clock instance data pClockInstance = new CLOCK_INSTANCE( &pStartNodeInstance->pPinInstance->ParentInstance); if(pClockInstance == NULL) { Trap(); Status = STATUS_INSUFFICIENT_RESOURCES; goto exit; } Status = pClockInstance->DispatchCreate( pIrp, (UTIL_PFN)ClockDispatchCreateKP, pClockCreate, 0, NULL, &ClockDispatchTable); if(!NT_SUCCESS(Status)) { DPF1(5, "ClockDispatchCreateKP: FAILED %08x", Status); goto exit; } // // Issue the ioctl to get the function table of the master clock. // Property.Set = KSPROPSETID_Clock; Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE; Property.Flags = KSPROPERTY_TYPE_GET; AssertFileObject(pClockInstance->GetNextFileObject()); Status = KsSynchronousIoControlDevice( pClockInstance->GetNextFileObject(), KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &pClockInstance->FunctionTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned); if(!NT_SUCCESS(Status)) { Trap(); goto exit; } exit: if(!NT_SUCCESS(Status)) { delete pClockInstance; } ::ReleaseMutex(); pIrp->IoStatus.Status = Status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return Status; } NTSTATUS CClockInstance::ClockDispatchCreateKP( PCLOCK_INSTANCE pClockInstance, PKSCLOCK_CREATE pClockCreate ) { PPIN_INSTANCE pPinInstance; HANDLE hClock = NULL; NTSTATUS Status; Assert(pClockInstance); pPinInstance = pClockInstance->GetParentInstance(); Assert(pPinInstance); Assert(pPinInstance->pStartNodeInstance); Assert(pPinInstance->pStartNodeInstance->pPinNodeInstance); ASSERT(pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin != NULL); Status = KsCreateClock( pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin, pClockCreate, &hClock); if(!NT_SUCCESS(Status)) { goto exit; } Status = pClockInstance->SetNextFileObject(hClock); if(!NT_SUCCESS(Status)) { Trap(); goto exit; } exit: if(hClock != NULL) { ZwClose(hClock); } return(Status); } NTSTATUS CClockInstance::ClockDispatchIoControl( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PIO_STACK_LOCATION pIrpStack; NTSTATUS Status; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_KS_PROPERTY: Status = KsPropertyHandler( pIrp, SIZEOF_ARRAY(ClockPropertySets), (PKSPROPERTY_SET)&ClockPropertySets); if(Status == STATUS_NOT_FOUND || Status == STATUS_PROPSET_NOT_FOUND) { break; } pIrp->IoStatus.Status = Status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return(Status); } return(DispatchForwardIrp(pDeviceObject, pIrp)); } //--------------------------------------------------------------------------- NTSTATUS CClockInstance::ClockGetFunctionTable( IN PIRP pIrp, IN PKSPROPERTY pProperty, IN OUT PKSCLOCK_FUNCTIONTABLE pFunctionTable ) { *pFunctionTable = ClockFunctionTable; pIrp->IoStatus.Information = sizeof(KSCLOCK_FUNCTIONTABLE); return(STATUS_SUCCESS); } LONGLONG FASTCALL CClockInstance::ClockGetTime( IN PFILE_OBJECT pFileObject ) { PCLOCK_INSTANCE pClockInstance; pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext; Assert(pClockInstance); return(pClockInstance->FunctionTable.GetTime( pClockInstance->GetNextFileObject())); } LONGLONG FASTCALL CClockInstance::ClockGetPhysicalTime( IN PFILE_OBJECT pFileObject ) { PCLOCK_INSTANCE pClockInstance; pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext; Assert(pClockInstance); return(pClockInstance->FunctionTable.GetPhysicalTime( pClockInstance->GetNextFileObject())); } LONGLONG FASTCALL CClockInstance::ClockGetCorrelatedTime( IN PFILE_OBJECT pFileObject, OUT PLONGLONG Time ) { PCLOCK_INSTANCE pClockInstance; pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext; Assert(pClockInstance); return(pClockInstance->FunctionTable.GetCorrelatedTime( pClockInstance->GetNextFileObject(), Time)); } LONGLONG FASTCALL CClockInstance::ClockGetCorrelatedPhysicalTime( IN PFILE_OBJECT pFileObject, OUT PLONGLONG Time ) { PCLOCK_INSTANCE pClockInstance; pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext; Assert(pClockInstance); return(pClockInstance->FunctionTable.GetCorrelatedPhysicalTime( pClockInstance->GetNextFileObject(), Time)); } //---------------------------------------------------------------------------