riched20: Merge the richole object with the text services object.
[wine.git] / dlls / qmgr / job.c
blob2ba65cbc290a6897ad7ad41954c93db2e936163c
1 /*
2 * Background Copy Job Interface for BITS
4 * Copyright 2007 Google (Roy Shea)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "qmgr.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
30 BOOL transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE from, BG_JOB_STATE to)
32 BOOL ret = FALSE;
34 EnterCriticalSection(&globalMgr.cs);
35 if (job->state == from)
37 job->state = to;
38 ret = TRUE;
40 LeaveCriticalSection(&globalMgr.cs);
41 return ret;
44 struct copy_error
46 IBackgroundCopyError IBackgroundCopyError_iface;
47 LONG refs;
48 BG_ERROR_CONTEXT context;
49 HRESULT code;
50 IBackgroundCopyFile2 *file;
53 static inline struct copy_error *impl_from_IBackgroundCopyError(IBackgroundCopyError *iface)
55 return CONTAINING_RECORD(iface, struct copy_error, IBackgroundCopyError_iface);
58 static HRESULT WINAPI copy_error_QueryInterface(
59 IBackgroundCopyError *iface,
60 REFIID riid,
61 void **obj)
63 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
65 TRACE("(%p)->(%s %p)\n", error, debugstr_guid(riid), obj);
67 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyError))
69 *obj = &error->IBackgroundCopyError_iface;
71 else
73 *obj = NULL;
74 WARN("interface %s not supported\n", debugstr_guid(riid));
75 return E_NOINTERFACE;
78 IBackgroundCopyError_AddRef(iface);
79 return S_OK;
82 static ULONG WINAPI copy_error_AddRef(
83 IBackgroundCopyError *iface)
85 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
86 LONG refs = InterlockedIncrement(&error->refs);
87 TRACE("(%p)->(%d)\n", error, refs);
88 return refs;
91 static ULONG WINAPI copy_error_Release(
92 IBackgroundCopyError *iface)
94 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
95 LONG refs = InterlockedDecrement(&error->refs);
97 TRACE("(%p)->(%d)\n", error, refs);
99 if (!refs)
101 if (error->file) IBackgroundCopyFile2_Release(error->file);
102 HeapFree(GetProcessHeap(), 0, error);
104 return refs;
107 static HRESULT WINAPI copy_error_GetError(
108 IBackgroundCopyError *iface,
109 BG_ERROR_CONTEXT *pContext,
110 HRESULT *pCode)
112 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
114 TRACE("(%p)->(%p %p)\n", error, pContext, pCode);
116 *pContext = error->context;
117 *pCode = error->code;
119 TRACE("returning context %u error code 0x%08x\n", error->context, error->code);
120 return S_OK;
123 static HRESULT WINAPI copy_error_GetFile(
124 IBackgroundCopyError *iface,
125 IBackgroundCopyFile **pVal)
127 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
129 TRACE("(%p)->(%p)\n", error, pVal);
131 if (error->file)
133 IBackgroundCopyFile2_AddRef(error->file);
134 *pVal = (IBackgroundCopyFile *)error->file;
135 return S_OK;
137 *pVal = NULL;
138 return BG_E_FILE_NOT_AVAILABLE;
141 static HRESULT WINAPI copy_error_GetErrorDescription(
142 IBackgroundCopyError *iface,
143 DWORD LanguageId,
144 LPWSTR *pErrorDescription)
146 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
147 FIXME("(%p)->(%p)\n", error, pErrorDescription);
148 return E_NOTIMPL;
151 static HRESULT WINAPI copy_error_GetErrorContextDescription(
152 IBackgroundCopyError *iface,
153 DWORD LanguageId,
154 LPWSTR *pContextDescription)
156 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
157 FIXME("(%p)->(%p)\n", error, pContextDescription);
158 return E_NOTIMPL;
161 static HRESULT WINAPI copy_error_GetProtocol(
162 IBackgroundCopyError *iface,
163 LPWSTR *pProtocol)
165 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
166 FIXME("(%p)->(%p)\n", error, pProtocol);
167 return E_NOTIMPL;
170 static const IBackgroundCopyErrorVtbl copy_error_vtbl =
172 copy_error_QueryInterface,
173 copy_error_AddRef,
174 copy_error_Release,
175 copy_error_GetError,
176 copy_error_GetFile,
177 copy_error_GetErrorDescription,
178 copy_error_GetErrorContextDescription,
179 copy_error_GetProtocol
182 static HRESULT create_copy_error(
183 BG_ERROR_CONTEXT context,
184 HRESULT code,
185 IBackgroundCopyFile2 *file,
186 IBackgroundCopyError **obj)
188 struct copy_error *error;
190 TRACE("context %u code %08x file %p\n", context, code, file);
192 if (!(error = HeapAlloc(GetProcessHeap(), 0, sizeof(*error) ))) return E_OUTOFMEMORY;
193 error->IBackgroundCopyError_iface.lpVtbl = &copy_error_vtbl;
194 error->refs = 1;
195 error->context = context;
196 error->code = code;
197 error->file = file;
198 if (error->file) IBackgroundCopyFile2_AddRef(error->file);
200 *obj = &error->IBackgroundCopyError_iface;
201 TRACE("returning iface %p\n", *obj);
202 return S_OK;
205 static inline BOOL is_job_done(const BackgroundCopyJobImpl *job)
207 return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED;
210 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob4(IBackgroundCopyJob4 *iface)
212 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob4_iface);
215 static HRESULT WINAPI BackgroundCopyJob_QueryInterface(IBackgroundCopyJob4 *iface, REFIID riid, void **obj)
217 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
219 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
221 if (IsEqualGUID(riid, &IID_IUnknown) ||
222 IsEqualGUID(riid, &IID_IBackgroundCopyJob) ||
223 IsEqualGUID(riid, &IID_IBackgroundCopyJob2) ||
224 IsEqualGUID(riid, &IID_IBackgroundCopyJob3) ||
225 IsEqualGUID(riid, &IID_IBackgroundCopyJob4))
227 *obj = &job->IBackgroundCopyJob4_iface;
229 else if (IsEqualGUID(riid, &IID_IBackgroundCopyJobHttpOptions))
231 *obj = &job->IBackgroundCopyJobHttpOptions_iface;
233 else
235 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
236 *obj = NULL;
237 return E_NOINTERFACE;
240 IBackgroundCopyJob4_AddRef(iface);
241 return S_OK;
244 static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob4 *iface)
246 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
247 ULONG refcount = InterlockedIncrement(&job->ref);
248 TRACE("%p, refcount %d.\n", iface, refcount);
249 return refcount;
252 static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob4 *iface)
254 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
255 ULONG i, j, ref = InterlockedDecrement(&job->ref);
257 TRACE("%p, refcount %d.\n", iface, ref);
259 if (!ref)
261 job->cs.DebugInfo->Spare[0] = 0;
262 DeleteCriticalSection(&job->cs);
263 if (job->callback)
264 IBackgroundCopyCallback2_Release(job->callback);
265 HeapFree(GetProcessHeap(), 0, job->displayName);
266 HeapFree(GetProcessHeap(), 0, job->description);
267 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
268 for (i = 0; i < BG_AUTH_TARGET_PROXY; i++)
270 for (j = 0; j < BG_AUTH_SCHEME_PASSPORT; j++)
272 BG_AUTH_CREDENTIALS *cred = &job->http_options.creds[i][j];
273 HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.UserName);
274 HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.Password);
277 CloseHandle(job->wait);
278 CloseHandle(job->cancel);
279 CloseHandle(job->done);
280 HeapFree(GetProcessHeap(), 0, job);
283 return ref;
286 /*** IBackgroundCopyJob methods ***/
288 static HRESULT WINAPI BackgroundCopyJob_AddFileSet(IBackgroundCopyJob4 *iface, ULONG cFileCount, BG_FILE_INFO *pFileSet)
290 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
291 HRESULT hr = S_OK;
292 ULONG i;
294 TRACE("%p, %u, %p.\n", iface, cFileCount, pFileSet);
296 EnterCriticalSection(&job->cs);
298 for (i = 0; i < cFileCount; ++i)
300 BackgroundCopyFileImpl *file;
302 /* We should return E_INVALIDARG in these cases. */
303 FIXME("Check for valid filenames and supported protocols\n");
305 hr = BackgroundCopyFileConstructor(job, pFileSet[i].RemoteName, pFileSet[i].LocalName, &file);
306 if (hr != S_OK) break;
308 /* Add a reference to the file to file list */
309 list_add_head(&job->files, &file->entryFromJob);
310 job->jobProgress.BytesTotal = BG_SIZE_UNKNOWN;
311 ++job->jobProgress.FilesTotal;
314 LeaveCriticalSection(&job->cs);
316 return hr;
319 static HRESULT WINAPI BackgroundCopyJob_AddFile(IBackgroundCopyJob4 *iface, LPCWSTR RemoteUrl, LPCWSTR LocalName)
321 BG_FILE_INFO file;
323 TRACE("%p, %s, %s.\n", iface, debugstr_w(RemoteUrl), debugstr_w(LocalName));
325 file.RemoteName = (LPWSTR)RemoteUrl;
326 file.LocalName = (LPWSTR)LocalName;
327 return IBackgroundCopyJob4_AddFileSet(iface, 1, &file);
330 static HRESULT WINAPI BackgroundCopyJob_EnumFiles(IBackgroundCopyJob4 *iface, IEnumBackgroundCopyFiles **enum_files)
332 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
333 TRACE("%p, %p.\n", iface, enum_files);
334 return EnumBackgroundCopyFilesConstructor(job, enum_files);
337 static HRESULT WINAPI BackgroundCopyJob_Suspend(IBackgroundCopyJob4 *iface)
339 FIXME("(%p): stub\n", iface);
340 return E_NOTIMPL;
343 static HRESULT WINAPI BackgroundCopyJob_Resume(IBackgroundCopyJob4 *iface)
345 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
346 HRESULT hr = S_OK;
348 TRACE("%p.\n", iface);
350 EnterCriticalSection(&globalMgr.cs);
351 if (is_job_done(job))
353 hr = BG_E_INVALID_STATE;
355 else if (job->jobProgress.FilesTransferred == job->jobProgress.FilesTotal)
357 hr = BG_E_EMPTY;
359 else if (job->state != BG_JOB_STATE_CONNECTING
360 && job->state != BG_JOB_STATE_TRANSFERRING)
362 job->state = BG_JOB_STATE_QUEUED;
363 job->error.context = 0;
364 job->error.code = S_OK;
365 if (job->error.file)
367 IBackgroundCopyFile2_Release(job->error.file);
368 job->error.file = NULL;
370 SetEvent(globalMgr.jobEvent);
372 LeaveCriticalSection(&globalMgr.cs);
374 return hr;
377 static HRESULT WINAPI BackgroundCopyJob_Cancel(IBackgroundCopyJob4 *iface)
379 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
380 HRESULT hr = S_OK;
382 TRACE("%p.\n", iface);
384 EnterCriticalSection(&job->cs);
386 if (is_job_done(job))
388 hr = BG_E_INVALID_STATE;
390 else
392 BackgroundCopyFileImpl *file;
394 if (job->state == BG_JOB_STATE_CONNECTING || job->state == BG_JOB_STATE_TRANSFERRING)
396 job->state = BG_JOB_STATE_CANCELLED;
397 SetEvent(job->cancel);
399 LeaveCriticalSection(&job->cs);
400 WaitForSingleObject(job->done, INFINITE);
401 EnterCriticalSection(&job->cs);
404 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
406 if (file->tempFileName[0] && !DeleteFileW(file->tempFileName))
408 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError());
409 hr = BG_S_UNABLE_TO_DELETE_FILES;
411 if (file->info.LocalName && !DeleteFileW(file->info.LocalName))
413 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError());
414 hr = BG_S_UNABLE_TO_DELETE_FILES;
417 job->state = BG_JOB_STATE_CANCELLED;
420 LeaveCriticalSection(&job->cs);
421 return hr;
424 static HRESULT WINAPI BackgroundCopyJob_Complete(IBackgroundCopyJob4 *iface)
426 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
427 HRESULT hr = S_OK;
429 TRACE("%p.\n", iface);
431 EnterCriticalSection(&job->cs);
433 if (is_job_done(job))
435 hr = BG_E_INVALID_STATE;
437 else
439 BackgroundCopyFileImpl *file;
440 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
442 if (file->fileProgress.Completed)
444 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
445 (MOVEFILE_COPY_ALLOWED
446 | MOVEFILE_REPLACE_EXISTING
447 | MOVEFILE_WRITE_THROUGH)))
449 ERR("Couldn't rename file %s -> %s\n",
450 debugstr_w(file->tempFileName),
451 debugstr_w(file->info.LocalName));
452 hr = BG_S_PARTIAL_COMPLETE;
455 else
456 hr = BG_S_PARTIAL_COMPLETE;
460 job->state = BG_JOB_STATE_ACKNOWLEDGED;
461 LeaveCriticalSection(&job->cs);
463 return hr;
466 static HRESULT WINAPI BackgroundCopyJob_GetId(IBackgroundCopyJob4 *iface, GUID *id)
468 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
470 TRACE("%p, %p.\n", iface, id);
472 *id = job->jobId;
474 return S_OK;
477 static HRESULT WINAPI BackgroundCopyJob_GetType(IBackgroundCopyJob4 *iface, BG_JOB_TYPE *job_type)
479 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
481 TRACE("%p, %p.\n", iface, job_type);
483 if (!job_type)
484 return E_INVALIDARG;
486 *job_type = job->type;
487 return S_OK;
490 static HRESULT WINAPI BackgroundCopyJob_GetProgress(IBackgroundCopyJob4 *iface, BG_JOB_PROGRESS *progress)
492 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
494 TRACE("%p, %p.\n", iface, progress);
496 if (!progress)
497 return E_INVALIDARG;
499 EnterCriticalSection(&job->cs);
500 *progress = job->jobProgress;
501 LeaveCriticalSection(&job->cs);
503 return S_OK;
506 static HRESULT WINAPI BackgroundCopyJob_GetTimes(IBackgroundCopyJob4 *iface, BG_JOB_TIMES *pVal)
508 FIXME("%p, %p: stub\n", iface, pVal);
509 return E_NOTIMPL;
512 static HRESULT WINAPI BackgroundCopyJob_GetState(IBackgroundCopyJob4 *iface, BG_JOB_STATE *state)
514 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
516 TRACE("%p, %p.\n", iface, state);
518 if (!state)
519 return E_INVALIDARG;
521 /* Don't think we need a critical section for this */
522 *state = job->state;
523 return S_OK;
526 static HRESULT WINAPI BackgroundCopyJob_GetError(IBackgroundCopyJob4 *iface, IBackgroundCopyError **ppError)
528 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
530 TRACE("%p, %p.\n", iface, ppError);
532 if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
534 return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
537 static HRESULT WINAPI BackgroundCopyJob_GetOwner(IBackgroundCopyJob4 *iface, LPWSTR *owner)
539 FIXME("%p, %p: stub\n", iface, owner);
540 return E_NOTIMPL;
543 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName(IBackgroundCopyJob4 *iface, LPCWSTR name)
545 FIXME("%p, %s: stub\n", iface, debugstr_w(name));
546 return E_NOTIMPL;
549 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName(IBackgroundCopyJob4 *iface, LPWSTR *name)
551 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
553 TRACE("%p, %p.\n", iface, name);
555 return return_strval(job->displayName, name);
558 static HRESULT WINAPI BackgroundCopyJob_SetDescription(IBackgroundCopyJob4 *iface, LPCWSTR desc)
560 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
561 static const int max_description_len = 1024;
562 HRESULT hr = S_OK;
563 int len;
565 TRACE("%p, %s.\n", iface, debugstr_w(desc));
567 if (!desc)
568 return E_INVALIDARG;
570 len = lstrlenW(desc);
571 if (len > max_description_len) return BG_E_STRING_TOO_LONG;
573 EnterCriticalSection(&job->cs);
575 if (is_job_done(job))
577 hr = BG_E_INVALID_STATE;
579 else
581 HeapFree(GetProcessHeap(), 0, job->description);
582 if ((job->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR))))
583 lstrcpyW(job->description, desc);
584 else
585 hr = E_OUTOFMEMORY;
588 LeaveCriticalSection(&job->cs);
590 return hr;
593 static HRESULT WINAPI BackgroundCopyJob_GetDescription(IBackgroundCopyJob4 *iface, LPWSTR *desc)
595 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
597 TRACE("%p, %p.\n", iface, desc);
599 return return_strval(job->description, desc);
602 static HRESULT WINAPI BackgroundCopyJob_SetPriority(IBackgroundCopyJob4 *iface, BG_JOB_PRIORITY priority)
604 FIXME("%p, %d: stub\n", iface, priority);
605 return S_OK;
608 static HRESULT WINAPI BackgroundCopyJob_GetPriority(IBackgroundCopyJob4 *iface, BG_JOB_PRIORITY *priority)
610 FIXME("%p, %p: stub\n", iface, priority);
611 return E_NOTIMPL;
614 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags(IBackgroundCopyJob4 *iface, ULONG flags)
616 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
617 static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED |
618 BG_NOTIFY_JOB_ERROR |
619 BG_NOTIFY_DISABLE |
620 BG_NOTIFY_JOB_MODIFICATION |
621 BG_NOTIFY_FILE_TRANSFERRED;
623 TRACE("%p, %#x.\n", iface, flags);
625 if (is_job_done(job)) return BG_E_INVALID_STATE;
626 if (flags & ~valid_flags) return E_NOTIMPL;
627 job->notify_flags = flags;
628 return S_OK;
631 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags(IBackgroundCopyJob4 *iface, ULONG *flags)
633 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
635 TRACE("%p, %p.\n", iface, flags);
637 if (!flags) return E_INVALIDARG;
639 *flags = job->notify_flags;
641 return S_OK;
644 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface(IBackgroundCopyJob4 *iface, IUnknown *callback)
646 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
647 HRESULT hr = S_OK;
649 TRACE("%p, %p.\n", iface, callback);
651 if (is_job_done(job)) return BG_E_INVALID_STATE;
653 if (job->callback)
655 IBackgroundCopyCallback2_Release(job->callback);
656 job->callback = NULL;
657 job->callback2 = FALSE;
660 if (callback)
662 hr = IUnknown_QueryInterface(callback, &IID_IBackgroundCopyCallback2, (void **)&job->callback);
663 if (FAILED(hr))
664 hr = IUnknown_QueryInterface(callback, &IID_IBackgroundCopyCallback, (void**)&job->callback);
665 else
666 job->callback2 = TRUE;
669 return hr;
672 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface(IBackgroundCopyJob4 *iface, IUnknown **callback)
674 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
676 TRACE("%p, %p.\n", iface, callback);
678 if (!callback) return E_INVALIDARG;
680 *callback = (IUnknown *)job->callback;
681 if (*callback)
682 IUnknown_AddRef(*callback);
684 return S_OK;
687 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay(IBackgroundCopyJob4 *iface, ULONG delay)
689 FIXME("%p, %u.\n", iface, delay);
690 return S_OK;
693 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay(IBackgroundCopyJob4 *iface, ULONG *delay)
695 FIXME("%p, %p: stub\n", iface, delay);
696 *delay = 30;
697 return S_OK;
700 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout(IBackgroundCopyJob4 *iface, ULONG timeout)
702 FIXME("%p, %u.: stub\n", iface, timeout);
703 return S_OK;
706 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout(IBackgroundCopyJob4 *iface, ULONG *timeout)
708 FIXME("%p, %p: stub\n", iface, timeout);
709 *timeout = 900;
710 return S_OK;
713 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount(IBackgroundCopyJob4 *iface, ULONG *count)
715 FIXME("%p, %p: stub\n", iface, count);
716 return E_NOTIMPL;
719 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings(IBackgroundCopyJob4 *iface, BG_JOB_PROXY_USAGE proxy_usage,
720 const WCHAR *proxy_list, const WCHAR *proxy_bypass_list)
722 FIXME("%p, %d, %s, %s: stub\n", iface, proxy_usage, debugstr_w(proxy_list), debugstr_w(proxy_bypass_list));
723 return E_NOTIMPL;
726 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings(IBackgroundCopyJob4 *iface, BG_JOB_PROXY_USAGE *proxy_usage,
727 LPWSTR *proxy_list, LPWSTR *proxy_bypass_list)
729 FIXME("%p, %p, %p, %p: stub\n", iface, proxy_usage, proxy_list, proxy_bypass_list);
730 return E_NOTIMPL;
733 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership(IBackgroundCopyJob4 *iface)
735 FIXME("%p: stub\n", iface);
736 return E_NOTIMPL;
739 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine(IBackgroundCopyJob4 *iface, LPCWSTR prog, LPCWSTR params)
741 FIXME("%p, %s, %s: stub\n", iface, debugstr_w(prog), debugstr_w(params));
742 return E_NOTIMPL;
745 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine(IBackgroundCopyJob4 *iface, LPWSTR *prog, LPWSTR *params)
747 FIXME("%p, %p, %p: stub\n", iface, prog, params);
748 return E_NOTIMPL;
751 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress(IBackgroundCopyJob4 *iface, BG_JOB_REPLY_PROGRESS *progress)
753 FIXME("%p, %p: stub\n", iface, progress);
754 return E_NOTIMPL;
757 static HRESULT WINAPI BackgroundCopyJob_GetReplyData(IBackgroundCopyJob4 *iface, byte **buffer, UINT64 *length)
759 FIXME("%p, %p, %p: stub\n", iface, buffer, length);
760 return E_NOTIMPL;
763 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName(IBackgroundCopyJob4 *iface, LPCWSTR filename)
765 FIXME("%p, %s: stub\n", iface, debugstr_w(filename));
766 return E_NOTIMPL;
769 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName(IBackgroundCopyJob4 *iface, LPWSTR *filename)
771 FIXME("%p, %p: stub\n", iface, filename);
772 return E_NOTIMPL;
775 static int index_from_target(BG_AUTH_TARGET target)
777 if (!target || target > BG_AUTH_TARGET_PROXY) return -1;
778 return target - 1;
781 static int index_from_scheme(BG_AUTH_SCHEME scheme)
783 if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1;
784 return scheme - 1;
787 static HRESULT WINAPI BackgroundCopyJob_SetCredentials(IBackgroundCopyJob4 *iface, BG_AUTH_CREDENTIALS *cred)
789 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
790 BG_AUTH_CREDENTIALS *new_cred;
791 int idx_target, idx_scheme;
793 TRACE("%p, %p.\n", iface, cred);
795 if ((idx_target = index_from_target(cred->Target)) < 0) return BG_E_INVALID_AUTH_TARGET;
796 if ((idx_scheme = index_from_scheme(cred->Scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
797 new_cred = &job->http_options.creds[idx_target][idx_scheme];
799 EnterCriticalSection(&job->cs);
801 new_cred->Target = cred->Target;
802 new_cred->Scheme = cred->Scheme;
804 if (cred->Credentials.Basic.UserName)
806 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
807 new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName);
809 if (cred->Credentials.Basic.Password)
811 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
812 new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password);
815 LeaveCriticalSection(&job->cs);
816 return S_OK;
819 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials(
820 IBackgroundCopyJob4 *iface,
821 BG_AUTH_TARGET target,
822 BG_AUTH_SCHEME scheme)
824 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob4(iface);
825 BG_AUTH_CREDENTIALS *new_cred;
826 int idx_target, idx_scheme;
828 TRACE("%p, %u, %u.\n", iface, target, scheme);
830 if ((idx_target = index_from_target(target)) < 0) return BG_E_INVALID_AUTH_TARGET;
831 if ((idx_scheme = index_from_scheme(scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
832 new_cred = &job->http_options.creds[idx_target][idx_scheme];
834 EnterCriticalSection(&job->cs);
836 new_cred->Target = new_cred->Scheme = 0;
837 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
838 new_cred->Credentials.Basic.UserName = NULL;
839 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
840 new_cred->Credentials.Basic.Password = NULL;
842 LeaveCriticalSection(&job->cs);
843 return S_OK;
846 static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix(
847 IBackgroundCopyJob4 *iface,
848 LPCWSTR OldPrefix,
849 LPCWSTR NewPrefix)
851 FIXME("%p, %s, %s: stub\n", iface, debugstr_w(OldPrefix), debugstr_w(NewPrefix));
852 return S_OK;
855 static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges(
856 IBackgroundCopyJob4 *iface,
857 LPCWSTR RemoteUrl,
858 LPCWSTR LocalName,
859 DWORD RangeCount,
860 BG_FILE_RANGE Ranges[])
862 FIXME("%p, %s, %s, %u, %p: stub\n", iface, debugstr_w(RemoteUrl), debugstr_w(LocalName), RangeCount, Ranges);
863 return S_OK;
866 static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags(IBackgroundCopyJob4 *iface, DWORD flags)
868 FIXME("%p, %#x: stub\n", iface, flags);
869 return S_OK;
872 static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags(IBackgroundCopyJob4 *iface, DWORD *flags)
874 FIXME("%p, %p: stub\n", iface, flags);
875 return S_OK;
878 static HRESULT WINAPI BackgroundCopyJob_SetPeerCachingFlags(IBackgroundCopyJob4 *iface, DWORD flags)
880 FIXME("%p, %#x.\n", iface, flags);
881 return S_OK;
884 static HRESULT WINAPI BackgroundCopyJob_GetPeerCachingFlags(IBackgroundCopyJob4 *iface, DWORD *flags)
886 FIXME("%p, %p.\n", iface, flags);
887 return E_NOTIMPL;
890 static HRESULT WINAPI BackgroundCopyJob_GetOwnerIntegrityLevel(IBackgroundCopyJob4 *iface, ULONG *level)
892 FIXME("%p, %p.\n", iface, level);
893 return E_NOTIMPL;
896 static HRESULT WINAPI BackgroundCopyJob_GetOwnerElevationState(IBackgroundCopyJob4 *iface, BOOL *elevated)
898 FIXME("%p, %p.\n", iface, elevated);
899 return E_NOTIMPL;
902 static HRESULT WINAPI BackgroundCopyJob_SetMaximumDownloadTime(IBackgroundCopyJob4 *iface, ULONG timeout)
904 FIXME("%p, %u.\n", iface, timeout);
905 return S_OK;
908 static HRESULT WINAPI BackgroundCopyJob_GetMaximumDownloadTime(IBackgroundCopyJob4 *iface, ULONG *timeout)
910 FIXME("%p, %p.\n", iface, timeout);
911 return E_NOTIMPL;
914 static const IBackgroundCopyJob4Vtbl BackgroundCopyJobVtbl =
916 BackgroundCopyJob_QueryInterface,
917 BackgroundCopyJob_AddRef,
918 BackgroundCopyJob_Release,
919 BackgroundCopyJob_AddFileSet,
920 BackgroundCopyJob_AddFile,
921 BackgroundCopyJob_EnumFiles,
922 BackgroundCopyJob_Suspend,
923 BackgroundCopyJob_Resume,
924 BackgroundCopyJob_Cancel,
925 BackgroundCopyJob_Complete,
926 BackgroundCopyJob_GetId,
927 BackgroundCopyJob_GetType,
928 BackgroundCopyJob_GetProgress,
929 BackgroundCopyJob_GetTimes,
930 BackgroundCopyJob_GetState,
931 BackgroundCopyJob_GetError,
932 BackgroundCopyJob_GetOwner,
933 BackgroundCopyJob_SetDisplayName,
934 BackgroundCopyJob_GetDisplayName,
935 BackgroundCopyJob_SetDescription,
936 BackgroundCopyJob_GetDescription,
937 BackgroundCopyJob_SetPriority,
938 BackgroundCopyJob_GetPriority,
939 BackgroundCopyJob_SetNotifyFlags,
940 BackgroundCopyJob_GetNotifyFlags,
941 BackgroundCopyJob_SetNotifyInterface,
942 BackgroundCopyJob_GetNotifyInterface,
943 BackgroundCopyJob_SetMinimumRetryDelay,
944 BackgroundCopyJob_GetMinimumRetryDelay,
945 BackgroundCopyJob_SetNoProgressTimeout,
946 BackgroundCopyJob_GetNoProgressTimeout,
947 BackgroundCopyJob_GetErrorCount,
948 BackgroundCopyJob_SetProxySettings,
949 BackgroundCopyJob_GetProxySettings,
950 BackgroundCopyJob_TakeOwnership,
951 BackgroundCopyJob_SetNotifyCmdLine,
952 BackgroundCopyJob_GetNotifyCmdLine,
953 BackgroundCopyJob_GetReplyProgress,
954 BackgroundCopyJob_GetReplyData,
955 BackgroundCopyJob_SetReplyFileName,
956 BackgroundCopyJob_GetReplyFileName,
957 BackgroundCopyJob_SetCredentials,
958 BackgroundCopyJob_RemoveCredentials,
959 BackgroundCopyJob_ReplaceRemotePrefix,
960 BackgroundCopyJob_AddFileWithRanges,
961 BackgroundCopyJob_SetFileACLFlags,
962 BackgroundCopyJob_GetFileACLFlags,
963 BackgroundCopyJob_SetPeerCachingFlags,
964 BackgroundCopyJob_GetPeerCachingFlags,
965 BackgroundCopyJob_GetOwnerIntegrityLevel,
966 BackgroundCopyJob_GetOwnerElevationState,
967 BackgroundCopyJob_SetMaximumDownloadTime,
968 BackgroundCopyJob_GetMaximumDownloadTime,
971 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions(
972 IBackgroundCopyJobHttpOptions *iface)
974 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface);
977 static HRESULT WINAPI http_options_QueryInterface(
978 IBackgroundCopyJobHttpOptions *iface,
979 REFIID riid,
980 void **ppvObject)
982 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
983 return IBackgroundCopyJob4_QueryInterface(&job->IBackgroundCopyJob4_iface, riid, ppvObject);
986 static ULONG WINAPI http_options_AddRef(
987 IBackgroundCopyJobHttpOptions *iface)
989 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
990 return IBackgroundCopyJob4_AddRef(&job->IBackgroundCopyJob4_iface);
993 static ULONG WINAPI http_options_Release(
994 IBackgroundCopyJobHttpOptions *iface)
996 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
997 return IBackgroundCopyJob4_Release(&job->IBackgroundCopyJob4_iface);
1000 static HRESULT WINAPI http_options_SetClientCertificateByID(
1001 IBackgroundCopyJobHttpOptions *iface,
1002 BG_CERT_STORE_LOCATION StoreLocation,
1003 LPCWSTR StoreName,
1004 BYTE *pCertHashBlob)
1006 FIXME("\n");
1007 return E_NOTIMPL;
1010 static HRESULT WINAPI http_options_SetClientCertificateByName(
1011 IBackgroundCopyJobHttpOptions *iface,
1012 BG_CERT_STORE_LOCATION StoreLocation,
1013 LPCWSTR StoreName,
1014 LPCWSTR SubjectName)
1016 FIXME("\n");
1017 return E_NOTIMPL;
1020 static HRESULT WINAPI http_options_RemoveClientCertificate(
1021 IBackgroundCopyJobHttpOptions *iface)
1023 FIXME("\n");
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI http_options_GetClientCertificate(
1028 IBackgroundCopyJobHttpOptions *iface,
1029 BG_CERT_STORE_LOCATION *pStoreLocation,
1030 LPWSTR *pStoreName,
1031 BYTE **ppCertHashBlob,
1032 LPWSTR *pSubjectName)
1034 FIXME("\n");
1035 return E_NOTIMPL;
1038 static HRESULT WINAPI http_options_SetCustomHeaders(
1039 IBackgroundCopyJobHttpOptions *iface,
1040 LPCWSTR RequestHeaders)
1042 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1044 TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders));
1046 EnterCriticalSection(&job->cs);
1048 if (RequestHeaders)
1050 WCHAR *headers = strdupW(RequestHeaders);
1051 if (!headers)
1053 LeaveCriticalSection(&job->cs);
1054 return E_OUTOFMEMORY;
1056 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1057 job->http_options.headers = headers;
1059 else
1061 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1062 job->http_options.headers = NULL;
1065 LeaveCriticalSection(&job->cs);
1066 return S_OK;
1069 static HRESULT WINAPI http_options_GetCustomHeaders(
1070 IBackgroundCopyJobHttpOptions *iface,
1071 LPWSTR *pRequestHeaders)
1073 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1075 TRACE("(%p)->(%p)\n", iface, pRequestHeaders);
1077 EnterCriticalSection(&job->cs);
1079 if (job->http_options.headers)
1081 WCHAR *headers = co_strdupW(job->http_options.headers);
1082 if (!headers)
1084 LeaveCriticalSection(&job->cs);
1085 return E_OUTOFMEMORY;
1087 *pRequestHeaders = headers;
1088 LeaveCriticalSection(&job->cs);
1089 return S_OK;
1092 *pRequestHeaders = NULL;
1093 LeaveCriticalSection(&job->cs);
1094 return S_FALSE;
1097 static HRESULT WINAPI http_options_SetSecurityFlags(
1098 IBackgroundCopyJobHttpOptions *iface,
1099 ULONG Flags)
1101 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1103 TRACE("(%p)->(0x%08x)\n", iface, Flags);
1105 job->http_options.flags = Flags;
1106 return S_OK;
1109 static HRESULT WINAPI http_options_GetSecurityFlags(
1110 IBackgroundCopyJobHttpOptions *iface,
1111 ULONG *pFlags)
1113 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1115 TRACE("(%p)->(%p)\n", iface, pFlags);
1117 *pFlags = job->http_options.flags;
1118 return S_OK;
1121 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl =
1123 http_options_QueryInterface,
1124 http_options_AddRef,
1125 http_options_Release,
1126 http_options_SetClientCertificateByID,
1127 http_options_SetClientCertificateByName,
1128 http_options_RemoveClientCertificate,
1129 http_options_GetClientCertificate,
1130 http_options_SetCustomHeaders,
1131 http_options_GetCustomHeaders,
1132 http_options_SetSecurityFlags,
1133 http_options_GetSecurityFlags
1136 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job)
1138 HRESULT hr;
1139 BackgroundCopyJobImpl *This;
1141 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job);
1143 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
1144 if (!This)
1145 return E_OUTOFMEMORY;
1147 This->IBackgroundCopyJob4_iface.lpVtbl = &BackgroundCopyJobVtbl;
1148 This->IBackgroundCopyJobHttpOptions_iface.lpVtbl = &http_options_vtbl;
1149 InitializeCriticalSection(&This->cs);
1150 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs");
1152 This->ref = 1;
1153 This->type = type;
1155 This->displayName = strdupW(displayName);
1156 if (!This->displayName)
1158 This->cs.DebugInfo->Spare[0] = 0;
1159 DeleteCriticalSection(&This->cs);
1160 HeapFree(GetProcessHeap(), 0, This);
1161 return E_OUTOFMEMORY;
1164 hr = CoCreateGuid(&This->jobId);
1165 if (FAILED(hr))
1167 This->cs.DebugInfo->Spare[0] = 0;
1168 DeleteCriticalSection(&This->cs);
1169 HeapFree(GetProcessHeap(), 0, This->displayName);
1170 HeapFree(GetProcessHeap(), 0, This);
1171 return hr;
1173 *job_id = This->jobId;
1175 list_init(&This->files);
1176 This->jobProgress.BytesTotal = 0;
1177 This->jobProgress.BytesTransferred = 0;
1178 This->jobProgress.FilesTotal = 0;
1179 This->jobProgress.FilesTransferred = 0;
1181 This->state = BG_JOB_STATE_SUSPENDED;
1182 This->description = NULL;
1183 This->notify_flags = BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED;
1184 This->callback = NULL;
1185 This->callback2 = FALSE;
1187 This->error.context = 0;
1188 This->error.code = S_OK;
1189 This->error.file = NULL;
1191 memset(&This->http_options, 0, sizeof(This->http_options));
1193 This->wait = CreateEventW(NULL, FALSE, FALSE, NULL);
1194 This->cancel = CreateEventW(NULL, FALSE, FALSE, NULL);
1195 This->done = CreateEventW(NULL, FALSE, FALSE, NULL);
1197 *job = This;
1199 TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This);
1201 return S_OK;
1204 void processJob(BackgroundCopyJobImpl *job)
1206 for (;;)
1208 BackgroundCopyFileImpl *file;
1209 BOOL done = TRUE;
1211 EnterCriticalSection(&job->cs);
1212 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
1213 if (!file->fileProgress.Completed)
1215 done = FALSE;
1216 break;
1218 LeaveCriticalSection(&job->cs);
1219 if (done)
1221 transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
1222 if (job->callback && (job->notify_flags & BG_NOTIFY_JOB_TRANSFERRED))
1224 TRACE("Calling JobTransferred -->\n");
1225 IBackgroundCopyCallback2_JobTransferred(job->callback, (IBackgroundCopyJob*)&job->IBackgroundCopyJob4_iface);
1226 TRACE("Called JobTransferred <--\n");
1228 return;
1231 if (!processFile(file, job))
1232 return;