[KS]
[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_NOT_IMPLEMENTED;
116 IoCompleteRequest(Irp, IO_NO_INCREMENT);
117
118 return STATUS_NOT_IMPLEMENTED;
119 }
120
121
122
123 static KSDISPATCH_TABLE DispatchTable =
124 {
125 IKsClock_DispatchDeviceIoControl,
126 KsDispatchInvalidDeviceRequest,
127 KsDispatchInvalidDeviceRequest,
128 KsDispatchInvalidDeviceRequest,
129 IKsClock_DispatchClose,
130 KsDispatchQuerySecurity,
131 KsDispatchSetSecurity,
132 KsDispatchFastIoDeviceControlFailure,
133 KsDispatchFastReadFailure,
134 KsDispatchFastReadFailure,
135 };
136
137 /*
138 @implemented
139 */
140 KSDDKAPI
141 NTSTATUS
142 NTAPI
143 KsCreateDefaultClock(
144 IN PIRP Irp,
145 IN PKSDEFAULTCLOCK DefaultClock)
146 {
147 NTSTATUS Status;
148 PKSCLOCK_CREATE ClockCreate;
149 PKSICLOCK Clock;
150 PKSOBJECT_CREATE_ITEM CreateItem;
151
152 Status = KsValidateClockCreateRequest(Irp, &ClockCreate);
153 if (!NT_SUCCESS(Status))
154 return Status;
155
156 /* let's allocate the clock struct */
157 Clock = AllocateItem(NonPagedPool, sizeof(KSICLOCK));
158 if (!Clock)
159 return STATUS_INSUFFICIENT_RESOURCES;
160
161 /* now allocate the object header */
162 Status = KsAllocateObjectHeader((PVOID*)&Clock->ObjectHeader, 0, NULL, Irp, &DispatchTable);
163
164 /* did it work */
165 if (!NT_SUCCESS(Status))
166 {
167 /* failed */
168 FreeItem(Clock);
169 return Status;
170 }
171
172 /* initialize clock */
173 /* FIXME IKsClock */
174 Clock->ObjectHeader->Unknown = (PUNKNOWN)&Clock->lpVtbl;
175 Clock->ref = 1;
176 Clock->ClockCreate = ClockCreate;
177 Clock->DefaultClock = (PKSIDEFAULTCLOCK)DefaultClock;
178
179 /* increment reference count */
180 InterlockedIncrement(&Clock->DefaultClock->ReferenceCount);
181
182 /* get create item */
183 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
184
185 return Status;
186 }
187
188 /*
189 @implemented
190 */
191 KSDDKAPI
192 NTSTATUS
193 NTAPI
194 KsAllocateDefaultClock(
195 OUT PKSDEFAULTCLOCK* DefaultClock)
196 {
197 return KsAllocateDefaultClockEx(DefaultClock, NULL, NULL, NULL, NULL, NULL, 0);
198 }
199
200 /*
201 @unimplemented
202 */
203 KSDDKAPI
204 NTSTATUS
205 NTAPI
206 KsAllocateDefaultClockEx(
207 OUT PKSDEFAULTCLOCK* DefaultClock,
208 IN PVOID Context OPTIONAL,
209 IN PFNKSSETTIMER SetTimer OPTIONAL,
210 IN PFNKSCANCELTIMER CancelTimer OPTIONAL,
211 IN PFNKSCORRELATEDTIME CorrelatedTime OPTIONAL,
212 IN const KSRESOLUTION* Resolution OPTIONAL,
213 IN ULONG Flags)
214 {
215 PKSIDEFAULTCLOCK Clock;
216
217 if (!DefaultClock)
218 return STATUS_INVALID_PARAMETER_1;
219
220 /* allocate default clock */
221 Clock = AllocateItem(NonPagedPool, sizeof(KSIDEFAULTCLOCK));
222 if (!Clock)
223 return STATUS_INSUFFICIENT_RESOURCES;
224
225 /* initialize default clock */
226 KeInitializeSpinLock(&Clock->TimeLock);
227 KeInitializeTimer(&Clock->Timer);
228 Clock->ReferenceCount = 1;
229 Clock->Context = Context;
230 Clock->SetTimer = SetTimer;
231 Clock->CancelTimer = CancelTimer;
232 Clock->CorrelatedTime = CorrelatedTime;
233 Clock->Resolution = (PKSRESOLUTION)Resolution;
234 Clock->Flags = Flags;
235
236 *DefaultClock = (PKSDEFAULTCLOCK)Clock;
237 return STATUS_SUCCESS;
238 }
239
240 /*
241 @implemented
242 */
243 KSDDKAPI
244 VOID
245 NTAPI
246 KsFreeDefaultClock(
247 IN PKSDEFAULTCLOCK DefaultClock)
248 {
249 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
250
251 InterlockedDecrement(&Clock->ReferenceCount);
252
253 if (Clock->ReferenceCount == 0)
254 {
255 /* free default clock */
256 FreeItem(Clock);
257 }
258 }
259
260 /*
261 @implemented
262 */
263 KSDDKAPI
264 KSSTATE
265 NTAPI
266 KsGetDefaultClockState(
267 IN PKSDEFAULTCLOCK DefaultClock)
268 {
269 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
270 return Clock->State;
271 }
272
273 /*
274 @unimplemented
275 */
276 KSDDKAPI
277 VOID
278 NTAPI
279 KsSetDefaultClockState(
280 IN PKSDEFAULTCLOCK DefaultClock,
281 IN KSSTATE State)
282 {
283 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
284
285 if (State != Clock->State)
286 {
287 /* FIXME set time etc */
288 Clock->State = State;
289 }
290
291 }
292
293 /*
294 @implemented
295 */
296 KSDDKAPI
297 LONGLONG
298 NTAPI
299 KsGetDefaultClockTime(
300 IN PKSDEFAULTCLOCK DefaultClock)
301 {
302 LONGLONG Time = 0LL;
303 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
304
305 Time = ExInterlockedCompareExchange64(&Clock->Time, &Time, &Time, &Clock->TimeLock);
306
307 return Time;
308 }
309
310 /*
311 @implemented
312 */
313 KSDDKAPI
314 VOID
315 NTAPI
316 KsSetDefaultClockTime(
317 IN PKSDEFAULTCLOCK DefaultClock,
318 IN LONGLONG Time)
319 {
320 PKSIDEFAULTCLOCK Clock = (PKSIDEFAULTCLOCK)DefaultClock;
321
322 /* set the time safely */
323 ExInterlockedCompareExchange64(&Clock->Time, &Time, &Clock->Time, &Clock->TimeLock);
324 }