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 "mstask_private.h" 20 21 #include <winternl.h> 22 23 typedef struct 24 { 25 ITaskTrigger ITaskTrigger_iface; 26 LONG ref; 27 TASK_TRIGGER triggerCond; 28 } TaskTriggerImpl; 29 30 static inline TaskTriggerImpl *impl_from_ITaskTrigger(ITaskTrigger *iface) 31 { 32 return CONTAINING_RECORD(iface, TaskTriggerImpl, ITaskTrigger_iface); 33 } 34 35 static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface( 36 ITaskTrigger* iface, 37 REFIID riid, 38 void **ppvObject) 39 { 40 TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); 41 42 TRACE("IID: %s\n", debugstr_guid(riid)); 43 if (ppvObject == NULL) 44 return E_POINTER; 45 46 if (IsEqualGUID(riid, &IID_IUnknown) || 47 IsEqualGUID(riid, &IID_ITaskTrigger)) 48 { 49 *ppvObject = &This->ITaskTrigger_iface; 50 ITaskTrigger_AddRef(iface); 51 return S_OK; 52 } 53 54 WARN("Unknown interface: %s\n", debugstr_guid(riid)); 55 *ppvObject = NULL; 56 return E_NOINTERFACE; 57 } 58 59 static ULONG WINAPI MSTASK_ITaskTrigger_AddRef( 60 ITaskTrigger* iface) 61 { 62 TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); 63 ULONG ref; 64 TRACE("\n"); 65 ref = InterlockedIncrement(&This->ref); 66 return ref; 67 } 68 69 static ULONG WINAPI MSTASK_ITaskTrigger_Release( 70 ITaskTrigger* iface) 71 { 72 TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); 73 ULONG ref; 74 TRACE("\n"); 75 ref = InterlockedDecrement(&This->ref); 76 if (ref == 0) 77 { 78 HeapFree(GetProcessHeap(), 0, This); 79 InterlockedDecrement(&dll_ref); 80 } 81 return ref; 82 } 83 84 static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger( 85 ITaskTrigger* iface, 86 const PTASK_TRIGGER pTrigger) 87 { 88 TaskTriggerImpl * This = impl_from_ITaskTrigger(iface); 89 TIME_FIELDS field_time; 90 LARGE_INTEGER sys_time; 91 TASK_TRIGGER tmp_trigger_cond; 92 93 TRACE("(%p, %p)\n", iface, pTrigger); 94 95 /* Verify valid structure size */ 96 if (pTrigger->cbTriggerSize != sizeof(*pTrigger)) 97 return E_INVALIDARG; 98 tmp_trigger_cond.cbTriggerSize = pTrigger->cbTriggerSize; 99 100 /* Reserved field must be zero */ 101 tmp_trigger_cond.Reserved1 = 0; 102 103 /* Verify and set valid start date and time */ 104 memset(&field_time, 0, sizeof(field_time)); 105 field_time.Year = pTrigger->wBeginYear; 106 field_time.Month = pTrigger->wBeginMonth; 107 field_time.Day = pTrigger->wBeginDay; 108 field_time.Hour = pTrigger->wStartHour; 109 field_time.Minute = pTrigger->wStartMinute; 110 if (!RtlTimeFieldsToTime(&field_time, &sys_time)) 111 return E_INVALIDARG; 112 tmp_trigger_cond.wBeginYear = pTrigger->wBeginYear; 113 tmp_trigger_cond.wBeginMonth = pTrigger->wBeginMonth; 114 tmp_trigger_cond.wBeginDay = pTrigger->wBeginDay; 115 tmp_trigger_cond.wStartHour = pTrigger->wStartHour; 116 tmp_trigger_cond.wStartMinute = pTrigger->wStartMinute; 117 118 /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */ 119 if (pTrigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) 120 { 121 memset(&field_time, 0, sizeof(field_time)); 122 field_time.Year = pTrigger->wEndYear; 123 field_time.Month = pTrigger->wEndMonth; 124 field_time.Day = pTrigger->wEndDay; 125 if (!RtlTimeFieldsToTime(&field_time, &sys_time)) 126 return E_INVALIDARG; 127 } 128 129 /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */ 130 tmp_trigger_cond.wEndYear = pTrigger->wEndYear; 131 tmp_trigger_cond.wEndMonth = pTrigger->wEndMonth; 132 tmp_trigger_cond.wEndDay = pTrigger->wEndDay; 133 134 /* Verify duration and interval pair */ 135 if (pTrigger->MinutesDuration <= pTrigger->MinutesInterval && 136 pTrigger->MinutesInterval > 0) 137 return E_INVALIDARG; 138 tmp_trigger_cond.MinutesDuration = pTrigger->MinutesDuration; 139 tmp_trigger_cond.MinutesInterval = pTrigger->MinutesInterval; 140 141 /* Copy over flags */ 142 tmp_trigger_cond.rgFlags = pTrigger->rgFlags; 143 144 /* Set TriggerType dependent fields of Type union */ 145 tmp_trigger_cond.TriggerType = pTrigger->TriggerType; 146 switch (pTrigger->TriggerType) 147 { 148 case TASK_TIME_TRIGGER_DAILY: 149 tmp_trigger_cond.Type.Daily.DaysInterval = 150 pTrigger->Type.Daily.DaysInterval; 151 break; 152 case TASK_TIME_TRIGGER_WEEKLY: 153 tmp_trigger_cond.Type.Weekly.WeeksInterval = 154 pTrigger->Type.Weekly.WeeksInterval; 155 tmp_trigger_cond.Type.Weekly.rgfDaysOfTheWeek = 156 pTrigger->Type.Weekly.rgfDaysOfTheWeek; 157 break; 158 case TASK_TIME_TRIGGER_MONTHLYDATE: 159 tmp_trigger_cond.Type.MonthlyDate.rgfDays = 160 pTrigger->Type.MonthlyDate.rgfDays; 161 tmp_trigger_cond.Type.MonthlyDate.rgfMonths = 162 pTrigger->Type.MonthlyDate.rgfMonths; 163 break; 164 case TASK_TIME_TRIGGER_MONTHLYDOW: 165 tmp_trigger_cond.Type.MonthlyDOW.wWhichWeek = 166 pTrigger->Type.MonthlyDOW.wWhichWeek; 167 tmp_trigger_cond.Type.MonthlyDOW.rgfDaysOfTheWeek = 168 pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek; 169 tmp_trigger_cond.Type.MonthlyDOW.rgfMonths = 170 pTrigger->Type.MonthlyDOW.rgfMonths; 171 break; 172 case TASK_TIME_TRIGGER_ONCE: 173 case TASK_EVENT_TRIGGER_ON_IDLE: 174 case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: 175 case TASK_EVENT_TRIGGER_AT_LOGON: 176 default: 177 tmp_trigger_cond.Type = This->triggerCond.Type; 178 break; 179 } 180 181 /* Reserved field must be zero */ 182 tmp_trigger_cond.Reserved2 = 0; 183 184 /* wRandomMinutesInterval not currently used and is initialized to zero */ 185 tmp_trigger_cond.wRandomMinutesInterval = 0; 186 187 /* Update object copy of triggerCond */ 188 This->triggerCond = tmp_trigger_cond; 189 190 return S_OK; 191 } 192 193 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger( 194 ITaskTrigger* iface, 195 PTASK_TRIGGER pTrigger) 196 { 197 TaskTriggerImpl * This = impl_from_ITaskTrigger(iface); 198 199 TRACE("(%p, %p)\n", iface, pTrigger); 200 201 /* Native implementation doesn't verify equivalent cbTriggerSize fields */ 202 203 /* Copy relevant fields of the structure */ 204 pTrigger->cbTriggerSize = This->triggerCond.cbTriggerSize; 205 pTrigger->Reserved1 = 0; 206 pTrigger->wBeginYear = This->triggerCond.wBeginYear; 207 pTrigger->wBeginMonth = This->triggerCond.wBeginMonth; 208 pTrigger->wBeginDay = This->triggerCond.wBeginDay; 209 pTrigger->wEndYear = This->triggerCond.wEndYear; 210 pTrigger->wEndMonth = This->triggerCond.wEndMonth; 211 pTrigger->wEndDay = This->triggerCond.wEndDay; 212 pTrigger->wStartHour = This->triggerCond.wStartHour; 213 pTrigger->wStartMinute = This->triggerCond.wStartMinute; 214 pTrigger->MinutesDuration = This->triggerCond.MinutesDuration; 215 pTrigger->MinutesInterval = This->triggerCond.MinutesInterval; 216 pTrigger->rgFlags = This->triggerCond.rgFlags; 217 pTrigger->TriggerType = This->triggerCond.TriggerType; 218 switch (This->triggerCond.TriggerType) 219 { 220 case TASK_TIME_TRIGGER_DAILY: 221 pTrigger->Type.Daily.DaysInterval = 222 This->triggerCond.Type.Daily.DaysInterval; 223 break; 224 case TASK_TIME_TRIGGER_WEEKLY: 225 pTrigger->Type.Weekly.WeeksInterval = 226 This->triggerCond.Type.Weekly.WeeksInterval; 227 pTrigger->Type.Weekly.rgfDaysOfTheWeek = 228 This->triggerCond.Type.Weekly.rgfDaysOfTheWeek; 229 break; 230 case TASK_TIME_TRIGGER_MONTHLYDATE: 231 pTrigger->Type.MonthlyDate.rgfDays = 232 This->triggerCond.Type.MonthlyDate.rgfDays; 233 pTrigger->Type.MonthlyDate.rgfMonths = 234 This->triggerCond.Type.MonthlyDate.rgfMonths; 235 break; 236 case TASK_TIME_TRIGGER_MONTHLYDOW: 237 pTrigger->Type.MonthlyDOW.wWhichWeek = 238 This->triggerCond.Type.MonthlyDOW.wWhichWeek; 239 pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek = 240 This->triggerCond.Type.MonthlyDOW.rgfDaysOfTheWeek; 241 pTrigger->Type.MonthlyDOW.rgfMonths = 242 This->triggerCond.Type.MonthlyDOW.rgfMonths; 243 break; 244 case TASK_TIME_TRIGGER_ONCE: 245 case TASK_EVENT_TRIGGER_ON_IDLE: 246 case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: 247 case TASK_EVENT_TRIGGER_AT_LOGON: 248 default: 249 break; 250 } 251 pTrigger->Reserved2 = 0; 252 pTrigger->wRandomMinutesInterval = 0; 253 return S_OK; 254 } 255 256 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString( 257 ITaskTrigger* iface, 258 LPWSTR *ppwszTrigger) 259 { 260 FIXME("Not implemented\n"); 261 return E_NOTIMPL; 262 } 263 264 static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl = 265 { 266 MSTASK_ITaskTrigger_QueryInterface, 267 MSTASK_ITaskTrigger_AddRef, 268 MSTASK_ITaskTrigger_Release, 269 MSTASK_ITaskTrigger_SetTrigger, 270 MSTASK_ITaskTrigger_GetTrigger, 271 MSTASK_ITaskTrigger_GetTriggerString 272 }; 273 274 HRESULT TaskTriggerConstructor(LPVOID *ppObj) 275 { 276 TaskTriggerImpl *This; 277 SYSTEMTIME time; 278 TRACE("(%p)\n", ppObj); 279 280 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 281 if (!This) 282 return E_OUTOFMEMORY; 283 284 This->ITaskTrigger_iface.lpVtbl = &MSTASK_ITaskTriggerVtbl; 285 This->ref = 1; 286 287 /* Most fields of triggerCond default to zero. Initialize other 288 * fields to default values. */ 289 memset(&This->triggerCond, 0, sizeof(TASK_TRIGGER)); 290 GetLocalTime(&time); 291 This->triggerCond.cbTriggerSize = sizeof(This->triggerCond); 292 This->triggerCond.wBeginYear = time.wYear; 293 This->triggerCond.wBeginMonth = time.wMonth; 294 This->triggerCond.wBeginDay = time.wDay; 295 This->triggerCond.wStartHour = time.wHour; 296 This->triggerCond.wStartMinute = time.wMinute; 297 This->triggerCond.rgFlags = TASK_TRIGGER_FLAG_DISABLED; 298 This->triggerCond.TriggerType = TASK_TIME_TRIGGER_DAILY, 299 This->triggerCond.Type.Daily.DaysInterval = 1; 300 301 *ppObj = &This->ITaskTrigger_iface; 302 InterlockedIncrement(&dll_ref); 303 return S_OK; 304 } 305