1 /* 2 * Background Copy Job Interface for BITS 3 * 4 * Copyright 2007 Google (Roy Shea) 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "qmgr.h" 22 23 static inline BOOL is_job_done(const BackgroundCopyJobImpl *job) 24 { 25 return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED; 26 } 27 28 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob2(IBackgroundCopyJob2 *iface) 29 { 30 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob2_iface); 31 } 32 33 static HRESULT WINAPI BackgroundCopyJob_QueryInterface( 34 IBackgroundCopyJob2 *iface, REFIID riid, void **obj) 35 { 36 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 37 38 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); 39 40 if (IsEqualGUID(riid, &IID_IUnknown) 41 || IsEqualGUID(riid, &IID_IBackgroundCopyJob) 42 || IsEqualGUID(riid, &IID_IBackgroundCopyJob2)) 43 { 44 *obj = iface; 45 IBackgroundCopyJob2_AddRef(iface); 46 return S_OK; 47 } 48 49 *obj = NULL; 50 return E_NOINTERFACE; 51 } 52 53 static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob2 *iface) 54 { 55 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 56 ULONG ref = InterlockedIncrement(&This->ref); 57 TRACE("(%p)->(%d)\n", This, ref); 58 return ref; 59 } 60 61 static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob2 *iface) 62 { 63 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 64 ULONG ref = InterlockedDecrement(&This->ref); 65 66 TRACE("(%p)->(%d)\n", This, ref); 67 68 if (ref == 0) 69 { 70 This->cs.DebugInfo->Spare[0] = 0; 71 DeleteCriticalSection(&This->cs); 72 if (This->callback) 73 IBackgroundCopyCallback2_Release(This->callback); 74 HeapFree(GetProcessHeap(), 0, This->displayName); 75 HeapFree(GetProcessHeap(), 0, This->description); 76 HeapFree(GetProcessHeap(), 0, This); 77 } 78 79 return ref; 80 } 81 82 /*** IBackgroundCopyJob methods ***/ 83 84 static HRESULT WINAPI BackgroundCopyJob_AddFileSet( 85 IBackgroundCopyJob2 *iface, 86 ULONG cFileCount, 87 BG_FILE_INFO *pFileSet) 88 { 89 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 90 HRESULT hr = S_OK; 91 ULONG i; 92 93 TRACE("(%p)->(%d %p)\n", This, cFileCount, pFileSet); 94 95 EnterCriticalSection(&This->cs); 96 97 for (i = 0; i < cFileCount; ++i) 98 { 99 BackgroundCopyFileImpl *file; 100 101 /* We should return E_INVALIDARG in these cases. */ 102 FIXME("Check for valid filenames and supported protocols\n"); 103 104 hr = BackgroundCopyFileConstructor(This, pFileSet[i].RemoteName, pFileSet[i].LocalName, &file); 105 if (hr != S_OK) break; 106 107 /* Add a reference to the file to file list */ 108 list_add_head(&This->files, &file->entryFromJob); 109 This->jobProgress.BytesTotal = BG_SIZE_UNKNOWN; 110 ++This->jobProgress.FilesTotal; 111 } 112 113 LeaveCriticalSection(&This->cs); 114 115 return hr; 116 } 117 118 static HRESULT WINAPI BackgroundCopyJob_AddFile( 119 IBackgroundCopyJob2 *iface, 120 LPCWSTR RemoteUrl, 121 LPCWSTR LocalName) 122 { 123 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 124 BG_FILE_INFO file; 125 126 TRACE("(%p)->(%s %s)\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName)); 127 128 file.RemoteName = (LPWSTR)RemoteUrl; 129 file.LocalName = (LPWSTR)LocalName; 130 return IBackgroundCopyJob2_AddFileSet(iface, 1, &file); 131 } 132 133 static HRESULT WINAPI BackgroundCopyJob_EnumFiles( 134 IBackgroundCopyJob2 *iface, 135 IEnumBackgroundCopyFiles **enum_files) 136 { 137 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 138 TRACE("(%p)->(%p)\n", This, enum_files); 139 return EnumBackgroundCopyFilesConstructor(This, enum_files); 140 } 141 142 static HRESULT WINAPI BackgroundCopyJob_Suspend( 143 IBackgroundCopyJob2 *iface) 144 { 145 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 146 FIXME("(%p): stub\n", This); 147 return E_NOTIMPL; 148 } 149 150 static HRESULT WINAPI BackgroundCopyJob_Resume( 151 IBackgroundCopyJob2 *iface) 152 { 153 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 154 HRESULT rv = S_OK; 155 156 TRACE("(%p)\n", This); 157 158 EnterCriticalSection(&globalMgr.cs); 159 if (is_job_done(This)) 160 { 161 rv = BG_E_INVALID_STATE; 162 } 163 else if (This->jobProgress.FilesTransferred == This->jobProgress.FilesTotal) 164 { 165 rv = BG_E_EMPTY; 166 } 167 else if (This->state != BG_JOB_STATE_CONNECTING 168 && This->state != BG_JOB_STATE_TRANSFERRING) 169 { 170 This->state = BG_JOB_STATE_QUEUED; 171 SetEvent(globalMgr.jobEvent); 172 } 173 LeaveCriticalSection(&globalMgr.cs); 174 175 return rv; 176 } 177 178 static HRESULT WINAPI BackgroundCopyJob_Cancel( 179 IBackgroundCopyJob2 *iface) 180 { 181 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 182 FIXME("(%p): stub\n", This); 183 return E_NOTIMPL; 184 } 185 186 static HRESULT WINAPI BackgroundCopyJob_Complete( 187 IBackgroundCopyJob2 *iface) 188 { 189 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 190 HRESULT rv = S_OK; 191 192 TRACE("(%p)\n", This); 193 194 EnterCriticalSection(&This->cs); 195 196 if (is_job_done(This)) 197 { 198 rv = BG_E_INVALID_STATE; 199 } 200 else 201 { 202 BackgroundCopyFileImpl *file; 203 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob) 204 { 205 if (file->fileProgress.Completed) 206 { 207 if (!MoveFileExW(file->tempFileName, file->info.LocalName, 208 (MOVEFILE_COPY_ALLOWED 209 | MOVEFILE_REPLACE_EXISTING 210 | MOVEFILE_WRITE_THROUGH))) 211 { 212 ERR("Couldn't rename file %s -> %s\n", 213 debugstr_w(file->tempFileName), 214 debugstr_w(file->info.LocalName)); 215 rv = BG_S_PARTIAL_COMPLETE; 216 } 217 } 218 else 219 rv = BG_S_PARTIAL_COMPLETE; 220 } 221 } 222 223 This->state = BG_JOB_STATE_ACKNOWLEDGED; 224 LeaveCriticalSection(&This->cs); 225 226 return rv; 227 } 228 229 static HRESULT WINAPI BackgroundCopyJob_GetId( 230 IBackgroundCopyJob2 *iface, 231 GUID *pVal) 232 { 233 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 234 TRACE("(%p)->(%p)\n", This, pVal); 235 *pVal = This->jobId; 236 return S_OK; 237 } 238 239 static HRESULT WINAPI BackgroundCopyJob_GetType( 240 IBackgroundCopyJob2 *iface, 241 BG_JOB_TYPE *pVal) 242 { 243 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 244 245 TRACE("(%p)->(%p)\n", This, pVal); 246 247 if (!pVal) 248 return E_INVALIDARG; 249 250 *pVal = This->type; 251 return S_OK; 252 } 253 254 static HRESULT WINAPI BackgroundCopyJob_GetProgress( 255 IBackgroundCopyJob2 *iface, 256 BG_JOB_PROGRESS *pVal) 257 { 258 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 259 260 TRACE("(%p)->(%p)\n", This, pVal); 261 262 if (!pVal) 263 return E_INVALIDARG; 264 265 EnterCriticalSection(&This->cs); 266 pVal->BytesTotal = This->jobProgress.BytesTotal; 267 pVal->BytesTransferred = This->jobProgress.BytesTransferred; 268 pVal->FilesTotal = This->jobProgress.FilesTotal; 269 pVal->FilesTransferred = This->jobProgress.FilesTransferred; 270 LeaveCriticalSection(&This->cs); 271 272 return S_OK; 273 } 274 275 static HRESULT WINAPI BackgroundCopyJob_GetTimes( 276 IBackgroundCopyJob2 *iface, 277 BG_JOB_TIMES *pVal) 278 { 279 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 280 FIXME("(%p)->(%p): stub\n", This, pVal); 281 return E_NOTIMPL; 282 } 283 284 static HRESULT WINAPI BackgroundCopyJob_GetState( 285 IBackgroundCopyJob2 *iface, 286 BG_JOB_STATE *pVal) 287 { 288 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 289 290 TRACE("(%p)->(%p)\n", This, pVal); 291 292 if (!pVal) 293 return E_INVALIDARG; 294 295 /* Don't think we need a critical section for this */ 296 *pVal = This->state; 297 return S_OK; 298 } 299 300 static HRESULT WINAPI BackgroundCopyJob_GetError( 301 IBackgroundCopyJob2 *iface, 302 IBackgroundCopyError **ppError) 303 { 304 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 305 FIXME("(%p)->(%p): stub\n", This, ppError); 306 return E_NOTIMPL; 307 } 308 309 static HRESULT WINAPI BackgroundCopyJob_GetOwner( 310 IBackgroundCopyJob2 *iface, 311 LPWSTR *pVal) 312 { 313 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 314 FIXME("(%p)->(%p): stub\n", This, pVal); 315 return E_NOTIMPL; 316 } 317 318 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName( 319 IBackgroundCopyJob2 *iface, 320 LPCWSTR Val) 321 { 322 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 323 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val)); 324 return E_NOTIMPL; 325 } 326 327 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName( 328 IBackgroundCopyJob2 *iface, 329 LPWSTR *pVal) 330 { 331 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 332 333 TRACE("(%p)->(%p)\n", This, pVal); 334 335 return return_strval(This->displayName, pVal); 336 } 337 338 static HRESULT WINAPI BackgroundCopyJob_SetDescription( 339 IBackgroundCopyJob2 *iface, 340 LPCWSTR Val) 341 { 342 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 343 static const int max_description_len = 1024; 344 HRESULT hr = S_OK; 345 int len; 346 347 TRACE("(%p)->(%s)\n", This, debugstr_w(Val)); 348 349 if (!Val) return E_INVALIDARG; 350 351 len = strlenW(Val); 352 if (len > max_description_len) return BG_E_STRING_TOO_LONG; 353 354 EnterCriticalSection(&This->cs); 355 356 if (is_job_done(This)) 357 { 358 hr = BG_E_INVALID_STATE; 359 } 360 else 361 { 362 HeapFree(GetProcessHeap(), 0, This->description); 363 if ((This->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)))) 364 strcpyW(This->description, Val); 365 else 366 hr = E_OUTOFMEMORY; 367 } 368 369 LeaveCriticalSection(&This->cs); 370 371 return hr; 372 } 373 374 static HRESULT WINAPI BackgroundCopyJob_GetDescription( 375 IBackgroundCopyJob2 *iface, 376 LPWSTR *pVal) 377 { 378 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 379 380 TRACE("(%p)->(%p)\n", This, pVal); 381 382 return return_strval(This->description, pVal); 383 } 384 385 static HRESULT WINAPI BackgroundCopyJob_SetPriority( 386 IBackgroundCopyJob2 *iface, 387 BG_JOB_PRIORITY Val) 388 { 389 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 390 FIXME("(%p)->(%d): stub\n", This, Val); 391 return S_OK; 392 } 393 394 static HRESULT WINAPI BackgroundCopyJob_GetPriority( 395 IBackgroundCopyJob2 *iface, 396 BG_JOB_PRIORITY *pVal) 397 { 398 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 399 FIXME("(%p)->(%p): stub\n", This, pVal); 400 return E_NOTIMPL; 401 } 402 403 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags( 404 IBackgroundCopyJob2 *iface, 405 ULONG Val) 406 { 407 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 408 static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED | 409 BG_NOTIFY_JOB_ERROR | 410 BG_NOTIFY_DISABLE | 411 BG_NOTIFY_JOB_MODIFICATION | 412 BG_NOTIFY_FILE_TRANSFERRED; 413 414 TRACE("(%p)->(0x%x)\n", This, Val); 415 416 if (is_job_done(This)) return BG_E_INVALID_STATE; 417 if (Val & ~valid_flags) return E_NOTIMPL; 418 This->notify_flags = Val; 419 return S_OK; 420 } 421 422 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags( 423 IBackgroundCopyJob2 *iface, 424 ULONG *pVal) 425 { 426 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 427 428 TRACE("(%p)->(%p)\n", This, pVal); 429 430 if (!pVal) return E_INVALIDARG; 431 432 *pVal = This->notify_flags; 433 434 return S_OK; 435 } 436 437 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface( 438 IBackgroundCopyJob2 *iface, 439 IUnknown *Val) 440 { 441 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 442 HRESULT hr = S_OK; 443 444 TRACE("(%p)->(%p)\n", This, Val); 445 446 if (is_job_done(This)) return BG_E_INVALID_STATE; 447 448 if (This->callback) 449 { 450 IBackgroundCopyCallback2_Release(This->callback); 451 This->callback = NULL; 452 This->callback2 = FALSE; 453 } 454 455 if (Val) 456 { 457 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback2, (void**)&This->callback); 458 if (FAILED(hr)) 459 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback, (void**)&This->callback); 460 else 461 This->callback2 = TRUE; 462 } 463 464 return hr; 465 } 466 467 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface( 468 IBackgroundCopyJob2 *iface, 469 IUnknown **pVal) 470 { 471 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 472 473 TRACE("(%p)->(%p)\n", This, pVal); 474 475 if (!pVal) return E_INVALIDARG; 476 477 *pVal = (IUnknown*)This->callback; 478 if (*pVal) 479 IUnknown_AddRef(*pVal); 480 481 return S_OK; 482 } 483 484 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay( 485 IBackgroundCopyJob2 *iface, 486 ULONG Seconds) 487 { 488 FIXME("%u\n", Seconds); 489 return S_OK; 490 } 491 492 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay( 493 IBackgroundCopyJob2 *iface, 494 ULONG *Seconds) 495 { 496 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 497 FIXME("(%p)->(%p): stub\n", This, Seconds); 498 *Seconds = 30; 499 return S_OK; 500 } 501 502 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout( 503 IBackgroundCopyJob2 *iface, 504 ULONG Seconds) 505 { 506 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 507 FIXME("(%p)->(%d): stub\n", This, Seconds); 508 return S_OK; 509 } 510 511 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout( 512 IBackgroundCopyJob2 *iface, 513 ULONG *Seconds) 514 { 515 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 516 FIXME("(%p)->(%p): stub\n", This, Seconds); 517 *Seconds = 900; 518 return S_OK; 519 } 520 521 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount( 522 IBackgroundCopyJob2 *iface, 523 ULONG *Errors) 524 { 525 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 526 FIXME("(%p)->(%p): stub\n", This, Errors); 527 return E_NOTIMPL; 528 } 529 530 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings( 531 IBackgroundCopyJob2 *iface, 532 BG_JOB_PROXY_USAGE ProxyUsage, 533 const WCHAR *ProxyList, 534 const WCHAR *ProxyBypassList) 535 { 536 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 537 FIXME("(%p)->(%d %s %s): stub\n", This, ProxyUsage, debugstr_w(ProxyList), debugstr_w(ProxyBypassList)); 538 return E_NOTIMPL; 539 } 540 541 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings( 542 IBackgroundCopyJob2 *iface, 543 BG_JOB_PROXY_USAGE *pProxyUsage, 544 LPWSTR *pProxyList, 545 LPWSTR *pProxyBypassList) 546 { 547 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 548 FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList); 549 return E_NOTIMPL; 550 } 551 552 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership( 553 IBackgroundCopyJob2 *iface) 554 { 555 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 556 FIXME("(%p): stub\n", This); 557 return E_NOTIMPL; 558 } 559 560 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine( 561 IBackgroundCopyJob2 *iface, 562 LPCWSTR prog, 563 LPCWSTR params) 564 { 565 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 566 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prog), debugstr_w(params)); 567 return E_NOTIMPL; 568 } 569 570 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine( 571 IBackgroundCopyJob2 *iface, 572 LPWSTR *prog, 573 LPWSTR *params) 574 { 575 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 576 FIXME("(%p)->(%p %p): stub\n", This, prog, params); 577 return E_NOTIMPL; 578 } 579 580 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress( 581 IBackgroundCopyJob2 *iface, 582 BG_JOB_REPLY_PROGRESS *progress) 583 { 584 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 585 FIXME("(%p)->(%p): stub\n", This, progress); 586 return E_NOTIMPL; 587 } 588 589 static HRESULT WINAPI BackgroundCopyJob_GetReplyData( 590 IBackgroundCopyJob2 *iface, 591 byte **pBuffer, 592 UINT64 *pLength) 593 { 594 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 595 FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength); 596 return E_NOTIMPL; 597 } 598 599 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName( 600 IBackgroundCopyJob2 *iface, 601 LPCWSTR filename) 602 { 603 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 604 FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename)); 605 return E_NOTIMPL; 606 } 607 608 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName( 609 IBackgroundCopyJob2 *iface, 610 LPWSTR *pFilename) 611 { 612 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 613 FIXME("(%p)->(%p): stub\n", This, pFilename); 614 return E_NOTIMPL; 615 } 616 617 static HRESULT WINAPI BackgroundCopyJob_SetCredentials( 618 IBackgroundCopyJob2 *iface, 619 BG_AUTH_CREDENTIALS *cred) 620 { 621 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 622 FIXME("(%p)->(%p): stub\n", This, cred); 623 return S_OK; 624 } 625 626 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials( 627 IBackgroundCopyJob2 *iface, 628 BG_AUTH_TARGET target, 629 BG_AUTH_SCHEME scheme) 630 { 631 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); 632 FIXME("(%p)->(%d %d): stub\n", This, target, scheme); 633 return S_OK; 634 } 635 636 static const IBackgroundCopyJob2Vtbl BackgroundCopyJobVtbl = 637 { 638 BackgroundCopyJob_QueryInterface, 639 BackgroundCopyJob_AddRef, 640 BackgroundCopyJob_Release, 641 BackgroundCopyJob_AddFileSet, 642 BackgroundCopyJob_AddFile, 643 BackgroundCopyJob_EnumFiles, 644 BackgroundCopyJob_Suspend, 645 BackgroundCopyJob_Resume, 646 BackgroundCopyJob_Cancel, 647 BackgroundCopyJob_Complete, 648 BackgroundCopyJob_GetId, 649 BackgroundCopyJob_GetType, 650 BackgroundCopyJob_GetProgress, 651 BackgroundCopyJob_GetTimes, 652 BackgroundCopyJob_GetState, 653 BackgroundCopyJob_GetError, 654 BackgroundCopyJob_GetOwner, 655 BackgroundCopyJob_SetDisplayName, 656 BackgroundCopyJob_GetDisplayName, 657 BackgroundCopyJob_SetDescription, 658 BackgroundCopyJob_GetDescription, 659 BackgroundCopyJob_SetPriority, 660 BackgroundCopyJob_GetPriority, 661 BackgroundCopyJob_SetNotifyFlags, 662 BackgroundCopyJob_GetNotifyFlags, 663 BackgroundCopyJob_SetNotifyInterface, 664 BackgroundCopyJob_GetNotifyInterface, 665 BackgroundCopyJob_SetMinimumRetryDelay, 666 BackgroundCopyJob_GetMinimumRetryDelay, 667 BackgroundCopyJob_SetNoProgressTimeout, 668 BackgroundCopyJob_GetNoProgressTimeout, 669 BackgroundCopyJob_GetErrorCount, 670 BackgroundCopyJob_SetProxySettings, 671 BackgroundCopyJob_GetProxySettings, 672 BackgroundCopyJob_TakeOwnership, 673 BackgroundCopyJob_SetNotifyCmdLine, 674 BackgroundCopyJob_GetNotifyCmdLine, 675 BackgroundCopyJob_GetReplyProgress, 676 BackgroundCopyJob_GetReplyData, 677 BackgroundCopyJob_SetReplyFileName, 678 BackgroundCopyJob_GetReplyFileName, 679 BackgroundCopyJob_SetCredentials, 680 BackgroundCopyJob_RemoveCredentials 681 }; 682 683 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job) 684 { 685 HRESULT hr; 686 BackgroundCopyJobImpl *This; 687 int n; 688 689 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job); 690 691 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This); 692 if (!This) 693 return E_OUTOFMEMORY; 694 695 This->IBackgroundCopyJob2_iface.lpVtbl = &BackgroundCopyJobVtbl; 696 InitializeCriticalSection(&This->cs); 697 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs"); 698 699 This->ref = 1; 700 This->type = type; 701 702 n = (strlenW(displayName) + 1) * sizeof *displayName; 703 This->displayName = HeapAlloc(GetProcessHeap(), 0, n); 704 if (!This->displayName) 705 { 706 This->cs.DebugInfo->Spare[0] = 0; 707 DeleteCriticalSection(&This->cs); 708 HeapFree(GetProcessHeap(), 0, This); 709 return E_OUTOFMEMORY; 710 } 711 memcpy(This->displayName, displayName, n); 712 713 hr = CoCreateGuid(&This->jobId); 714 if (FAILED(hr)) 715 { 716 This->cs.DebugInfo->Spare[0] = 0; 717 DeleteCriticalSection(&This->cs); 718 HeapFree(GetProcessHeap(), 0, This->displayName); 719 HeapFree(GetProcessHeap(), 0, This); 720 return hr; 721 } 722 *job_id = This->jobId; 723 724 list_init(&This->files); 725 This->jobProgress.BytesTotal = 0; 726 This->jobProgress.BytesTransferred = 0; 727 This->jobProgress.FilesTotal = 0; 728 This->jobProgress.FilesTransferred = 0; 729 730 This->state = BG_JOB_STATE_SUSPENDED; 731 This->description = NULL; 732 This->notify_flags = BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED; 733 This->callback = NULL; 734 This->callback2 = FALSE; 735 736 *job = This; 737 738 TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This); 739 740 return S_OK; 741 } 742 743 void processJob(BackgroundCopyJobImpl *job) 744 { 745 for (;;) 746 { 747 BackgroundCopyFileImpl *file; 748 BOOL done = TRUE; 749 750 EnterCriticalSection(&job->cs); 751 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob) 752 if (!file->fileProgress.Completed) 753 { 754 done = FALSE; 755 break; 756 } 757 LeaveCriticalSection(&job->cs); 758 if (done) 759 { 760 transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED); 761 return; 762 } 763 764 if (!processFile(file, job)) 765 return; 766 } 767 } 768