Changeset 34831 in vbox
- Timestamp:
- Dec 8, 2010 1:37:55 PM (14 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r34769 r34831 201 201 static int ctrlPrintProgressError(ComPtr<IProgress> progress) 202 202 { 203 com::ProgressErrorInfo ErrInfo(progress); 204 return ctrlPrintError(ErrInfo); 203 int rc; 204 BOOL fCanceled; 205 if ( SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled))) 206 && fCanceled) 207 { 208 rc = VERR_CANCELLED; 209 } 210 else 211 { 212 com::ProgressErrorInfo ErrInfo(progress); 213 rc = ctrlPrintError(ErrInfo); 214 } 215 return rc; 205 216 } 206 217 … … 954 965 * @return IPRT status code. 955 966 * @param pGuest IGuest interface pointer. 967 * @param fVerbose Verbose flag. 956 968 * @param pszSource Source path of existing host file to copy. 957 969 * @param pszDest Destination path on guest to copy the file to. … … 960 972 * @param uFlags Copy flags. 961 973 */ 962 static int ctrlCopyFileToGuest(IGuest *pGuest, const char *pszSource, const char *pszDest,974 static int ctrlCopyFileToGuest(IGuest *pGuest, bool fVerbose, const char *pszSource, const char *pszDest, 963 975 const char *pszUserName, const char *pszPassword, 964 976 uint32_t uFlags) … … 978 990 else 979 991 { 980 /* Setup signal handling if cancelable. */ 981 ASSERT(progress); 982 bool fCanceledAlready = false; 983 BOOL fCancelable = FALSE; 984 HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable); 985 if (fCancelable) 986 ctrlSignalHandlerInstall(); 987 988 /* Wait for process to exit ... */ 989 BOOL fCompleted = FALSE; 990 BOOL fCanceled = FALSE; 991 while ( SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))) 992 && !fCompleted) 993 { 994 /* Process async cancelation */ 995 if (g_fGuestCtrlCanceled && !fCanceledAlready) 996 { 997 hrc = progress->Cancel(); 998 if (SUCCEEDED(hrc)) 999 fCanceledAlready = TRUE; 1000 else 1001 g_fGuestCtrlCanceled = false; 1002 } 1003 1004 /* Progress canceled by Main API? */ 1005 if ( SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled))) 1006 && fCanceled) 1007 { 1008 break; 1009 } 1010 } 1011 1012 /* Undo signal handling. */ 1013 if (fCancelable) 1014 ctrlSignalHandlerUninstall(); 1015 1016 if (fCanceled) 1017 { 1018 /* Nothing to do here right now. */ 1019 } 1020 else if ( fCompleted 1021 && SUCCEEDED(rc)) 1022 { 1023 LONG iRc; 1024 CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc); 1025 if (FAILED(iRc)) 1026 vrc = ctrlPrintProgressError(progress); 1027 } 992 rc = showProgress(progress); 993 if (FAILED(rc)) 994 vrc = ctrlPrintProgressError(progress); 1028 995 } 1029 996 return vrc; … … 1208 1175 /* Finally copy the desired file (if no dry run selected). */ 1209 1176 if (!fDryRun) 1210 vrc = ctrlCopyFileToGuest(guest, pNode->pszSourcePath, pNode->pszDestPath,1177 vrc = ctrlCopyFileToGuest(guest, fVerbose, pNode->pszSourcePath, pNode->pszDestPath, 1211 1178 Utf8UserName.c_str(), Utf8Password.c_str(), uFlags); 1212 1179 } -
trunk/src/VBox/Main/GuestImpl.cpp
r34760 r34831 31 31 #ifdef VBOX_WITH_GUEST_CONTROL 32 32 # include <VBox/com/array.h> 33 # include <VBox/com/ErrorInfo.h> 33 34 #endif 34 35 #include <iprt/cpp/utils.h> … … 54 55 enum TaskType 55 56 { 57 /** Copies a file to the guest. */ 58 CopyFile = 50, 59 56 60 /** Update Guest Additions by directly copying the required installer 57 61 * off the .ISO file, transfer it to the guest and execute the installer … … 72 76 static int uploadProgress(unsigned uPercent, void *pvUser); 73 77 78 static HRESULT setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, const char * pszText, ...); 79 static HRESULT setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest); 80 74 81 TaskType taskType; 75 82 Guest *pGuest; … … 79 86 /* Task data. */ 80 87 Utf8Str strSource; 81 ULONG uFlags; 88 Utf8Str strDest; 89 Utf8Str strUserName; 90 Utf8Str strPassword; 91 ULONG uFlags; 82 92 }; 83 93 … … 110 120 { 111 121 #ifdef VBOX_WITH_GUEST_CONTROL 122 case TaskGuest::CopyFile: 123 { 124 rc = pGuest->taskCopyFile(task.get()); 125 break; 126 } 112 127 case TaskGuest::UpdateGuestAdditions: 113 128 { … … 144 159 } 145 160 161 /* static */ 162 HRESULT Guest::TaskGuest::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, const char *pszText, ...) 163 { 164 BOOL fCanceled; 165 BOOL fCompleted; 166 if ( SUCCEEDED(pProgress->COMGETTER(Canceled(&fCanceled))) 167 && !fCanceled 168 && SUCCEEDED(pProgress->COMGETTER(Completed(&fCompleted))) 169 && !fCompleted) 170 { 171 va_list va; 172 va_start(va, pszText); 173 HRESULT hr2 = pProgress->notifyComplete(hr, 174 COM_IIDOF(IGuest), 175 Guest::getStaticComponentName(), 176 va); 177 va_end(va); 178 if (hr2 == S_OK) /* If unable to retrieve error, return input error. */ 179 hr2 = hr; 180 return hr2; 181 } 182 return S_OK; 183 } 184 185 /* static */ 186 HRESULT Guest::TaskGuest::setProgressErrorInfo(HRESULT hr, ComObjPtr<Progress> pProgress, ComObjPtr<Guest> pGuest) 187 { 188 return setProgressErrorInfo(hr, pProgress, 189 Utf8Str(com::ErrorInfo((IGuest*)pGuest, COM_IIDOF(IGuest)).getText()).c_str()); 190 } 191 146 192 #ifdef VBOX_WITH_GUEST_CONTROL 193 HRESULT Guest::taskCopyFile(TaskGuest *aTask) 194 { 195 LogFlowFuncEnter(); 196 197 AutoCaller autoCaller(this); 198 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 199 200 /* 201 * Do *not* take a write lock here since we don't (and won't) 202 * touch any class-specific data (of IGuest) here - only the member functions 203 * which get called here can do that. 204 */ 205 206 HRESULT rc = S_OK; 207 208 try 209 { 210 Guest *pGuest = aTask->pGuest; 211 AssertPtr(pGuest); 212 213 /* Does our source file exist? */ 214 if (!RTFileExists(aTask->strSource.c_str())) 215 { 216 /* Since this task runs in another thread than the main Guest object 217 * we cannot rely on notifyComplete's internal lookup - so do this ourselves. */ 218 rc = VBOX_E_IPRT_ERROR; 219 aTask->progress->notifyComplete(rc, 220 COM_IIDOF(IGuest), 221 Guest::getStaticComponentName(), 222 Guest::tr("Source file \"%s\" does not exist"), aTask->strSource.c_str()); 223 } 224 else 225 { 226 RTFILE fileSource; 227 int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(), 228 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 229 if (RT_FAILURE(vrc)) 230 { 231 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 232 Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"), 233 aTask->strSource.c_str(), vrc); 234 } 235 else 236 { 237 uint64_t cbSize; 238 vrc = RTFileGetSize(fileSource, &cbSize); 239 if (RT_FAILURE(vrc)) 240 { 241 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 242 Guest::tr("Could not query file size of \"%s\" (%Rrc)"), 243 aTask->strSource.c_str(), vrc); 244 } 245 else 246 { 247 com::SafeArray<IN_BSTR> args; 248 com::SafeArray<IN_BSTR> env; 249 250 /* 251 * Prepare tool command line. 252 */ 253 char szOutput[RTPATH_MAX]; 254 if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1) 255 { 256 /* 257 * Normalize path slashes, based on the detected guest. 258 */ 259 Utf8Str osType = mData.mOSTypeId; 260 if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) 261 || osType.contains("Windows", Utf8Str::CaseInsensitive)) 262 { 263 /* We have a Windows guest. */ 264 RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */); 265 } 266 else /* ... or something which isn't from Redmond ... */ 267 { 268 RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */); 269 } 270 271 args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */ 272 args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */ 273 } 274 else 275 { 276 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 277 Guest::tr("Error preparing command line")); 278 } 279 280 ComPtr<IProgress> execProgress; 281 ULONG uPID; 282 if (SUCCEEDED(rc)) 283 { 284 LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n", 285 aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize)); 286 /* 287 * Okay, since we gathered all stuff we need until now to start the 288 * actual copying, start the guest part now. 289 */ 290 rc = pGuest->ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(), 291 ExecuteProcessFlag_Hidden 292 | ExecuteProcessFlag_WaitForProcessStartOnly, 293 ComSafeArrayAsInParam(args), 294 ComSafeArrayAsInParam(env), 295 Bstr(aTask->strUserName).raw(), 296 Bstr(aTask->strPassword).raw(), 297 5 * 1000 /* Wait 5s for getting the process started. */, 298 &uPID, execProgress.asOutParam()); 299 if (FAILED(rc)) 300 rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest); 301 } 302 303 if (SUCCEEDED(rc)) 304 { 305 BOOL fCompleted = FALSE; 306 BOOL fCanceled = FALSE; 307 308 size_t cbToRead = cbSize; 309 size_t cbTransfered = 0; 310 size_t cbRead; 311 SafeArray<BYTE> aInputData(_1M); 312 while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) 313 && !fCompleted) 314 { 315 vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), RT_MIN(cbToRead, _1M), &cbRead); 316 /* 317 * Some other error occured? There might be a chance that RTFileRead 318 * could not resolve/map the native error code to an IPRT code, so just 319 * print a generic error. 320 */ 321 if (RT_FAILURE(vrc)) 322 { 323 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 324 Guest::tr("Could not read from file \"%s\" (%Rrc)"), 325 aTask->strSource.c_str(), vrc); 326 break; 327 } 328 329 /* Resize buffer to reflect amount we just have read. */ 330 aInputData.resize(cbRead); 331 332 ULONG uFlags = ProcessInputFlag_None; 333 /* Did we reach the end of the content we want to transfer (last chunk)? */ 334 if ( (cbRead < _1M) 335 /* ... or does the user want to cancel? */ 336 || ( SUCCEEDED(aTask->progress->COMGETTER(Canceled(&fCanceled))) 337 && fCanceled) 338 ) 339 { 340 uFlags |= ProcessInputFlag_EndOfFile; 341 } 342 343 /* Transfer the current chunk ... */ 344 ULONG uBytesWritten; 345 rc = pGuest->SetProcessInput(uPID, uFlags, 346 ComSafeArrayAsInParam(aInputData), &uBytesWritten); 347 if (FAILED(rc)) 348 { 349 rc = TaskGuest::setProgressErrorInfo(rc, aTask->progress, pGuest); 350 break; 351 } 352 353 Assert(cbRead <= cbToRead); 354 cbToRead -= cbRead; 355 Assert(cbToRead >= 0); 356 357 cbTransfered += uBytesWritten; 358 Assert(cbTransfered <= cbSize); 359 aTask->progress->SetCurrentOperationProgress(cbTransfered / (cbSize / 100)); 360 361 /* End of file reached? */ 362 if (cbToRead == 0) 363 break; 364 365 /* Progress canceled by Main API? */ 366 if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled))) 367 && fCanceled) 368 { 369 rc = TaskGuest::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->progress, 370 Guest::tr("Copy operation of file \"%s\" was canceled on guest side"), 371 aTask->strSource.c_str()); 372 break; 373 } 374 } 375 376 if (SUCCEEDED(rc)) 377 aTask->progress->notifyComplete(S_OK); 378 } 379 } 380 RTFileClose(fileSource); 381 } 382 } 383 } 384 catch (HRESULT aRC) 385 { 386 rc = aRC; 387 } 388 389 /* Clean up */ 390 aTask->rc = rc; 391 392 LogFlowFunc(("rc=%Rhrc\n", rc)); 393 LogFlowFuncLeave(); 394 395 return VINF_SUCCESS; 396 } 397 147 398 HRESULT Guest::taskUpdateGuestAdditions(TaskGuest *aTask) 148 399 { … … 307 558 308 559 /* Wait for process to exit ... */ 309 SafeArray<BYTE> aInputData(_ 64K);560 SafeArray<BYTE> aInputData(_1M); 310 561 while ( SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted))) 311 562 && !fCompleted) … … 314 565 /* cbLength contains remaining bytes of our installer file 315 566 * opened above to read. */ 316 size_t cbToRead = RT_MIN(cbLength, _ 64K);567 size_t cbToRead = RT_MIN(cbLength, _1M); 317 568 if (cbToRead) 318 569 { … … 324 575 * we want to transfer (last chunk)? */ 325 576 ULONG uFlags = ProcessInputFlag_None; 326 if (cbRead < _ 64K)577 if (cbRead < _1M) 327 578 { 328 579 uFlags |= ProcessInputFlag_EndOfFile; … … 2146 2397 Assert(uContextID > 0); 2147 2398 2148 size_t cbData = (size_t)RT_MIN(aSize, _64K); 2149 com::SafeArray<BYTE> outputData(cbData); 2399 com::SafeArray<BYTE> outputData((size_t)aSize); 2150 2400 2151 2401 VBOXHGCMSVCPARM paParms[5]; … … 2217 2467 { 2218 2468 /* Do we need to resize the array? */ 2219 if (pData->cbData > cbData)2469 if (pData->cbData > aSize) 2220 2470 outputData.resize(pData->cbData); 2221 2471 … … 2331 2581 } 2332 2582 2333 /** @todo For having a progress object which actually reports something,2334 * the actual copy loop (see below) needs to go to some worker thread2335 * so that this routine can return to the caller (and the caller then2336 * can do display a progress). */2337 2583 STDMETHODIMP Guest::CopyToGuest(IN_BSTR aSource, IN_BSTR aDest, 2338 2584 IN_BSTR aUserName, IN_BSTR aPassword, … … 2342 2588 ReturnComNotImplemented(); 2343 2589 #else /* VBOX_WITH_GUEST_CONTROL */ 2344 using namespace guestControl;2345 2346 2590 CheckComArgStrNotEmptyOrNull(aSource); 2347 2591 CheckComArgStrNotEmptyOrNull(aDest); 2592 CheckComArgStrNotEmptyOrNull(aUserName); 2593 CheckComArgStrNotEmptyOrNull(aPassword); 2348 2594 CheckComArgOutPointerValid(aProgress); 2349 2595 … … 2351 2597 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 2352 2598 2599 /* Validate flags. */ 2353 2600 if (aFlags != 0) /* Flags are not supported at the moment. */ 2354 2601 return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags); 2355 2602 2603 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 2604 2356 2605 HRESULT rc = S_OK; 2357 2606 2607 ComObjPtr<Progress> progress; 2358 2608 try 2359 2609 { 2360 Utf8Str Utf8Source(aSource); 2361 Utf8Str Utf8Dest(aDest); 2362 Utf8Str Utf8UserName(aUserName); 2363 Utf8Str Utf8Password(aPassword); 2364 2365 /* Does our source file exist? */ 2366 if (!RTFileExists(Utf8Source.c_str())) 2367 { 2368 rc = setError(VBOX_E_FILE_ERROR, 2369 tr("Source file \"%s\" does not exist"), Utf8Source.c_str()); 2370 } 2371 else 2372 { 2373 RTFILE fileSource; 2374 int vrc = RTFileOpen(&fileSource, Utf8Source.c_str(), 2375 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE); 2376 if (RT_FAILURE(vrc)) 2377 { 2378 rc = setError(VBOX_E_IPRT_ERROR, 2379 tr("Could not open source file \"%s\" for reading, rc=%Rrc"), 2380 Utf8Source.c_str(), vrc); 2381 } 2382 else 2383 { 2384 uint64_t cbSize; 2385 vrc = RTFileGetSize(fileSource, &cbSize); 2386 if (RT_FAILURE(vrc)) 2387 { 2388 rc = setError(VBOX_E_IPRT_ERROR, 2389 tr("Could not query file size of \"%s\", rc=%Rrc"), 2390 Utf8Source.c_str(), vrc); 2391 } 2392 else 2393 { 2394 com::SafeArray<IN_BSTR> args; 2395 com::SafeArray<IN_BSTR> env; 2396 2397 /* 2398 * Prepare tool command line. 2399 */ 2400 char szOutput[RTPATH_MAX]; 2401 if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", Utf8Dest.c_str()) <= sizeof(szOutput) - 1) 2402 { 2403 /* 2404 * Normalize path slashes, based on the detected guest. 2405 */ 2406 Utf8Str osType = mData.mOSTypeId; 2407 if ( osType.contains("Microsoft", Utf8Str::CaseInsensitive) 2408 || osType.contains("Windows", Utf8Str::CaseInsensitive)) 2409 { 2410 /* We have a Windows guest. */ 2411 RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */); 2412 } 2413 else /* ... or something which isn't from Redmond ... */ 2414 { 2415 RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */); 2416 } 2417 2418 args.push_back(Bstr(VBOXSERVICE_TOOL_CAT).raw()); /* The actual (internal) tool to use (as argv[0]). */ 2419 args.push_back(Bstr(szOutput).raw()); /* We want to write a file ... */ 2420 } 2421 else 2422 rc = setError(VBOX_E_IPRT_ERROR, tr("Error preparing command line")); 2423 2424 ComPtr<IProgress> execProgress; 2425 ULONG uPID; 2426 if (SUCCEEDED(rc)) 2427 { 2428 LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n", 2429 Utf8Source.c_str(), Utf8Dest.c_str(), cbSize)); 2430 /* 2431 * Okay, since we gathered all stuff we need until now to start the 2432 * actual copying, start the guest part now. 2433 */ 2434 rc = ExecuteProcess(Bstr(VBOXSERVICE_TOOL_CAT).raw(), 2435 ExecuteProcessFlag_Hidden 2436 | ExecuteProcessFlag_WaitForProcessStartOnly, 2437 ComSafeArrayAsInParam(args), 2438 ComSafeArrayAsInParam(env), 2439 Bstr(Utf8UserName).raw(), 2440 Bstr(Utf8Password).raw(), 2441 5 * 1000 /* Wait 5s for getting the process started. */, 2442 &uPID, execProgress.asOutParam()); 2443 } 2444 2445 if (SUCCEEDED(rc)) 2446 { 2447 /* Wait for process to exit ... */ 2448 BOOL fCompleted = FALSE; 2449 BOOL fCanceled = FALSE; 2450 2451 size_t cbRead; 2452 SafeArray<BYTE> aInputData(_64K); 2453 while ( SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted))) 2454 && !fCompleted) 2455 { 2456 vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(), _64K, &cbRead); 2457 if ( cbRead == 0 2458 || vrc == VERR_EOF) 2459 break; 2460 2461 aInputData.resize(cbRead); 2462 2463 /* Did we reach the end of the content 2464 * we want to transfer (last chunk)? */ 2465 ULONG uFlags = ProcessInputFlag_None; 2466 if (cbRead < _64K) 2467 uFlags |= ProcessInputFlag_EndOfFile; 2468 2469 /* Transfer the current chunk ... */ 2470 ULONG uBytesWritten; 2471 rc = SetProcessInput(uPID, uFlags, 2472 ComSafeArrayAsInParam(aInputData), &uBytesWritten); 2473 if (FAILED(rc)) 2474 break; 2475 2476 /* Progress canceled by Main API? */ 2477 if ( SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled))) 2478 && fCanceled) 2479 { 2480 break; 2481 } 2482 } 2483 2484 if (SUCCEEDED(rc)) 2485 { 2486 /* Return the progress to the caller. */ 2487 execProgress.queryInterfaceTo(aProgress); 2488 } 2489 } 2490 } 2491 RTFileClose(fileSource); 2492 } 2493 } 2494 } 2495 catch (std::bad_alloc &) 2496 { 2497 rc = E_OUTOFMEMORY; 2610 /* Create the progress object. */ 2611 progress.createObject(); 2612 2613 rc = progress->init(static_cast<IGuest*>(this), 2614 Bstr(tr("Copying file")).raw(), 2615 TRUE /* aCancelable */); 2616 if (FAILED(rc)) throw rc; 2617 2618 /* Initialize our worker task. */ 2619 TaskGuest *pTask = new TaskGuest(TaskGuest::CopyFile, this, progress); 2620 AssertPtr(pTask); 2621 std::auto_ptr<TaskGuest> task(pTask); 2622 2623 /* Assign data - in that case aSource is the full path 2624 * to the Guest Additions .ISO we want to mount. */ 2625 task->strSource = (Utf8Str(aSource)); 2626 task->strDest = (Utf8Str(aDest)); 2627 task->strUserName = (Utf8Str(aUserName)); 2628 task->strPassword = (Utf8Str(aPassword)); 2629 task->uFlags = aFlags; 2630 2631 rc = task->startThread(); 2632 if (FAILED(rc)) throw rc; 2633 2634 /* Don't destruct on success. */ 2635 task.release(); 2636 } 2637 catch (HRESULT aRC) 2638 { 2639 rc = aRC; 2640 } 2641 2642 if (SUCCEEDED(rc)) 2643 { 2644 /* Return progress to the caller. */ 2645 progress.queryInterfaceTo(aProgress); 2498 2646 } 2499 2647 return rc; -
trunk/src/VBox/Main/include/GuestImpl.h
r33898 r34831 136 136 struct TaskGuest; /* Worker thread helper. */ 137 137 #ifdef VBOX_WITH_GUEST_CONTROL 138 HRESULT taskCopyFile(TaskGuest *aTask); 138 139 HRESULT taskUpdateGuestAdditions(TaskGuest *aTask); 139 140
Note:
See TracChangeset
for help on using the changeset viewer.