VirtualBox

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

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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