VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/ProgressProxyImpl.cpp@ 54840

Last change on this file since 54840 was 51687, checked in by vboxsync, 10 years ago

Main/Guid+Progress: big cleanup of Guid.h and some Progress cleanup, mostly removing the totally unused aId parameter of the init method and by deleting long gone initi/uninit methods

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

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