VirtualBox

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

Last change on this file since 50874 was 50874, checked in by vboxsync, 11 years ago

6813 src-all/ProgressImp.cpp + some formatting/line length sorting

  • 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 50874 2014-03-25 18:29:02Z vboxsync $ */
2/** @file
3 * IProgress implementation for Machine::openRemoteSession in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2010-2011 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 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 BaseFinalRelease();
139}
140
141void ProgressProxy::uninit()
142{
143 LogFlowThisFunc(("\n"));
144
145 mptrOtherProgress.setNull();
146 Progress::uninit();
147}
148
149// Public methods
150////////////////////////////////////////////////////////////////////////////////
151
152/** Just a wrapper so we can automatically do the handover before setting
153 * the result locally. */
154HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode)
155{
156 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
157 clearOtherProgressObjectInternal(true /* fEarly */);
158 HRESULT hrc = S_OK;
159 if (!mCompleted)
160 hrc = Progress::i_notifyComplete(aResultCode);
161 return hrc;
162}
163
164/** Just a wrapper so we can automatically do the handover before setting
165 * the result locally. */
166HRESULT ProgressProxy::notifyComplete(HRESULT aResultCode,
167 const GUID &aIID,
168 const char *pcszComponent,
169 const char *aText,
170 ...)
171{
172 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
173 clearOtherProgressObjectInternal(true /* fEarly */);
174
175 HRESULT hrc = S_OK;
176 if (!mCompleted)
177 {
178 va_list va;
179 va_start(va, aText);
180 hrc = Progress::i_notifyCompleteV(aResultCode, aIID, pcszComponent, aText, va);
181 va_end(va);
182 }
183 return hrc;
184}
185
186/**
187 * Sets the other progress object unless the operation has been completed /
188 * canceled already.
189 *
190 * @returns false if failed/canceled, true if not.
191 * @param pOtherProgress The other progress object. Must not be NULL.
192 */
193bool ProgressProxy::setOtherProgressObject(IProgress *pOtherProgress)
194{
195 LogFlowThisFunc(("setOtherProgressObject: %p\n", pOtherProgress));
196 ComPtr<IProgress> ptrOtherProgress = pOtherProgress;
197
198 /*
199 * Query information from the other progress object before we grab the
200 * lock.
201 */
202 ULONG cOperations;
203 HRESULT hrc = pOtherProgress->COMGETTER(OperationCount)(&cOperations);
204 if (FAILED(hrc))
205 cOperations = 1;
206
207 Bstr bstrOperationDescription;
208 hrc = pOtherProgress->COMGETTER(Description)(bstrOperationDescription.asOutParam());
209 if (FAILED(hrc))
210 bstrOperationDescription = "oops";
211
212
213 /*
214 * Take the lock and check for cancelation, cancel the other object if
215 * we've been canceled already.
216 */
217 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
218
219 BOOL fCompletedOrCanceled = mCompleted || mCanceled;
220 if (!fCompletedOrCanceled)
221 {
222 /*
223 * Advance to the next object and operation. If the other object has
224 * more operations than anticipated, adjust our internal count.
225 */
226 mptrOtherProgress = ptrOtherProgress;
227 mfMultiOperation = cOperations > 1;
228
229 muOtherProgressStartWeight = m_ulOperationsCompletedWeight + m_ulCurrentOperationWeight;
230 muOtherProgressWeight = m_ulTotalOperationsWeight - muOtherProgressStartWeight;
231 Progress::SetNextOperation(bstrOperationDescription.raw(), muOtherProgressWeight);
232
233 muOtherProgressStartOperation = m_ulCurrentOperation;
234 m_cOperations = cOperations + m_ulCurrentOperation;
235
236 /*
237 * Check for cancelation and completion.
238 */
239 BOOL f;
240 hrc = ptrOtherProgress->COMGETTER(Completed)(&f);
241 fCompletedOrCanceled = FAILED(hrc) || f;
242
243 if (!fCompletedOrCanceled)
244 {
245 hrc = ptrOtherProgress->COMGETTER(Canceled)(&f);
246 fCompletedOrCanceled = SUCCEEDED(hrc) && f;
247 }
248
249 if (fCompletedOrCanceled)
250 {
251 LogFlowThisFunc(("Other object completed or canceled, clearing...\n"));
252 clearOtherProgressObjectInternal(false /*fEarly*/);
253 }
254 else
255 {
256 /*
257 * Finally, mirror the cancelable property.
258 * Note! Note necessary if we do passthru!
259 */
260 if (mCancelable)
261 {
262 hrc = ptrOtherProgress->COMGETTER(Cancelable)(&f);
263 if (SUCCEEDED(hrc) && !f)
264 {
265 LogFlowThisFunc(("The other progress object is not cancelable\n"));
266 mCancelable = FALSE;
267 }
268 }
269 }
270 }
271 else
272 {
273 LogFlowThisFunc(("mCompleted=%RTbool mCanceled=%RTbool - Canceling the other progress object!\n",
274 mCompleted, mCanceled));
275 hrc = ptrOtherProgress->Cancel();
276 LogFlowThisFunc(("Cancel -> %Rhrc", hrc));
277 }
278
279 LogFlowThisFunc(("Returns %RTbool\n", !fCompletedOrCanceled));
280 return !fCompletedOrCanceled;
281}
282
283// Internal methods.
284////////////////////////////////////////////////////////////////////////////////
285
286
287/**
288 * Clear the other progress object reference, first copying over its state.
289 *
290 * This is used internally when completion is signalled one way or another.
291 *
292 * @param fEarly Early clearing or not.
293 */
294void ProgressProxy::clearOtherProgressObjectInternal(bool fEarly)
295{
296 if (!mptrOtherProgress.isNull())
297 {
298 ComPtr<IProgress> ptrOtherProgress = mptrOtherProgress;
299 mptrOtherProgress.setNull();
300 copyProgressInfo(ptrOtherProgress, fEarly);
301 }
302}
303
304/**
305 * Called to copy over the progress information from @a pOtherProgress.
306 *
307 * @param pOtherProgress The source of the information.
308 * @param fEarly Early copy.
309 *
310 * @note The caller owns the write lock and as cleared mptrOtherProgress
311 * already (or we might recurse forever)!
312 */
313void ProgressProxy::copyProgressInfo(IProgress *pOtherProgress, bool fEarly)
314{
315 HRESULT hrc;
316 LogFlowThisFunc(("\n"));
317
318 NOREF(fEarly);
319
320 /*
321 * No point in doing this if the progress object was canceled already.
322 */
323 if (!mCanceled)
324 {
325 /* Detect if the other progress object was canceled. */
326 BOOL fCanceled;
327 hrc = pOtherProgress->COMGETTER(Canceled)(&fCanceled);
328 if (FAILED(hrc))
329 fCanceled = FALSE;
330 if (fCanceled)
331 {
332 LogFlowThisFunc(("Canceled\n"));
333 mCanceled = TRUE;
334 if (m_pfnCancelCallback)
335 m_pfnCancelCallback(m_pvCancelUserArg);
336 }
337 else
338 {
339 /* Has it completed? */
340 BOOL fCompleted;
341 hrc = pOtherProgress->COMGETTER(Completed)(&fCompleted);
342 if (FAILED(hrc))
343 fCompleted = TRUE;
344 Assert(fCompleted || fEarly);
345 if (fCompleted)
346 {
347 /* Check the result. */
348 LONG hrcResult;
349 hrc = pOtherProgress->COMGETTER(ResultCode)(&hrcResult);
350 if (FAILED(hrc))
351 hrcResult = hrc;
352 if (SUCCEEDED((HRESULT)hrcResult))
353 LogFlowThisFunc(("Succeeded\n"));
354 else
355 {
356 /* Get the error information. */
357 ComPtr<IVirtualBoxErrorInfo> ptrErrorInfo;
358 hrc = pOtherProgress->COMGETTER(ErrorInfo)(ptrErrorInfo.asOutParam());
359 if (SUCCEEDED(hrc) && !ptrErrorInfo.isNull())
360 {
361 Bstr bstrIID;
362 hrc = ptrErrorInfo->COMGETTER(InterfaceID)(bstrIID.asOutParam()); AssertComRC(hrc);
363 if (FAILED(hrc))
364 bstrIID.setNull();
365
366 Bstr bstrComponent;
367 hrc = ptrErrorInfo->COMGETTER(Component)(bstrComponent.asOutParam()); AssertComRC(hrc);
368 if (FAILED(hrc))
369 bstrComponent = "failed";
370
371 Bstr bstrText;
372 hrc = ptrErrorInfo->COMGETTER(Text)(bstrText.asOutParam()); AssertComRC(hrc);
373 if (FAILED(hrc))
374 bstrText = "<failed>";
375
376 Utf8Str strText(bstrText);
377 LogFlowThisFunc(("Got ErrorInfo(%s); hrcResult=%Rhrc\n", strText.c_str(), hrcResult));
378 Progress::i_notifyComplete((HRESULT)hrcResult,
379 Guid(bstrIID).ref(),
380 Utf8Str(bstrComponent).c_str(),
381 "%s", strText.c_str());
382 }
383 else
384 {
385 LogFlowThisFunc(("ErrorInfo failed with hrc=%Rhrc; hrcResult=%Rhrc\n", hrc, hrcResult));
386 Progress::i_notifyComplete((HRESULT)hrcResult,
387 COM_IIDOF(IProgress),
388 "ProgressProxy",
389 tr("No error info"));
390 }
391 }
392 }
393 else
394 LogFlowThisFunc(("Not completed\n"));
395 }
396 }
397 else
398 LogFlowThisFunc(("Already canceled\n"));
399
400 /*
401 * Did cancelable state change (point of no return)?
402 */
403 if (mCancelable && !mCompleted && !mCanceled)
404 {
405 BOOL fCancelable;
406 hrc = pOtherProgress->COMGETTER(Cancelable)(&fCancelable); AssertComRC(hrc);
407 if (SUCCEEDED(hrc) && !fCancelable)
408 {
409 LogFlowThisFunc(("point-of-no-return reached\n"));
410 mCancelable = FALSE;
411 }
412 }
413}
414
415
416// IProgress properties
417////////////////////////////////////////////////////////////////////////////////
418
419STDMETHODIMP ProgressProxy::COMGETTER(Cancelable)(BOOL *aCancelable)
420{
421 CheckComArgOutPointerValid(aCancelable);
422
423 AutoCaller autoCaller(this);
424 HRESULT hrc = autoCaller.rc();
425 if (SUCCEEDED(hrc))
426 {
427 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
428
429 /* ASSUME: The cancelable property can only change to FALSE. */
430 if (!mCancelable || mptrOtherProgress.isNull())
431 *aCancelable = mCancelable;
432 else
433 {
434 hrc = mptrOtherProgress->COMGETTER(Cancelable)(aCancelable);
435 if (SUCCEEDED(hrc) && !*aCancelable)
436 {
437 LogFlowThisFunc(("point-of-no-return reached\n"));
438 mCancelable = FALSE;
439 }
440 }
441 }
442 return hrc;
443}
444
445STDMETHODIMP ProgressProxy::COMGETTER(Percent)(ULONG *aPercent)
446{
447 CheckComArgOutPointerValid(aPercent);
448
449 AutoCaller autoCaller(this);
450 HRESULT hrc = autoCaller.rc();
451 if (SUCCEEDED(hrc))
452 {
453 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
454
455 if (mptrOtherProgress.isNull())
456 hrc = Progress::COMGETTER(Percent)(aPercent);
457 else
458 {
459 /*
460 * Get the overall percent of the other object and adjust it with
461 * the weighting given to the period before proxying started.
462 */
463 ULONG uPct;
464 hrc = mptrOtherProgress->COMGETTER(Percent)(&uPct);
465 if (SUCCEEDED(hrc))
466 {
467 double rdPercent = ((double)uPct / 100 * muOtherProgressWeight + muOtherProgressStartWeight)
468 / m_ulTotalOperationsWeight * 100;
469 *aPercent = RT_MIN((ULONG)rdPercent, 99); /* mptrOtherProgress is cleared when its completed,
470 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.isNull())
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.isNull()
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.

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