Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

312 lines
7.4 KiB

//---------------------------------------------------------------------------
//
// 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));
}
//---------------------------------------------------------------------------