VirtualBox

source: vbox/trunk/src/VBox/Main/ProgressProxyImpl.cpp@ 29932

Last change on this file since 29932 was 29932, checked in by vboxsync, 15 years ago

Main: Rewrote ProgressProxyImpl.cpp to proxy at the most one progress object and skip the final operation of the proxy object that wasn't really needed in the openRemoteSession case. Operations are proxied as well so that the openRemoteSession user can wait for the teleporter to become operational by waiting for the 3rd last operation to complete in a loop(!).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/* $Id: ProgressProxyImpl.cpp 29932 2010-06-01 01:40:07Z vboxsync $ */
2/** @file
3 * IProgress implementation for Machine::openRemoteSession in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <iprt/types.h>
19
20#if defined (VBOX_WITH_XPCOM)
21#include <nsIServiceManager.h>
22#include <nsIExceptionService.h>
23#include <nsCOMPtr.h>
24#endif /* defined (VBOX_WITH_XPCOM) */
25
26#include "ProgressProxyImpl.h"
27
28#include "VirtualBoxImpl.h"
29#include "VirtualBoxErrorInfoImpl.h"
30
31#include "Logging.h"
32
33#include <iprt/time.h>
34#include <iprt/semaphore.h>
35
36#include <VBox/err.h>
37
38////////////////////////////////////////////////////////////////////////////////
39// ProgressProxy class
40////////////////////////////////////////////////////////////////////////////////
41
42// constructor / destructor / uninitializer
43////////////////////////////////////////////////////////////////////////////////
44
45
46HRESULT ProgressProxy::FinalConstruct()
47{
48 mfMultiOperation = false;
49 muOtherProgressStartWeight = 0;
50 muOtherProgressWeight = 0;
51 muOtherProgressStartOperation = 0;
52
53 HRESULT rc = Progress::FinalConstruct();
54 return rc;
55}
56
57/**
58 * Initalize it as a one operation Progress object.
59 *
60 * This is used by SessionMachine::OnSessionEnd.
61 */
62HRESULT ProgressProxy::init(
63#if !defined (VBOX_COM_INPROC)
64 VirtualBox *pParent,
65#endif
66 IUnknown *pInitiator,
67 CBSTR bstrDescription,
68 BOOL fCancelable)
69{
70 mfMultiOperation = false;
71 muOtherProgressStartWeight = 1;
72 muOtherProgressWeight = 1;
73 muOtherProgressStartOperation = 1;
74
75 return Progress::init(
76#if !defined (VBOX_COM_INPROC)
77 pParent,
78#endif
79 pInitiator,
80 bstrDescription,
81 fCancelable,
82 1 /* cOperations */,
83 1 /* ulTotalOperationsWeight */,
84 bstrDescription /* bstrFirstOperationDescription */,
85 1 /* ulFirstOperationWeight */,
86 NULL /* pId */);
87}
88
89/**
90 * Initialize for proxying one other progress object.
91 *
92 * This is tailored explicitly for the openRemoteSession code, so we start out
93 * with one operation where we don't have any remote object (powerUp). Then a
94 * remote object is added and stays with us till the end.
95 *
96 * The user must do normal completion notification or risk leave the threads
97 * waiting forever!
98 */
99HRESULT ProgressProxy::init(
100#if !defined (VBOX_COM_INPROC)
101 VirtualBox *pParent,
102#endif
103 IUnknown *pInitiator,
104 CBSTR bstrDescription,
105 BOOL fCancelable,
106 ULONG uTotalOperationsWeight,
107 CBSTR bstrFirstOperationDescription,
108 ULONG uFirstOperationWeight,
109 ULONG cOtherProgressObjectOperations)
110{
111 mfMultiOperation = false;
112 muOtherProgressStartWeight = uFirstOperationWeight;
113 muOtherProgressWeight = uTotalOperationsWeight - uFirstOperationWeight;
114 muOtherProgressStartOperation = 1;
115
116 return Progress::init(
117#if !defined (VBOX_COM_INPROC)
118 pParent,
119#endif
120 pInitiator,
121 bstrDescription,
122 fCancelable,
123 1 + cOtherProgressObjectOperations /* cOperations */,
124 uTotalOperationsWeight,
125 bstrFirstOperationDescription,
126 uFirstOperationWeight,
127 NULL);
128}
129
130void ProgressProxy::FinalRelease()
131{
132 uninit();
133 mfMultiOperation = false;
134 muOtherProgressStartWeight = 0;
135 muOtherProgressWeight = 0;
136 muOtherProgressStartOperation = 0;
137}
138
139void ProgressProxy::uninit()
140{
141 LogFlowThisFunc(("\n"));
142
143 mptrOtherProgress.setNull();
144 Progress::uninit();
145}
146
147// Public methods
148////////////////////////////////////////////////////////////////////////////////
149
150/** Just a wrapper so we can automatically do the handover before setting
151 * the result locally. */
152HRESULT ProgressProxy::setResultCode(HRESULT aResultCode)
153{
154 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
155 clearOtherProgressObjectInternal(true /* fEarly */);
156 return Progress::setResultCode(aResultCode);
157}
158
159/** Just a wrapper so we can automatically do the handover before setting
160 * the result locally. */
161HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode)
162{
163 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
164 clearOtherProgressObjectInternal(true /* fEarly */);
165 return Progress::notifyComplete(aResultCode);
166}
167
168/** Just a wrapper so we can automatically do the handover before setting
169 * the result locally. */
170HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode,
171 const GUID &aIID,
172 const Bstr &aComponent,
173 const char *aText,
174 ...)
175{
176 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
177 clearOtherProgressObjectInternal(true /* fEarly */);
178
179 va_list va;
180 va_start(va, aText);
181 HRESULT hrc = Progress::notifyCompleteV(aResultCode, aIID, aComponent, aText, va);
182 va_end(va);
183 return hrc;
184}
185
186/** Just a wrapper so we can automatically do the handover before setting
187 * the result locally. */
188bool ProgressProxy::notifyPointOfNoReturn(void)
189{
190 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
191 clearOtherProgressObjectInternal(true /* fEarly */);
192 return Progress::notifyPointOfNoReturn();
193}
194
195/**
196 * Sets the other progress object unless the operation has been completed /
197 * canceled already.
198 *
199 * @returns false if failed/canceled, true if not.
200 * @param pOtherProgress The other progress object. Must not be NULL.
201 */
202bool ProgressProxy::setOtherProgressObject(IProgress *pOtherProgress)
203{
204 LogFlowThisFunc(("setOtherProgressObject: %p\n", pOtherProgress));
205 ComPtr<IProgress> ptrOtherProgress = pOtherProgress;
206
207 /*
208 * Query information from the other progress object before we grab the
209 * lock.
210 */
211 ULONG cOperations;
212 HRESULT hrc = pOtherProgress->COMGETTER(OperationCount)(&cOperations);
213 if (FAILED(hrc))
214 cOperations = 1;
215
216 Bstr bstrOperationDescription;
217 hrc = pOtherProgress->COMGETTER(Description)(bstrOperationDescription.asOutParam());
218 if (FAILED(hrc))
219 bstrOperationDescription = "oops";
220
221
222 /*
223 * Take the lock and check for cancelation, cancel the other object if
224 * we've been canceled already.
225 */
226 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
227
228 BOOL fCompletedOrCanceled = mCompleted || mCanceled;
229 if (!fCompletedOrCanceled)
230 {
231 /*
232 * Advance to the next object and operation. If the other object has
233 * more operations than anticipated, adjust our internal count.
234 */
235 mptrOtherProgress = ptrOtherProgress;
236 mfMultiOperation = cOperations > 1;
237
238 muOtherProgressStartWeight = m_ulOperationsCompletedWeight + m_ulCurrentOperationWeight;
239 muOtherProgressWeight = m_ulTotalOperationsWeight - muOtherProgressStartWeight;
240 Progress::SetNextOperation(bstrOperationDescription, muOtherProgressWeight);
241
242 muOtherProgressStartOperation = m_ulCurrentOperation;
243 m_cOperations = cOperations + m_ulCurrentOperation;
244
245 /*
246 * Check for cancelation and completion.
247 */
248 BOOL f;
249 hrc = ptrOtherProgress->COMGETTER(Completed)(&f);
250 fCompletedOrCanceled = FAILED(hrc) || f;
251
252 if (!fCompletedOrCanceled)
253 {
254 hrc = ptrOtherProgress->COMGETTER(Canceled)(&f);
255 fCompletedOrCanceled = SUCCEEDED(hrc) && f;
256 }
257
258 if (fCompletedOrCanceled)
259 {
260 LogFlowThisFunc(("Other object completed or canceled, clearing...\n"));
261 clearOtherProgressObjectInternal(false /*fEarly*/);
262 }
263 else
264 {
265 /*
266 * Finally, mirror the cancelable property.
267 * Note! Note necessary if we do passthru!
268 */
269 if (mCancelable)
270 {
271 hrc = ptrOtherProgress->COMGETTER(Cancelable)(&f);
272 if (SUCCEEDED(hrc) && !f)
273 {
274 LogFlowThisFunc(("The other progress object is not cancelable\n"));
275 mCancelable = FALSE;
276 }
277 }
278 }
279 }
280 else
281 {
282 LogFlowThisFunc(("mCompleted=%RTbool mCanceled=%RTbool - Canceling the other progress object!\n",
283 mCompleted, mCanceled));
284 hrc = ptrOtherProgress->Cancel();
285 LogFlowThisFunc(("Cancel -> %Rhrc", hrc));
286 }
287
288 LogFlowThisFunc(("Returns %RTbool\n", !fCompletedOrCanceled));
289 return !fCompletedOrCanceled;
290}
291
292// Internal methods.
293////////////////////////////////////////////////////////////////////////////////
294
295
296/**
297 * Clear the other progress object reference, first copying over its state.
298 *
299 * This is used internally when completion is signalled one way or another.
300 *
301 * @param fEarly Early clearing or not.
302 */
303void ProgressProxy::clearOtherProgressObjectInternal(bool fEarly)
304{
305 if (mptrOtherProgress.isNotNull())
306 {
307 ComPtr<IProgress> ptrOtherProgress = mptrOtherProgress;
308 mptrOtherProgress.setNull();
309 copyProgressInfo(ptrOtherProgress, fEarly);
310 }
311}
312
313/**
314 * Called to copy over the progress information from @a pOtherProgress.
315 *
316 * @param pOtherProgress The source of the information.
317 * @param fEarly Early copy.
318 *
319 * @note The caller owns the write lock and as cleared mptrOtherProgress
320 * already (or we might recurse forever)!
321 */
322void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly)
323{
324 HRESULT hrc;
325 LogFlowThisFunc(("\n"));
326
327 /*
328 * No point in doing this if the progress object was canceled already.
329 */
330 if (!mCanceled)
331 {
332 /* Detect if the other progress object was canceled. */
333 BOOL fCanceled;
334 hrc = pOtherProgress->COMGETTER(Canceled)(&fCanceled); AssertComRC(hrc);
335 if (FAILED(hrc))
336 fCanceled = FALSE;
337 if (fCanceled)
338 {
339 LogFlowThisFunc(("Canceled\n"));
340 mCanceled = TRUE;
341 if (m_pfnCancelCallback)
342 m_pfnCancelCallback(m_pvCancelUserArg);
343 }
344 else
345 {
346 /* Has it completed? */
347 BOOL fCompleted;
348 hrc = pOtherProgress->COMGETTER(Completed)(&fCompleted); AssertComRC(hrc);
349 if (FAILED(hrc))
350 fCompleted = TRUE;
351 Assert(fCompleted || fEarly);
352 if (fCompleted)
353 {
354 /* Check the result. */
355 LONG hrcResult;
356 hrc = pOtherProgress->COMGETTER(ResultCode)(&hrcResult); AssertComRC(hrc);
357 if (FAILED(hrc))
358 hrcResult = hrc;
359 if (SUCCEEDED((HRESULT)hrcResult))
360 LogFlowThisFunc(("Succeeded\n"));
361 else
362 {
363 /* Get the error information. */
364 ComPtr<IVirtualBoxErrorInfo> ptrErrorInfo;
365 hrc = pOtherProgress->COMGETTER(ErrorInfo)(ptrErrorInfo.asOutParam());
366 if (SUCCEEDED(hrc))
367 {
368 Bstr bstrIID;
369 hrc = ptrErrorInfo->COMGETTER(InterfaceID)(bstrIID.asOutParam());
370 if (FAILED(hrc))
371 bstrIID.setNull();
372
373 Bstr bstrComponent;
374 hrc = ptrErrorInfo->COMGETTER(Component)(bstrComponent.asOutParam());
375 if (FAILED(hrc))
376 bstrComponent = "failed";
377
378 Bstr bstrText;
379 hrc = ptrErrorInfo->COMGETTER(Text)(bstrText.asOutParam());
380 if (FAILED(hrc))
381 bstrText = "<failed>";
382
383 Utf8Str strText(bstrText);
384 LogFlowThisFunc(("Got ErrorInfo(%s); hrcResult=%Rhrc\n", strText.c_str(), hrcResult));
385 Progress::notifyComplete((HRESULT)hrcResult, Guid(bstrIID), bstrComponent, "%s", strText.c_str());
386 }
387 else
388 {
389 LogFlowThisFunc(("ErrorInfo failed with hrc=%Rhrc; hrcResult=%Rhrc\n", hrc, hrcResult));
390 Progress::notifyComplete((HRESULT)hrcResult);
391 }
392 }
393 }
394 else
395 LogFlowThisFunc(("Not completed\n"));
396 }
397 }
398 else
399 LogFlowThisFunc(("Already canceled\n"));
400
401 /*
402 * Did cancelable state change (point of no return)?
403 */
404 if (mCancelable)
405 {
406 BOOL fCancelable;
407 hrc = pOtherProgress->COMGETTER(Cancelable)(&fCancelable); AssertComRC(hrc);
408 if (SUCCEEDED(hrc) && !fCancelable)
409 {
410 LogFlowThisFunc(("point-of-no-return reached\n"));
411 mCancelable = FALSE;
412 }
413 }
414}
415
416
417// IProgress properties
418////////////////////////////////////////////////////////////////////////////////
419
420STDMETHODIMP ProgressProxy::COMGETTER(Cancelable)(BOOL *aCancelable)
421{
422 CheckComArgOutPointerValid(aCancelable);
423
424 AutoCaller autoCaller(this);
425 HRESULT hrc = autoCaller.rc();
426 if (SUCCEEDED(hrc))
427 {
428 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
429
430 /* ASSUME: The cancelable property can only change to FALSE. */
431 if (!mCancelable || mptrOtherProgress.isNull())
432 *aCancelable = mCancelable;
433 else
434 {
435 hrc = mptrOtherProgress->COMGETTER(Cancelable)(aCancelable);
436 if (SUCCEEDED(hrc) && !*aCancelable)
437 {
438 LogFlowThisFunc(("point-of-no-return reached\n"));
439 mCancelable = FALSE;
440 }
441 }
442 }
443 return hrc;
444}
445
446STDMETHODIMP ProgressProxy::COMGETTER(Percent)(ULONG *aPercent)
447{
448 CheckComArgOutPointerValid(aPercent);
449
450 AutoCaller autoCaller(this);
451 HRESULT hrc = autoCaller.rc();
452 if (SUCCEEDED(hrc))
453 {
454 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
455
456 if (mptrOtherProgress.isNotNull())
457 hrc = Progress::COMGETTER(Percent)(aPercent);
458 else
459 {
460 /*
461 * Get the overall percent of the other object and adjust it with
462 * the weighting given to the period before proxying started.
463 */
464 ULONG uPct;
465 hrc = mptrOtherProgress->COMGETTER(Percent)(&uPct);
466 if (SUCCEEDED(hrc))
467 {
468 double rdPercent = ((double)uPct / 100 * muOtherProgressWeight + muOtherProgressStartWeight)
469 / m_ulTotalOperationsWeight * 100;
470 *aPercent = RT_MIN((ULONG)rdPercent, 99); /* mptrOtherProgress is cleared when its completed, so we can never return 100%. */
471 }
472 }
473 }
474 return hrc;
475}
476
477STDMETHODIMP ProgressProxy::COMGETTER(TimeRemaining)(LONG *aTimeRemaining)
478{
479 CheckComArgOutPointerValid(aTimeRemaining);
480
481 AutoCaller autoCaller(this);
482 HRESULT hrc = autoCaller.rc();
483 if (SUCCEEDED(hrc))
484 {
485 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
486
487 if (mptrOtherProgress.isNotNull())
488 hrc = Progress::COMGETTER(TimeRemaining)(aTimeRemaining);
489 else
490 hrc = mptrOtherProgress->COMGETTER(TimeRemaining)(aTimeRemaining);
491 }
492 return hrc;
493}
494
495STDMETHODIMP ProgressProxy::COMGETTER(Completed)(BOOL *aCompleted)
496{
497 /* Not proxied since we EXPECT a normal completion notification call. */
498 return Progress::COMGETTER(Completed)(aCompleted);
499}
500
501STDMETHODIMP ProgressProxy::COMGETTER(Canceled)(BOOL *aCanceled)
502{
503 CheckComArgOutPointerValid(aCanceled);
504
505 AutoCaller autoCaller(this);
506 HRESULT hrc = autoCaller.rc();
507 if (SUCCEEDED(hrc))
508 {
509 /* Check the local data first, then the other object. */
510 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
511 hrc = Progress::COMGETTER(Canceled)(aCanceled);
512 if ( SUCCEEDED(hrc)
513 && !*aCanceled
514 && mptrOtherProgress.isNotNull()
515 && mCancelable)
516 {
517 hrc = mptrOtherProgress->COMGETTER(Canceled)(aCanceled);
518 if (SUCCEEDED(hrc) && *aCanceled)
519 /* This will not complete the object, only mark it as canceled. */
520 clearOtherProgressObjectInternal(false /*fEarly*/);
521 }
522 }
523 return hrc;
524}
525
526STDMETHODIMP ProgressProxy::COMGETTER(ResultCode)(LONG *aResultCode)
527{
528 /* Not proxied since we EXPECT a normal completion notification call. */
529 return Progress::COMGETTER(ResultCode)(aResultCode);
530}
531
532STDMETHODIMP ProgressProxy::COMGETTER(ErrorInfo)(IVirtualBoxErrorInfo **aErrorInfo)
533{
534 /* Not proxied since we EXPECT a normal completion notification call. */
535 return Progress::COMGETTER(ErrorInfo)(aErrorInfo);
536}
537
538STDMETHODIMP ProgressProxy::COMGETTER(Operation)(ULONG *aOperation)
539{
540 CheckComArgOutPointerValid(aOperation);
541
542 AutoCaller autoCaller(this);
543 HRESULT hrc = autoCaller.rc();
544 if (SUCCEEDED(hrc))
545 {
546 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
547 if (mptrOtherProgress.isNull())
548 hrc = Progress::COMGETTER(Operation)(aOperation);
549 else
550 {
551 ULONG uCurOtherOperation;
552 hrc = mptrOtherProgress->COMGETTER(Operation)(&uCurOtherOperation);
553 if (SUCCEEDED(hrc))
554 *aOperation = uCurOtherOperation + muOtherProgressStartOperation;
555 }
556 }
557 return hrc;
558}
559
560STDMETHODIMP ProgressProxy::COMGETTER(OperationDescription)(BSTR *aOperationDescription)
561{
562 CheckComArgOutPointerValid(aOperationDescription);
563
564 AutoCaller autoCaller(this);
565 HRESULT hrc = autoCaller.rc();
566 if (SUCCEEDED(hrc))
567 {
568 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
569 if (mptrOtherProgress.isNull() || !mfMultiOperation)
570 hrc = Progress::COMGETTER(OperationDescription)(aOperationDescription);
571 else
572 hrc = mptrOtherProgress->COMGETTER(OperationDescription)(aOperationDescription);
573 }
574 return hrc;
575}
576
577STDMETHODIMP ProgressProxy::COMGETTER(OperationPercent)(ULONG *aOperationPercent)
578{
579 CheckComArgOutPointerValid(aOperationPercent);
580
581 AutoCaller autoCaller(this);
582 HRESULT hrc = autoCaller.rc();
583 if (SUCCEEDED(hrc))
584 {
585 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
586 if (mptrOtherProgress.isNull() || !mfMultiOperation)
587 hrc = Progress::COMGETTER(OperationPercent)(aOperationPercent);
588 else
589 hrc = mptrOtherProgress->COMGETTER(OperationPercent)(aOperationPercent);
590 }
591 return hrc;
592}
593
594STDMETHODIMP ProgressProxy::COMSETTER(Timeout)(ULONG aTimeout)
595{
596 /* Not currently supported. */
597 NOREF(aTimeout);
598 AssertFailed();
599 return E_NOTIMPL;
600}
601
602STDMETHODIMP ProgressProxy::COMGETTER(Timeout)(ULONG *aTimeout)
603{
604 /* Not currently supported. */
605 CheckComArgOutPointerValid(aTimeout);
606
607 AssertFailed();
608 return E_NOTIMPL;
609}
610
611// IProgress methods
612/////////////////////////////////////////////////////////////////////////////
613
614STDMETHODIMP ProgressProxy::WaitForCompletion(LONG aTimeout)
615{
616 HRESULT hrc;
617 LogFlowThisFuncEnter();
618 LogFlowThisFunc(("aTimeout=%d\n", aTimeout));
619
620 /* No need to wait on the proxied object for these since we'll get the
621 normal completion notifications. */
622 hrc = Progress::WaitForCompletion(aTimeout);
623
624 LogFlowThisFuncLeave();
625 return hrc;
626}
627
628STDMETHODIMP ProgressProxy::WaitForOperationCompletion(ULONG aOperation, LONG aTimeout)
629{
630 LogFlowThisFuncEnter();
631 LogFlowThisFunc(("aOperation=%d aTimeout=%d\n", aOperation, aTimeout));
632
633 AutoCaller autoCaller(this);
634 HRESULT hrc = autoCaller.rc();
635 if (SUCCEEDED(hrc))
636 {
637 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
638
639 CheckComArgExpr(aOperation, aOperation < m_cOperations);
640
641 /*
642 * Check if we can wait locally.
643 */
644 if ( aOperation + 1 == m_cOperations /* final operation */
645 || mptrOtherProgress.isNull())
646 {
647 /* ASSUMES that Progress::WaitForOperationCompletion is using
648 AutoWriteLock::leave() as it saves us from duplicating the code! */
649 hrc = Progress::WaitForOperationCompletion(aOperation, aTimeout);
650 }
651 else
652 {
653 LogFlowThisFunc(("calling the other object...\n"));
654 ComPtr<IProgress> ptrOtherProgress = mptrOtherProgress;
655 alock.release();
656
657 hrc = ptrOtherProgress->WaitForOperationCompletion(aOperation, aTimeout);
658 }
659 }
660
661 LogFlowThisFuncLeave();
662 return hrc;
663}
664
665STDMETHODIMP ProgressProxy::Cancel()
666{
667 LogFlowThisFunc(("\n"));
668 AutoCaller autoCaller(this);
669 HRESULT hrc = autoCaller.rc();
670 if (SUCCEEDED(hrc))
671 {
672 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
673 if (mptrOtherProgress.isNull() || !mCancelable)
674 hrc = Progress::Cancel();
675 else
676 {
677 hrc = mptrOtherProgress->Cancel();
678 if (SUCCEEDED(hrc))
679 clearOtherProgressObjectInternal(false /*fEarly*/);
680 }
681 }
682
683 LogFlowThisFunc(("returns %Rhrc\n", hrc));
684 return hrc;
685}
686
687STDMETHODIMP ProgressProxy::SetCurrentOperationProgress(ULONG aPercent)
688{
689 /* Not supported - why do we actually expose this? */
690 NOREF(aPercent);
691 return E_NOTIMPL;
692}
693
694STDMETHODIMP ProgressProxy::SetNextOperation(IN_BSTR bstrNextOperationDescription, ULONG ulNextOperationsWeight)
695{
696 /* Not supported - why do we actually expose this? */
697 NOREF(bstrNextOperationDescription);
698 NOREF(ulNextOperationsWeight);
699 return E_NOTIMPL;
700}
701
702/* vi: set tabstop=4 shiftwidth=4 expandtab: */
703
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette