Create a branch for header work.
[reactos.git] / dll / win32 / mstask / task_trigger.c
1 /*
2 * Copyright (C) 2008 Google (Roy Shea)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include <stdarg.h>
20 #include "winternl.h"
21 #include "mstask_private.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(mstask);
25
26 static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface(
27 ITaskTrigger* iface,
28 REFIID riid,
29 void **ppvObject)
30 {
31 TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
32
33 TRACE("IID: %s\n", debugstr_guid(riid));
34 if (ppvObject == NULL)
35 return E_POINTER;
36
37 if (IsEqualGUID(riid, &IID_IUnknown) ||
38 IsEqualGUID(riid, &IID_ITaskTrigger))
39 {
40 *ppvObject = &This->lpVtbl;
41 ITaskTrigger_AddRef(iface);
42 return S_OK;
43 }
44
45 WARN("Unknown interface: %s\n", debugstr_guid(riid));
46 *ppvObject = NULL;
47 return E_NOINTERFACE;
48 }
49
50 static ULONG WINAPI MSTASK_ITaskTrigger_AddRef(
51 ITaskTrigger* iface)
52 {
53 TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
54 ULONG ref;
55 TRACE("\n");
56 ref = InterlockedIncrement(&This->ref);
57 return ref;
58 }
59
60 static ULONG WINAPI MSTASK_ITaskTrigger_Release(
61 ITaskTrigger* iface)
62 {
63 TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
64 ULONG ref;
65 TRACE("\n");
66 ref = InterlockedDecrement(&This->ref);
67 if (ref == 0)
68 {
69 HeapFree(GetProcessHeap(), 0, This);
70 InterlockedDecrement(&dll_ref);
71 }
72 return ref;
73 }
74
75 static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger(
76 ITaskTrigger* iface,
77 const PTASK_TRIGGER pTrigger)
78 {
79 TaskTriggerImpl * This = (TaskTriggerImpl *)iface;
80 TIME_FIELDS field_time;
81 LARGE_INTEGER sys_time;
82 TASK_TRIGGER tmp_trigger_cond;
83
84 TRACE("(%p, %p)\n", iface, pTrigger);
85
86 /* Verify valid structure size */
87 if (pTrigger->cbTriggerSize != sizeof(*pTrigger))
88 return E_INVALIDARG;
89 tmp_trigger_cond.cbTriggerSize = pTrigger->cbTriggerSize;
90
91 /* Reserved field must be zero */
92 tmp_trigger_cond.Reserved1 = 0;
93
94 /* Verify and set valid start date and time */
95 memset(&field_time, 0, sizeof(field_time));
96 field_time.Year = pTrigger->wBeginYear;
97 field_time.Month = pTrigger->wBeginMonth;
98 field_time.Day = pTrigger->wBeginDay;
99 field_time.Hour = pTrigger->wStartHour;
100 field_time.Minute = pTrigger->wStartMinute;
101 if (!RtlTimeFieldsToTime(&field_time, &sys_time))
102 return E_INVALIDARG;
103 tmp_trigger_cond.wBeginYear = pTrigger->wBeginYear;
104 tmp_trigger_cond.wBeginMonth = pTrigger->wBeginMonth;
105 tmp_trigger_cond.wBeginDay = pTrigger->wBeginDay;
106 tmp_trigger_cond.wStartHour = pTrigger->wStartHour;
107 tmp_trigger_cond.wStartMinute = pTrigger->wStartMinute;
108
109 /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */
110 if (pTrigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE)
111 {
112 memset(&field_time, 0, sizeof(field_time));
113 field_time.Year = pTrigger->wEndYear;
114 field_time.Month = pTrigger->wEndMonth;
115 field_time.Day = pTrigger->wEndDay;
116 if (!RtlTimeFieldsToTime(&field_time, &sys_time))
117 return E_INVALIDARG;
118 }
119
120 /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */
121 tmp_trigger_cond.wEndYear = pTrigger->wEndYear;
122 tmp_trigger_cond.wEndMonth = pTrigger->wEndMonth;
123 tmp_trigger_cond.wEndDay = pTrigger->wEndDay;
124
125 /* Verify duration and interval pair */
126 if (pTrigger->MinutesDuration <= pTrigger->MinutesInterval &&
127 pTrigger->MinutesInterval > 0)
128 return E_INVALIDARG;
129 if (pTrigger->MinutesDuration > 0 && pTrigger->MinutesInterval == 0)
130 return E_INVALIDARG;
131 tmp_trigger_cond.MinutesDuration = pTrigger->MinutesDuration;
132 tmp_trigger_cond.MinutesInterval = pTrigger->MinutesInterval;
133
134 /* Copy over flags */
135 tmp_trigger_cond.rgFlags = pTrigger->rgFlags;
136
137 /* Set TriggerType dependent fields of Type union */
138 tmp_trigger_cond.TriggerType = pTrigger->TriggerType;
139 switch (pTrigger->TriggerType)
140 {
141 case TASK_TIME_TRIGGER_DAILY:
142 tmp_trigger_cond.Type.Daily.DaysInterval =
143 pTrigger->Type.Daily.DaysInterval;
144 break;
145 case TASK_TIME_TRIGGER_WEEKLY:
146 tmp_trigger_cond.Type.Weekly.WeeksInterval =
147 pTrigger->Type.Weekly.WeeksInterval;
148 tmp_trigger_cond.Type.Weekly.rgfDaysOfTheWeek =
149 pTrigger->Type.Weekly.rgfDaysOfTheWeek;
150 break;
151 case TASK_TIME_TRIGGER_MONTHLYDATE:
152 tmp_trigger_cond.Type.MonthlyDate.rgfDays =
153 pTrigger->Type.MonthlyDate.rgfDays;
154 tmp_trigger_cond.Type.MonthlyDate.rgfMonths =
155 pTrigger->Type.MonthlyDate.rgfMonths;
156 break;
157 case TASK_TIME_TRIGGER_MONTHLYDOW:
158 tmp_trigger_cond.Type.MonthlyDOW.wWhichWeek =
159 pTrigger->Type.MonthlyDOW.wWhichWeek;
160 tmp_trigger_cond.Type.MonthlyDOW.rgfDaysOfTheWeek =
161 pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek;
162 tmp_trigger_cond.Type.MonthlyDOW.rgfMonths =
163 pTrigger->Type.MonthlyDOW.rgfMonths;
164 break;
165 case TASK_TIME_TRIGGER_ONCE:
166 case TASK_EVENT_TRIGGER_ON_IDLE:
167 case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
168 case TASK_EVENT_TRIGGER_AT_LOGON:
169 default:
170 tmp_trigger_cond.Type = This->triggerCond.Type;
171 break;
172 }
173
174 /* Reserved field must be zero */
175 tmp_trigger_cond.Reserved2 = 0;
176
177 /* wRandomMinutesInterval not currently used and is initialized to zero */
178 tmp_trigger_cond.wRandomMinutesInterval = 0;
179
180 /* Update object copy of triggerCond */
181 This->triggerCond = tmp_trigger_cond;
182
183 return S_OK;
184 }
185
186 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger(
187 ITaskTrigger* iface,
188 PTASK_TRIGGER pTrigger)
189 {
190 TaskTriggerImpl * This = (TaskTriggerImpl *)iface;
191
192 TRACE("(%p, %p)\n", iface, pTrigger);
193
194 /* Native implementation doesn't verify equivalent cbTriggerSize fields */
195
196 /* Copy relevant fields of the structure */
197 pTrigger->cbTriggerSize = This->triggerCond.cbTriggerSize;
198 pTrigger->Reserved1 = 0;
199 pTrigger->wBeginYear = This->triggerCond.wBeginYear;
200 pTrigger->wBeginMonth = This->triggerCond.wBeginMonth;
201 pTrigger->wBeginDay = This->triggerCond.wBeginDay;
202 pTrigger->wEndYear = This->triggerCond.wEndYear;
203 pTrigger->wEndMonth = This->triggerCond.wEndMonth;
204 pTrigger->wEndDay = This->triggerCond.wEndDay;
205 pTrigger->wStartHour = This->triggerCond.wStartHour;
206 pTrigger->wStartMinute = This->triggerCond.wStartMinute;
207 pTrigger->MinutesDuration = This->triggerCond.MinutesDuration;
208 pTrigger->MinutesInterval = This->triggerCond.MinutesInterval;
209 pTrigger->rgFlags = This->triggerCond.rgFlags;
210 pTrigger->TriggerType = This->triggerCond.TriggerType;
211 switch (This->triggerCond.TriggerType)
212 {
213 case TASK_TIME_TRIGGER_DAILY:
214 pTrigger->Type.Daily.DaysInterval =
215 This->triggerCond.Type.Daily.DaysInterval;
216 break;
217 case TASK_TIME_TRIGGER_WEEKLY:
218 pTrigger->Type.Weekly.WeeksInterval =
219 This->triggerCond.Type.Weekly.WeeksInterval;
220 pTrigger->Type.Weekly.rgfDaysOfTheWeek =
221 This->triggerCond.Type.Weekly.rgfDaysOfTheWeek;
222 break;
223 case TASK_TIME_TRIGGER_MONTHLYDATE:
224 pTrigger->Type.MonthlyDate.rgfDays =
225 This->triggerCond.Type.MonthlyDate.rgfDays;
226 pTrigger->Type.MonthlyDate.rgfMonths =
227 This->triggerCond.Type.MonthlyDate.rgfMonths;
228 break;
229 case TASK_TIME_TRIGGER_MONTHLYDOW:
230 pTrigger->Type.MonthlyDOW.wWhichWeek =
231 This->triggerCond.Type.MonthlyDOW.wWhichWeek;
232 pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek =
233 This->triggerCond.Type.MonthlyDOW.rgfDaysOfTheWeek;
234 pTrigger->Type.MonthlyDOW.rgfMonths =
235 This->triggerCond.Type.MonthlyDOW.rgfMonths;
236 break;
237 case TASK_TIME_TRIGGER_ONCE:
238 case TASK_EVENT_TRIGGER_ON_IDLE:
239 case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
240 case TASK_EVENT_TRIGGER_AT_LOGON:
241 default:
242 break;
243 }
244 pTrigger->Reserved2 = 0;
245 pTrigger->wRandomMinutesInterval = 0;
246 return S_OK;
247 }
248
249 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString(
250 ITaskTrigger* iface,
251 LPWSTR *ppwszTrigger)
252 {
253 FIXME("Not implemented\n");
254 return E_NOTIMPL;
255 }
256
257 static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl =
258 {
259 MSTASK_ITaskTrigger_QueryInterface,
260 MSTASK_ITaskTrigger_AddRef,
261 MSTASK_ITaskTrigger_Release,
262 MSTASK_ITaskTrigger_SetTrigger,
263 MSTASK_ITaskTrigger_GetTrigger,
264 MSTASK_ITaskTrigger_GetTriggerString
265 };
266
267 HRESULT TaskTriggerConstructor(LPVOID *ppObj)
268 {
269 TaskTriggerImpl *This;
270 SYSTEMTIME time;
271 TRACE("(%p)\n", ppObj);
272
273 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
274 if (!This)
275 return E_OUTOFMEMORY;
276
277 This->lpVtbl = &MSTASK_ITaskTriggerVtbl;
278 This->ref = 1;
279
280 /* Most fields of triggerCond default to zero. Initialize other
281 * fields to default values. */
282 memset(&This->triggerCond, 0, sizeof(TASK_TRIGGER));
283 GetLocalTime(&time);
284 This->triggerCond.cbTriggerSize = sizeof(This->triggerCond);
285 This->triggerCond.wBeginYear = time.wYear;
286 This->triggerCond.wBeginMonth = time.wMonth;
287 This->triggerCond.wBeginDay = time.wDay;
288 This->triggerCond.wStartHour = time.wHour;
289 This->triggerCond.wStartMinute = time.wMinute;
290 This->triggerCond.rgFlags = TASK_TRIGGER_FLAG_DISABLED;
291 This->triggerCond.TriggerType = TASK_TIME_TRIGGER_DAILY,
292 This->triggerCond.Type.Daily.DaysInterval = 1;
293
294 *ppObj = &This->lpVtbl;
295 InterlockedIncrement(&dll_ref);
296 return S_OK;
297 }