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 "corerror.h" 20 #include "mstask_private.h" 21 #include "wine/debug.h" 22 23 WINE_DEFAULT_DEBUG_CHANNEL(mstask); 24 25 typedef struct 26 { 27 ITaskScheduler ITaskScheduler_iface; 28 LONG ref; 29 } TaskSchedulerImpl; 30 31 typedef struct 32 { 33 IEnumWorkItems IEnumWorkItems_iface; 34 LONG ref; 35 } EnumWorkItemsImpl; 36 37 static inline TaskSchedulerImpl *impl_from_ITaskScheduler(ITaskScheduler *iface) 38 { 39 return CONTAINING_RECORD(iface, TaskSchedulerImpl, ITaskScheduler_iface); 40 } 41 42 static inline EnumWorkItemsImpl *impl_from_IEnumWorkItems(IEnumWorkItems *iface) 43 { 44 return CONTAINING_RECORD(iface, EnumWorkItemsImpl, IEnumWorkItems_iface); 45 } 46 47 static void TaskSchedulerDestructor(TaskSchedulerImpl *This) 48 { 49 TRACE("%p\n", This); 50 HeapFree(GetProcessHeap(), 0, This); 51 InterlockedDecrement(&dll_ref); 52 } 53 54 static HRESULT WINAPI EnumWorkItems_QueryInterface(IEnumWorkItems *iface, REFIID riid, void **obj) 55 { 56 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 57 58 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 59 60 if (IsEqualGUID(riid, &IID_IEnumWorkItems) || IsEqualGUID(riid, &IID_IUnknown)) 61 { 62 *obj = &This->IEnumWorkItems_iface; 63 IEnumWorkItems_AddRef(iface); 64 return S_OK; 65 } 66 67 *obj = NULL; 68 return E_NOINTERFACE; 69 } 70 71 static ULONG WINAPI EnumWorkItems_AddRef(IEnumWorkItems *iface) 72 { 73 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 74 ULONG ref = InterlockedIncrement(&This->ref); 75 TRACE("(%p)->(%u)\n", This, ref); 76 return ref; 77 } 78 79 static ULONG WINAPI EnumWorkItems_Release(IEnumWorkItems *iface) 80 { 81 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 82 ULONG ref = InterlockedDecrement(&This->ref); 83 84 TRACE("(%p)->(%u)\n", This, ref); 85 86 if (ref == 0) 87 { 88 HeapFree(GetProcessHeap(), 0, This); 89 InterlockedDecrement(&dll_ref); 90 } 91 92 return ref; 93 } 94 95 static HRESULT WINAPI EnumWorkItems_Next(IEnumWorkItems *iface, ULONG count, LPWSTR **names, ULONG *fetched) 96 { 97 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 98 FIXME("(%p)->(%u %p %p): stub\n", This, count, names, fetched); 99 return E_NOTIMPL; 100 } 101 102 static HRESULT WINAPI EnumWorkItems_Skip(IEnumWorkItems *iface, ULONG count) 103 { 104 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 105 FIXME("(%p)->(%u): stub\n", This, count); 106 return E_NOTIMPL; 107 } 108 109 static HRESULT WINAPI EnumWorkItems_Reset(IEnumWorkItems *iface) 110 { 111 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 112 FIXME("(%p): stub\n", This); 113 return E_NOTIMPL; 114 } 115 116 static HRESULT WINAPI EnumWorkItems_Clone(IEnumWorkItems *iface, IEnumWorkItems **cloned) 117 { 118 EnumWorkItemsImpl *This = impl_from_IEnumWorkItems(iface); 119 FIXME("(%p)->(%p): stub\n", This, cloned); 120 return E_NOTIMPL; 121 } 122 123 static const IEnumWorkItemsVtbl EnumWorkItemsVtbl = { 124 EnumWorkItems_QueryInterface, 125 EnumWorkItems_AddRef, 126 EnumWorkItems_Release, 127 EnumWorkItems_Next, 128 EnumWorkItems_Skip, 129 EnumWorkItems_Reset, 130 EnumWorkItems_Clone 131 }; 132 133 static HRESULT create_task_enum(IEnumWorkItems **ret) 134 { 135 EnumWorkItemsImpl *tasks; 136 137 *ret = NULL; 138 139 tasks = HeapAlloc(GetProcessHeap(), 0, sizeof(*tasks)); 140 if (!tasks) 141 return E_OUTOFMEMORY; 142 143 tasks->IEnumWorkItems_iface.lpVtbl = &EnumWorkItemsVtbl; 144 tasks->ref = 1; 145 146 *ret = &tasks->IEnumWorkItems_iface; 147 InterlockedIncrement(&dll_ref); 148 return S_OK; 149 } 150 151 static HRESULT WINAPI MSTASK_ITaskScheduler_QueryInterface( 152 ITaskScheduler* iface, 153 REFIID riid, 154 void **ppvObject) 155 { 156 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface); 157 158 TRACE("IID: %s\n", debugstr_guid(riid)); 159 160 if (IsEqualGUID(riid, &IID_IUnknown) || 161 IsEqualGUID(riid, &IID_ITaskScheduler)) 162 { 163 *ppvObject = &This->ITaskScheduler_iface; 164 ITaskScheduler_AddRef(iface); 165 return S_OK; 166 } 167 168 *ppvObject = NULL; 169 return E_NOINTERFACE; 170 } 171 172 static ULONG WINAPI MSTASK_ITaskScheduler_AddRef( 173 ITaskScheduler* iface) 174 { 175 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface); 176 TRACE("\n"); 177 return InterlockedIncrement(&This->ref); 178 } 179 180 static ULONG WINAPI MSTASK_ITaskScheduler_Release( 181 ITaskScheduler* iface) 182 { 183 TaskSchedulerImpl * This = impl_from_ITaskScheduler(iface); 184 ULONG ref; 185 TRACE("\n"); 186 ref = InterlockedDecrement(&This->ref); 187 if (ref == 0) 188 TaskSchedulerDestructor(This); 189 return ref; 190 } 191 192 static HRESULT WINAPI MSTASK_ITaskScheduler_SetTargetComputer( 193 ITaskScheduler* iface, 194 LPCWSTR pwszComputer) 195 { 196 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface); 197 WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 3]; /* extra space for two '\' and a zero */ 198 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; /* extra space for a zero */ 199 200 TRACE("(%p)->(%s)\n", This, debugstr_w(pwszComputer)); 201 202 /* NULL is an alias for the local computer */ 203 if (!pwszComputer) 204 return S_OK; 205 206 buffer[0] = '\\'; 207 buffer[1] = '\\'; 208 if (GetComputerNameW(buffer + 2, &len)) 209 { 210 if (!lstrcmpiW(buffer, pwszComputer) || /* full unc name */ 211 !lstrcmpiW(buffer + 2, pwszComputer)) /* name without backslash */ 212 return S_OK; 213 } 214 215 FIXME("remote computer %s not supported\n", debugstr_w(pwszComputer)); 216 return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH); 217 } 218 219 static HRESULT WINAPI MSTASK_ITaskScheduler_GetTargetComputer( 220 ITaskScheduler* iface, 221 LPWSTR *ppwszComputer) 222 { 223 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface); 224 LPWSTR buffer; 225 DWORD len = MAX_COMPUTERNAME_LENGTH + 1; /* extra space for the zero */ 226 227 TRACE("(%p)->(%p)\n", This, ppwszComputer); 228 229 if (!ppwszComputer) 230 return E_INVALIDARG; 231 232 /* extra space for two '\' and a zero */ 233 buffer = CoTaskMemAlloc((MAX_COMPUTERNAME_LENGTH + 3) * sizeof(WCHAR)); 234 if (buffer) 235 { 236 buffer[0] = '\\'; 237 buffer[1] = '\\'; 238 if (GetComputerNameW(buffer + 2, &len)) 239 { 240 *ppwszComputer = buffer; 241 return S_OK; 242 } 243 CoTaskMemFree(buffer); 244 } 245 *ppwszComputer = NULL; 246 return HRESULT_FROM_WIN32(GetLastError()); 247 } 248 249 static HRESULT WINAPI MSTASK_ITaskScheduler_Enum( 250 ITaskScheduler* iface, 251 IEnumWorkItems **tasks) 252 { 253 TaskSchedulerImpl *This = impl_from_ITaskScheduler(iface); 254 255 TRACE("(%p)->(%p)\n", This, tasks); 256 257 if (!tasks) 258 return E_INVALIDARG; 259 260 return create_task_enum(tasks); 261 } 262 263 static HRESULT WINAPI MSTASK_ITaskScheduler_Activate( 264 ITaskScheduler* iface, 265 LPCWSTR pwszName, 266 REFIID riid, 267 IUnknown **ppunk) 268 { 269 TRACE("%p, %s, %s, %p: stub\n", iface, debugstr_w(pwszName), 270 debugstr_guid(riid), ppunk); 271 FIXME("Partial stub always returning COR_E_FILENOTFOUND\n"); 272 return COR_E_FILENOTFOUND; 273 } 274 275 static HRESULT WINAPI MSTASK_ITaskScheduler_Delete( 276 ITaskScheduler* iface, 277 LPCWSTR pwszName) 278 { 279 FIXME("%p, %s: stub\n", iface, debugstr_w(pwszName)); 280 return E_NOTIMPL; 281 } 282 283 static HRESULT WINAPI MSTASK_ITaskScheduler_NewWorkItem( 284 ITaskScheduler* iface, 285 LPCWSTR pwszTaskName, 286 REFCLSID rclsid, 287 REFIID riid, 288 IUnknown **ppunk) 289 { 290 HRESULT hr; 291 TRACE("(%p, %s, %s, %s, %p)\n", iface, debugstr_w(pwszTaskName), 292 debugstr_guid(rclsid) ,debugstr_guid(riid), ppunk); 293 294 if (!IsEqualGUID(rclsid, &CLSID_CTask)) 295 return CLASS_E_CLASSNOTAVAILABLE; 296 297 if (!IsEqualGUID(riid, &IID_ITask)) 298 return E_NOINTERFACE; 299 300 hr = TaskConstructor(pwszTaskName, (LPVOID *)ppunk); 301 return hr; 302 } 303 304 static HRESULT WINAPI MSTASK_ITaskScheduler_AddWorkItem( 305 ITaskScheduler* iface, 306 LPCWSTR pwszTaskName, 307 IScheduledWorkItem *pWorkItem) 308 { 309 FIXME("%p, %s, %p: stub\n", iface, debugstr_w(pwszTaskName), pWorkItem); 310 return E_NOTIMPL; 311 } 312 313 static HRESULT WINAPI MSTASK_ITaskScheduler_IsOfType( 314 ITaskScheduler* iface, 315 LPCWSTR pwszName, 316 REFIID riid) 317 { 318 FIXME("%p, %s, %s: stub\n", iface, debugstr_w(pwszName), 319 debugstr_guid(riid)); 320 return E_NOTIMPL; 321 } 322 323 static const ITaskSchedulerVtbl MSTASK_ITaskSchedulerVtbl = 324 { 325 MSTASK_ITaskScheduler_QueryInterface, 326 MSTASK_ITaskScheduler_AddRef, 327 MSTASK_ITaskScheduler_Release, 328 MSTASK_ITaskScheduler_SetTargetComputer, 329 MSTASK_ITaskScheduler_GetTargetComputer, 330 MSTASK_ITaskScheduler_Enum, 331 MSTASK_ITaskScheduler_Activate, 332 MSTASK_ITaskScheduler_Delete, 333 MSTASK_ITaskScheduler_NewWorkItem, 334 MSTASK_ITaskScheduler_AddWorkItem, 335 MSTASK_ITaskScheduler_IsOfType 336 }; 337 338 HRESULT TaskSchedulerConstructor(LPVOID *ppObj) 339 { 340 TaskSchedulerImpl *This; 341 TRACE("(%p)\n", ppObj); 342 343 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); 344 if (!This) 345 return E_OUTOFMEMORY; 346 347 This->ITaskScheduler_iface.lpVtbl = &MSTASK_ITaskSchedulerVtbl; 348 This->ref = 1; 349 350 *ppObj = &This->ITaskScheduler_iface; 351 InterlockedIncrement(&dll_ref); 352 return S_OK; 353 } 354