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

  1. //---------------------------------------------------------------------------
  2. //
  3. // Module: clock.c
  4. //
  5. // Description:
  6. //
  7. //
  8. //@@BEGIN_MSINTERNAL
  9. // Development Team:
  10. // Mike McLaughlin
  11. //
  12. // History: Date Author Comment
  13. //
  14. // To Do: Date Author Comment
  15. //
  16. //@@END_MSINTERNAL
  17. //
  18. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  19. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  20. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  21. // PURPOSE.
  22. //
  23. // Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
  24. //
  25. //---------------------------------------------------------------------------
  26. #include "common.h"
  27. //---------------------------------------------------------------------------
  28. DEFINE_KSDISPATCH_TABLE(
  29. ClockDispatchTable,
  30. CClockInstance::ClockDispatchIoControl, // Ioctl
  31. DispatchInvalidDeviceRequest, // Read
  32. DispatchInvalidDeviceRequest, // Write
  33. DispatchInvalidDeviceRequest, // Flush
  34. CInstance::DispatchClose, // Close
  35. DispatchInvalidDeviceRequest, // QuerySecurity
  36. DispatchInvalidDeviceRequest, // SetSeturity
  37. DispatchFastIoDeviceControlFailure, // FastDeviceIoControl
  38. DispatchFastReadFailure, // FastRead
  39. DispatchFastWriteFailure // FastWrite
  40. );
  41. DEFINE_KSPROPERTY_TABLE(ClockPropertyItems)
  42. {
  43. DEFINE_KSPROPERTY_ITEM_CLOCK_FUNCTIONTABLE(
  44. CClockInstance::ClockGetFunctionTable
  45. )
  46. };
  47. DEFINE_KSPROPERTY_SET_TABLE(ClockPropertySets)
  48. {
  49. DEFINE_KSPROPERTY_SET(
  50. &KSPROPSETID_Clock,
  51. SIZEOF_ARRAY(ClockPropertyItems),
  52. ClockPropertyItems,
  53. 0,
  54. NULL
  55. )
  56. };
  57. KSCLOCK_FUNCTIONTABLE ClockFunctionTable = {
  58. CClockInstance::ClockGetTime,
  59. CClockInstance::ClockGetPhysicalTime,
  60. CClockInstance::ClockGetCorrelatedTime,
  61. CClockInstance::ClockGetCorrelatedPhysicalTime,
  62. };
  63. //---------------------------------------------------------------------------
  64. //---------------------------------------------------------------------------
  65. CClockInstance::CClockInstance(
  66. IN PPARENT_INSTANCE pParentInstance
  67. ) : CInstance(pParentInstance)
  68. {
  69. }
  70. NTSTATUS
  71. CClockInstance::ClockDispatchCreate(
  72. IN PDEVICE_OBJECT pDeviceObject,
  73. IN PIRP pIrp
  74. )
  75. {
  76. PSTART_NODE_INSTANCE pStartNodeInstance;
  77. PCLOCK_INSTANCE pClockInstance = NULL;
  78. PKSCLOCK_CREATE pClockCreate;
  79. KSPROPERTY Property;
  80. ULONG BytesReturned;
  81. NTSTATUS Status;
  82. ::GrabMutex();
  83. Status = GetRelatedStartNodeInstance(pIrp, &pStartNodeInstance);
  84. if(!NT_SUCCESS(Status)) {
  85. goto exit;
  86. }
  87. Assert(pStartNodeInstance);
  88. Status = KsValidateClockCreateRequest(
  89. pIrp,
  90. &pClockCreate);
  91. if(!NT_SUCCESS(Status)) {
  92. DPF1(5,
  93. "ClockDispatchCreate: KsValidateClockCreateRequest FAILED %08x",
  94. Status);
  95. goto exit;
  96. }
  97. // Allocate per clock instance data
  98. pClockInstance = new CLOCK_INSTANCE(
  99. &pStartNodeInstance->pPinInstance->ParentInstance);
  100. if(pClockInstance == NULL) {
  101. Trap();
  102. Status = STATUS_INSUFFICIENT_RESOURCES;
  103. goto exit;
  104. }
  105. Status = pClockInstance->DispatchCreate(
  106. pIrp,
  107. (UTIL_PFN)ClockDispatchCreateKP,
  108. pClockCreate,
  109. 0,
  110. NULL,
  111. &ClockDispatchTable);
  112. if(!NT_SUCCESS(Status)) {
  113. DPF1(5, "ClockDispatchCreateKP: FAILED %08x", Status);
  114. goto exit;
  115. }
  116. //
  117. // Issue the ioctl to get the function table of the master clock.
  118. //
  119. Property.Set = KSPROPSETID_Clock;
  120. Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
  121. Property.Flags = KSPROPERTY_TYPE_GET;
  122. AssertFileObject(pClockInstance->GetNextFileObject());
  123. Status = KsSynchronousIoControlDevice(
  124. pClockInstance->GetNextFileObject(),
  125. KernelMode,
  126. IOCTL_KS_PROPERTY,
  127. &Property,
  128. sizeof(KSPROPERTY),
  129. &pClockInstance->FunctionTable,
  130. sizeof(KSCLOCK_FUNCTIONTABLE),
  131. &BytesReturned);
  132. if(!NT_SUCCESS(Status)) {
  133. Trap();
  134. goto exit;
  135. }
  136. exit:
  137. if(!NT_SUCCESS(Status)) {
  138. delete pClockInstance;
  139. }
  140. ::ReleaseMutex();
  141. pIrp->IoStatus.Status = Status;
  142. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  143. return Status;
  144. }
  145. NTSTATUS
  146. CClockInstance::ClockDispatchCreateKP(
  147. PCLOCK_INSTANCE pClockInstance,
  148. PKSCLOCK_CREATE pClockCreate
  149. )
  150. {
  151. PPIN_INSTANCE pPinInstance;
  152. HANDLE hClock = NULL;
  153. NTSTATUS Status;
  154. Assert(pClockInstance);
  155. pPinInstance = pClockInstance->GetParentInstance();
  156. Assert(pPinInstance);
  157. Assert(pPinInstance->pStartNodeInstance);
  158. Assert(pPinInstance->pStartNodeInstance->pPinNodeInstance);
  159. ASSERT(pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin != NULL);
  160. Status = KsCreateClock(
  161. pPinInstance->pStartNodeInstance->pPinNodeInstance->hPin,
  162. pClockCreate,
  163. &hClock);
  164. if(!NT_SUCCESS(Status)) {
  165. goto exit;
  166. }
  167. Status = pClockInstance->SetNextFileObject(hClock);
  168. if(!NT_SUCCESS(Status)) {
  169. Trap();
  170. goto exit;
  171. }
  172. exit:
  173. if(hClock != NULL) {
  174. ZwClose(hClock);
  175. }
  176. return(Status);
  177. }
  178. NTSTATUS
  179. CClockInstance::ClockDispatchIoControl(
  180. IN PDEVICE_OBJECT pDeviceObject,
  181. IN PIRP pIrp
  182. )
  183. {
  184. PIO_STACK_LOCATION pIrpStack;
  185. NTSTATUS Status;
  186. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  187. switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
  188. case IOCTL_KS_PROPERTY:
  189. Status = KsPropertyHandler(
  190. pIrp,
  191. SIZEOF_ARRAY(ClockPropertySets),
  192. (PKSPROPERTY_SET)&ClockPropertySets);
  193. if(Status == STATUS_NOT_FOUND ||
  194. Status == STATUS_PROPSET_NOT_FOUND) {
  195. break;
  196. }
  197. pIrp->IoStatus.Status = Status;
  198. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  199. return(Status);
  200. }
  201. return(DispatchForwardIrp(pDeviceObject, pIrp));
  202. }
  203. //---------------------------------------------------------------------------
  204. NTSTATUS
  205. CClockInstance::ClockGetFunctionTable(
  206. IN PIRP pIrp,
  207. IN PKSPROPERTY pProperty,
  208. IN OUT PKSCLOCK_FUNCTIONTABLE pFunctionTable
  209. )
  210. {
  211. *pFunctionTable = ClockFunctionTable;
  212. pIrp->IoStatus.Information = sizeof(KSCLOCK_FUNCTIONTABLE);
  213. return(STATUS_SUCCESS);
  214. }
  215. LONGLONG
  216. FASTCALL
  217. CClockInstance::ClockGetTime(
  218. IN PFILE_OBJECT pFileObject
  219. )
  220. {
  221. PCLOCK_INSTANCE pClockInstance;
  222. pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext;
  223. Assert(pClockInstance);
  224. return(pClockInstance->FunctionTable.GetTime(
  225. pClockInstance->GetNextFileObject()));
  226. }
  227. LONGLONG
  228. FASTCALL
  229. CClockInstance::ClockGetPhysicalTime(
  230. IN PFILE_OBJECT pFileObject
  231. )
  232. {
  233. PCLOCK_INSTANCE pClockInstance;
  234. pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext;
  235. Assert(pClockInstance);
  236. return(pClockInstance->FunctionTable.GetPhysicalTime(
  237. pClockInstance->GetNextFileObject()));
  238. }
  239. LONGLONG
  240. FASTCALL
  241. CClockInstance::ClockGetCorrelatedTime(
  242. IN PFILE_OBJECT pFileObject,
  243. OUT PLONGLONG Time
  244. )
  245. {
  246. PCLOCK_INSTANCE pClockInstance;
  247. pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext;
  248. Assert(pClockInstance);
  249. return(pClockInstance->FunctionTable.GetCorrelatedTime(
  250. pClockInstance->GetNextFileObject(),
  251. Time));
  252. }
  253. LONGLONG
  254. FASTCALL
  255. CClockInstance::ClockGetCorrelatedPhysicalTime(
  256. IN PFILE_OBJECT pFileObject,
  257. OUT PLONGLONG Time
  258. )
  259. {
  260. PCLOCK_INSTANCE pClockInstance;
  261. pClockInstance = (PCLOCK_INSTANCE)pFileObject->FsContext;
  262. Assert(pClockInstance);
  263. return(pClockInstance->FunctionTable.GetCorrelatedPhysicalTime(
  264. pClockInstance->GetNextFileObject(),
  265. Time));
  266. }
  267. //---------------------------------------------------------------------------