2e7ff0e2a39f3afc0bf783e2201e19b6478a80ad
[reactos.git] / reactos / drivers / ksfilter / ks / clocks.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/ksfilter/ks/clocks.c
5 * PURPOSE: KS Clocks functions
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9
10 #include "priv.h"
11
12 typedef struct
13 {
14 LONGLONG Time;
15 KSPIN_LOCK TimeLock;
16 KSSTATE State;
17 KTIMER Timer;
18 LONG ReferenceCount;
19
20 PVOID Context;
21 PFNKSSETTIMER SetTimer;
22 PFNKSCANCELTIMER CancelTimer;
23 PFNKSCORRELATEDTIME CorrelatedTime;
24 KSRESOLUTION* Resolution;
25 ULONG Flags;
26
27 }KSIDEFAULTCLOCK, *PKSIDEFAULTCLOCK;
28
29 typedef struct
30 {
31 IKsClock *lpVtbl;
32 LONG ref;
33 PKSCLOCK_CREATE ClockCreate;
34 PKSIDEFAULTCLOCK DefaultClock;
35 PKSIOBJECT_HEADER ObjectHeader;
36 }KSICLOCK, *PKSICLOCK;
37
38
39 /*
40 @implemented
41 */
42 KSDDKAPI NTSTATUS NTAPI
43 KsCreateClock(
44 IN HANDLE ConnectionHandle,
45 IN PKSCLOCK_CREATE ClockCreate,
46 OUT PHANDLE ClockHandle)
47 {
48 return KspCreateObjectType(ConnectionHandle,
49 KSSTRING_Clock,
50 ClockCreate,
51 sizeof(KSCLOCK_CREATE),
52 GENERIC_READ,
53 ClockHandle);
54 }
55
56 /*
57 @implemented
58 */
59 KSDDKAPI
60 NTSTATUS
61 NTAPI
62 KsValidateClockCreateRequest(
63 IN PIRP Irp,
64 OUT PKSCLOCK_CREATE* OutClockCreate)
65 {
66 PKSCLOCK_CREATE ClockCreate;
67 NTSTATUS Status;
68 ULONG Size;
69
70 /* minimum request size */
71 Size = sizeof(KSCLOCK_CREATE);
72
73 /* copy create request */
74 Status = KspCopyCreateRequest(Irp,
75 KSSTRING_Clock,
76 &Size,
77 (PVOID*)&ClockCreate);
78
79 if (!NT_SUCCESS(Status))
80 return Status;
81
82 if (ClockCreate->CreateFlags != 0)
83 {
84 /* flags must be zero */
85 FreeItem(ClockCreate);
86 return STATUS_INVALID_PARAMETER;
87 }
88
89 *OutClockCreate = ClockCreate;
90 return STATUS_SUCCESS;
91 }
92
93 NTSTATUS
94 NTAPI
95 IKsClock_DispatchDeviceIoControl(
96 IN PDEVICE_OBJECT DeviceObject,
97 IN PIRP Irp)
98 {
99 UNIMPLEMENTED
100
101 Irp->IoStatus.Status = STATUS_SUCCESS;
102 IoCompleteRequest(Irp, IO_NO_INCREMENT);
103
104 return STATUS_SUCCESS;
105 }
106
107 NTSTATUS
108 NTAPI
109 IKsClock_DispatchClose(
110 IN PDEVICE_OBJECT DeviceObject,
111 IN PIRP Irp)
112 {
113 UNIMPLEMENTED
114
115 Irp->IoStatus.Status = STATUS_SUCCESS;
116 IoCompleteRequest(Irp, IO_NO_INCREMENT);
117
118 return STATUS_SUCCESS;
119 }
120
121 static KSDISPATCH_TABLE DispatchTable =
122 {
123 IKsClock_DispatchDeviceIoControl,
124 KsDispatchInvalidDeviceRequest,
125 KsDispatchInvalidDeviceRequest,
126 KsDispatchInvalidDeviceRequest,
127 IKsClock_DispatchClose,
128 KsDispatchQuerySecurity,
129 KsDispatchSetSecurity,
130 KsDispatchFastIoDeviceControlFailure,
131 KsDispatchFastReadFailure,
132 KsDispatchFastReadFailure,
133 };
134
135 /*
136 @implemented
137 */
138 KSDDKAPI
139 NTSTATUS
140 NTAPI
141 KsCreateDefaultClock(
142 IN PIRP Irp,
143 IN PKSDEFAULTCLOCK DefaultClock)
144 {
145 NTSTATUS Status;
146 PKSCLOCK_CREATE ClockCreate;
147 PKSICLOCK Clock;
148 PKSOBJECT_CREATE_ITEM CreateItem;
149
150 Status = KsValidateClockCreateRequest(Irp, &ClockCreate);
151 if (!NT_SUCCESS(Status))
152 return Status;
153
154 /* let's allocate the clock struct */
155 Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
156 if (!Clock)
157 return STATUS_INSUFFICIENT_RESOURCES;
158
159 /* now allocate the object header */
160 Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
161
162 /* did it work */
163 if (!NT_SUCCESS(Status))
164 {
165 /* failed */
166 FreeItem(Clock);
167 return Status;
168 }
169
170 /* initialize clock */
171 /* FIXME IKsClock */
172 Clock->ObjectHeader->Unknown = (PUNKNOWN)&Clock->lpVtbl;
173 Clock->ref = 1;
174 Clock->ClockCreate = ClockCreate;
175 Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
176
177 /* increment reference count */
178 InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
179
180 /* get create item */
181 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
182
183 return Status;
184 }
185
186 /*
187 @implemented
188 */
189 KSDDKAPI
190 NTSTATUS
191 NTAPI
192 KsAllocateDefaultClock(
193 OUT PKSDEFAULTCLOCK* DefaultClock)
194 {
195 return KsAllocateDefaultClockEx(DefaultClock, NULL, NULL, NULL, NULL, NULL, 0);
196 }
197
198 /*
199 @unimplemented
200 */
201 KSDDKAPI
202 NTSTATUS
203 NTAPI
204 KsAllocateDefaultClockEx(
205 OUT PKSDEFAULTCLOCK* DefaultClock,
206 IN PVOID Context OPTIONAL,
207 IN PFNKSSETTIMER SetTimer OPTIONAL,
208 IN PFNKSCANCELTIMER CancelTimer OPTIONAL,
209 IN PFNKSCORRELATEDTIME CorrelatedTime OPTIONAL,
210 IN const KSRESOLUTION* Resolution OPTIONAL,
211 IN ULONG Flags)
212 {
213 PKSIDEFAULTCLOCK Clock;
214
215 if (!DefaultClock)
216 return STATUS_INVALID_PARAMETER_1;
217
218 /* allocate default clock */
219 Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
220 if (!Clock)
221 return STATUS_INSUFFICIENT_RESOURCES;
222
223 /* initialize default clock */
224 KeInitializeSpinLock(&Clock->TimeLock);
225 KeInitializeTimer(&Clock->Timer);
226 Clock->ReferenceCount = 1;
227 Clock->Context = Context;
228 Clock->SetTimer = SetTimer;
229 Clock->CancelTimer = CancelTimer;
230 Clock->CorrelatedTime = CorrelatedTime;
231 Clock->Resolution = (PKSRESOLUTION)Resolution;
232 Clock->Flags = Flags;
233
234 *DefaultClock = (PKSDEFAULTCLOCK)Clock;
235 return STATUS_SUCCESS;
236 }
237
238 /*
239 @implemented
240 */
241 KSDDKAPI
242 VOID
243 NTAPI
244 KsFreeDefaultClock(
245 IN PKSDEFAULTCLOCK DefaultClock)
246 {
247 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
248
249 InterlockedDecrement(&Clock->ReferenceCount);
250
251 if (Clock->ReferenceCount == 0)
252 {
253 /* free default clock */
254 FreeItem(Clock);
255 }
256 }
257
258 /*
259 @implemented
260 */
261 KSDDKAPI
262 KSSTATE
263 NTAPI
264 KsGetDefaultClockState(
265 IN PKSDEFAULTCLOCK DefaultClock)
266 {
267 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
268 return Clock->State;
269 }
270
271 /*
272 @unimplemented
273 */
274 KSDDKAPI
275 VOID
276 NTAPI
277 KsSetDefaultClockState(
278 IN PKSDEFAULTCLOCK DefaultClock,
279 IN KSSTATE State)
280 {
281 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
282
283 if (State != Clock->State)
284 {
285 /* FIXME set time etc */
286 Clock->State = State;
287 }
288
289 }
290
291 /*
292 @implemented
293 */
294 KSDDKAPI
295 LONGLONG
296 NTAPI
297 KsGetDefaultClockTime(
298 IN PKSDEFAULTCLOCK DefaultClock)
299 {
300 LONGLONG Time = 0LL;
301 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
302
303 Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
304
305 return Time;
306 }
307
308 /*
309 @implemented
310 */
311 KSDDKAPI
312 VOID
313 NTAPI
314 KsSetDefaultClockTime(
315 IN PKSDEFAULTCLOCK DefaultClock,
316 IN LONGLONG Time)
317 {
318 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
319
320 /* set the time safely */
321 ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
322 }