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