313 lines
7.4 KiB
C++
313 lines
7.4 KiB
C++
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// 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));
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|