VirtualBox

source: vbox/trunk/src/VBox/Main/VFSExplorerImpl.cpp@ 33438

Last change on this file since 33438 was 33438, checked in by vboxsync, 14 years ago

Main;FE/Qt4: implement Cd and CdUp in IVFSExplorer

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.1 KB
Line 
1/* $Id: VFSExplorerImpl.cpp 33438 2010-10-25 17:45:24Z vboxsync $ */
2/** @file
3 *
4 * IVFSExplorer COM class implementations.
5 */
6
7/*
8 * Copyright (C) 2009 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include <iprt/dir.h>
20#include <iprt/path.h>
21#include <iprt/file.h>
22#include <iprt/s3.h>
23#include <iprt/cpp/utils.h>
24
25#include <VBox/com/array.h>
26
27#include <VBox/param.h>
28#include <VBox/version.h>
29
30#include "VFSExplorerImpl.h"
31#include "VirtualBoxImpl.h"
32#include "ProgressImpl.h"
33
34#include "AutoCaller.h"
35#include "Logging.h"
36
37#include <memory>
38
39////////////////////////////////////////////////////////////////////////////////
40//
41// VFSExplorer definitions
42//
43////////////////////////////////////////////////////////////////////////////////
44
45/* opaque private instance data of VFSExplorer class */
46struct VFSExplorer::Data
47{
48 struct DirEntry
49 {
50 DirEntry(Utf8Str aName, VFSFileType_T aType)
51 : name(aName)
52 , type(aType) {}
53
54 Utf8Str name;
55 VFSFileType_T type;
56 };
57
58 VFSType_T storageType;
59 Utf8Str strUsername;
60 Utf8Str strPassword;
61 Utf8Str strHostname;
62 Utf8Str strPath;
63 Utf8Str strBucket;
64
65 std::list<DirEntry> entryList;
66};
67
68VFSExplorer::VFSExplorer()
69 : mVirtualBox(NULL)
70{
71}
72
73VFSExplorer::~VFSExplorer()
74{
75}
76
77
78/**
79 * VFSExplorer COM initializer.
80 * @param
81 * @return
82 */
83HRESULT VFSExplorer::init(VFSType_T aType, Utf8Str aFilePath, Utf8Str aHostname, Utf8Str aUsername, Utf8Str aPassword, VirtualBox *aVirtualBox)
84{
85 /* Enclose the state transition NotReady->InInit->Ready */
86 AutoInitSpan autoInitSpan(this);
87 AssertReturn(autoInitSpan.isOk(), E_FAIL);
88
89 /* Weak reference to a VirtualBox object */
90 unconst(mVirtualBox) = aVirtualBox;
91
92 /* initialize data */
93 m = new Data;
94
95 m->storageType = aType;
96 m->strPath = aFilePath;
97 m->strHostname = aHostname;
98 m->strUsername = aUsername;
99 m->strPassword = aPassword;
100
101 if (m->storageType == VFSType_S3)
102 {
103 size_t bpos = aFilePath.find("/", 1);
104 if (bpos != Utf8Str::npos)
105 {
106 m->strBucket = aFilePath.substr(1, bpos - 1); /* The bucket without any slashes */
107 aFilePath = aFilePath.substr(bpos); /* The rest of the file path */
108 }
109 }
110
111 /* Confirm a successful initialization */
112 autoInitSpan.setSucceeded();
113
114 return S_OK;
115}
116
117/**
118 * VFSExplorer COM uninitializer.
119 * @return
120 */
121void VFSExplorer::uninit()
122{
123 delete m;
124 m = NULL;
125}
126
127/**
128 * Public method implementation.
129 * @param
130 * @return
131 */
132STDMETHODIMP VFSExplorer::COMGETTER(Path)(BSTR *aPath)
133{
134 if (!aPath)
135 return E_POINTER;
136
137 AutoCaller autoCaller(this);
138 if (FAILED(autoCaller.rc())) return autoCaller.rc();
139
140 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
141
142 Bstr bstrPath(m->strPath);
143 bstrPath.cloneTo(aPath);
144
145 return S_OK;
146}
147
148STDMETHODIMP VFSExplorer::COMGETTER(Type)(VFSType_T *aType)
149{
150 if (!aType)
151 return E_POINTER;
152
153 AutoCaller autoCaller(this);
154 if (FAILED(autoCaller.rc())) return autoCaller.rc();
155
156 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
157
158 *aType = m->storageType;
159
160 return S_OK;
161}
162
163struct VFSExplorer::TaskVFSExplorer
164{
165 enum TaskType
166 {
167 Update,
168 Delete
169 };
170
171 TaskVFSExplorer(TaskType aTaskType, VFSExplorer *aThat, Progress *aProgress)
172 : taskType(aTaskType),
173 pVFSExplorer(aThat),
174 progress(aProgress),
175 rc(S_OK)
176 {}
177 ~TaskVFSExplorer() {}
178
179 int startThread();
180 static int taskThread(RTTHREAD aThread, void *pvUser);
181 static int uploadProgress(unsigned uPercent, void *pvUser);
182
183 TaskType taskType;
184 VFSExplorer *pVFSExplorer;
185 ComObjPtr<Progress> progress;
186 HRESULT rc;
187
188 /* task data */
189 std::list<Utf8Str> filenames;
190};
191
192int VFSExplorer::TaskVFSExplorer::startThread()
193{
194 int vrc = RTThreadCreate(NULL, VFSExplorer::TaskVFSExplorer::taskThread, this,
195 0, RTTHREADTYPE_MAIN_HEAVY_WORKER, 0,
196 "Explorer::Task");
197
198 if (RT_FAILURE(vrc))
199 return VFSExplorer::setErrorStatic(E_FAIL, Utf8StrFmt("Could not create taskThreadVFS (%Rrc)\n", vrc));
200
201 return vrc;
202}
203
204/* static */
205DECLCALLBACK(int) VFSExplorer::TaskVFSExplorer::taskThread(RTTHREAD /* aThread */, void *pvUser)
206{
207 std::auto_ptr<TaskVFSExplorer> task(static_cast<TaskVFSExplorer*>(pvUser));
208 AssertReturn(task.get(), VERR_GENERAL_FAILURE);
209
210 VFSExplorer *pVFSExplorer = task->pVFSExplorer;
211
212 LogFlowFuncEnter();
213 LogFlowFunc(("VFSExplorer %p\n", pVFSExplorer));
214
215 HRESULT rc = S_OK;
216
217 switch(task->taskType)
218 {
219 case TaskVFSExplorer::Update:
220 {
221 if (pVFSExplorer->m->storageType == VFSType_File)
222 rc = pVFSExplorer->updateFS(task.get());
223 else if (pVFSExplorer->m->storageType == VFSType_S3)
224 rc = pVFSExplorer->updateS3(task.get());
225 break;
226 }
227 case TaskVFSExplorer::Delete:
228 {
229 if (pVFSExplorer->m->storageType == VFSType_File)
230 rc = pVFSExplorer->deleteFS(task.get());
231 else if (pVFSExplorer->m->storageType == VFSType_S3)
232 rc = pVFSExplorer->deleteS3(task.get());
233 break;
234 }
235 }
236
237 LogFlowFunc(("rc=%Rhrc\n", rc));
238 LogFlowFuncLeave();
239
240 return VINF_SUCCESS;
241}
242
243/* static */
244int VFSExplorer::TaskVFSExplorer::uploadProgress(unsigned uPercent, void *pvUser)
245{
246 VFSExplorer::TaskVFSExplorer* pTask = *(VFSExplorer::TaskVFSExplorer**)pvUser;
247
248 if (pTask &&
249 !pTask->progress.isNull())
250 {
251 BOOL fCanceled;
252 pTask->progress->COMGETTER(Canceled)(&fCanceled);
253 if (fCanceled)
254 return -1;
255 pTask->progress->SetCurrentOperationProgress(uPercent);
256 }
257 return VINF_SUCCESS;
258}
259
260VFSFileType_T VFSExplorer::RTToVFSFileType(int aType) const
261{
262 VFSFileType_T t;
263 switch(aType)
264 {
265 default:
266 case RTDIRENTRYTYPE_UNKNOWN: t = VFSFileType_Unknown; break;
267 case RTDIRENTRYTYPE_FIFO: t = VFSFileType_Fifo; break;
268 case RTDIRENTRYTYPE_DEV_CHAR: t = VFSFileType_DevChar; break;
269 case RTDIRENTRYTYPE_DIRECTORY: t = VFSFileType_Directory; break;
270 case RTDIRENTRYTYPE_DEV_BLOCK: t = VFSFileType_DevBlock; break;
271 case RTDIRENTRYTYPE_FILE: t = VFSFileType_File; break;
272 case RTDIRENTRYTYPE_SYMLINK: t = VFSFileType_SymLink; break;
273 case RTDIRENTRYTYPE_SOCKET: t = VFSFileType_Socket; break;
274 case RTDIRENTRYTYPE_WHITEOUT: t = VFSFileType_WhiteOut; break;
275 }
276 return t;
277}
278
279HRESULT VFSExplorer::updateFS(TaskVFSExplorer *aTask)
280{
281 LogFlowFuncEnter();
282
283 AutoCaller autoCaller(this);
284 if (FAILED(autoCaller.rc())) return autoCaller.rc();
285
286 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
287
288 HRESULT rc = S_OK;
289
290 std::list<VFSExplorer::Data::DirEntry> fileList;
291 char *pszPath = NULL;
292 PRTDIR pDir = NULL;
293 try
294 {
295 int vrc = RTDirOpen(&pDir, m->strPath.c_str());
296 if (RT_FAILURE(vrc))
297 throw setError(VBOX_E_FILE_ERROR, tr ("Can't open directory '%s' (%Rrc)"), pszPath, vrc);
298
299 if (aTask->progress)
300 aTask->progress->SetCurrentOperationProgress(33);
301 RTDIRENTRY entry;
302 while (RT_SUCCESS(vrc))
303 {
304 vrc = RTDirRead(pDir, &entry, NULL);
305 if (RT_SUCCESS(vrc))
306 {
307 Utf8Str name(entry.szName);
308 if (name != "." &&
309 name != "..")
310 fileList.push_back(VFSExplorer::Data::DirEntry(name, RTToVFSFileType(entry.enmType)));
311 }
312 }
313 if (aTask->progress)
314 aTask->progress->SetCurrentOperationProgress(66);
315 }
316 catch(HRESULT aRC)
317 {
318 rc = aRC;
319 }
320
321 /* Clean up */
322 if (pszPath)
323 RTStrFree(pszPath);
324 if (pDir)
325 RTDirClose(pDir);
326
327 if (aTask->progress)
328 aTask->progress->SetCurrentOperationProgress(99);
329
330 /* Assign the result on success (this clears the old list) */
331 if (rc == S_OK)
332 m->entryList.assign(fileList.begin(), fileList.end());
333
334 aTask->rc = rc;
335
336 if (!aTask->progress.isNull())
337 aTask->progress->notifyComplete(rc);
338
339 LogFlowFunc(("rc=%Rhrc\n", rc));
340 LogFlowFuncLeave();
341
342 return VINF_SUCCESS;
343}
344
345HRESULT VFSExplorer::deleteFS(TaskVFSExplorer *aTask)
346{
347 LogFlowFuncEnter();
348
349 AutoCaller autoCaller(this);
350 if (FAILED(autoCaller.rc())) return autoCaller.rc();
351
352 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
353
354 HRESULT rc = S_OK;
355
356 float fPercentStep = 100.0f / aTask->filenames.size();
357 try
358 {
359 char szPath[RTPATH_MAX];
360 std::list<Utf8Str>::const_iterator it;
361 size_t i = 0;
362 for (it = aTask->filenames.begin();
363 it != aTask->filenames.end();
364 ++it, ++i)
365 {
366 memcpy(szPath, m->strPath.c_str(), strlen(m->strPath.c_str()) + 1);
367 RTPathStripFilename(szPath);
368 RTPathAppend(szPath, sizeof(szPath), (*it).c_str());
369 int vrc = RTFileDelete(szPath);
370 if (RT_FAILURE(vrc))
371 throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), szPath, vrc);
372 if (aTask->progress)
373 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
374 }
375 }
376 catch(HRESULT aRC)
377 {
378 rc = aRC;
379 }
380
381 aTask->rc = rc;
382
383 if (!aTask->progress.isNull())
384 aTask->progress->notifyComplete(rc);
385
386 LogFlowFunc(("rc=%Rhrc\n", rc));
387 LogFlowFuncLeave();
388
389 return VINF_SUCCESS;
390}
391
392HRESULT VFSExplorer::updateS3(TaskVFSExplorer *aTask)
393{
394 LogFlowFuncEnter();
395
396 AutoCaller autoCaller(this);
397 if (FAILED(autoCaller.rc())) return autoCaller.rc();
398
399 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
400
401 HRESULT rc = S_OK;
402
403 RTS3 hS3 = NULL;
404 std::list<VFSExplorer::Data::DirEntry> fileList;
405 try
406 {
407 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
408 if (RT_FAILURE(vrc))
409 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
410
411 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
412 /* Do we need the list of buckets or keys? */
413 if (m->strBucket.isEmpty())
414 {
415 PCRTS3BUCKETENTRY pBuckets = NULL;
416 vrc = RTS3GetBuckets(hS3, &pBuckets);
417 if (RT_FAILURE(vrc))
418 throw setError(E_FAIL, tr ("Can't get buckets (%Rrc)"), vrc);
419
420 PCRTS3BUCKETENTRY pTmpBuckets = pBuckets;
421 while (pBuckets)
422 {
423 fileList.push_back(VFSExplorer::Data::DirEntry(pBuckets->pszName, VFSFileType_Directory));
424 pBuckets = pBuckets->pNext;
425 }
426 RTS3BucketsDestroy(pTmpBuckets);
427 }
428 else
429 {
430 PCRTS3KEYENTRY pKeys = NULL;
431 vrc = RTS3GetBucketKeys(hS3, m->strBucket.c_str(), &pKeys);
432 if (RT_FAILURE(vrc))
433 throw setError(E_FAIL, tr ("Can't get keys for bucket (%Rrc)"), vrc);
434
435 PCRTS3KEYENTRY pTmpKeys = pKeys;
436 while (pKeys)
437 {
438 Utf8Str name(pKeys->pszName);
439 fileList.push_back(VFSExplorer::Data::DirEntry(pKeys->pszName, VFSFileType_File));
440 pKeys = pKeys->pNext;
441 }
442 RTS3KeysDestroy(pTmpKeys);
443 }
444 }
445 catch(HRESULT aRC)
446 {
447 rc = aRC;
448 }
449
450 if (hS3 != NULL)
451 RTS3Destroy(hS3);
452
453 /* Assign the result on success (this clears the old list) */
454 if (rc == S_OK)
455 m->entryList.assign(fileList.begin(), fileList.end());
456
457 aTask->rc = rc;
458
459 if (!aTask->progress.isNull())
460 aTask->progress->notifyComplete(rc);
461
462 LogFlowFunc(("rc=%Rhrc\n", rc));
463 LogFlowFuncLeave();
464
465 return VINF_SUCCESS;
466}
467
468HRESULT VFSExplorer::deleteS3(TaskVFSExplorer *aTask)
469{
470 LogFlowFuncEnter();
471
472 AutoCaller autoCaller(this);
473 if (FAILED(autoCaller.rc())) return autoCaller.rc();
474
475 AutoWriteLock appLock(this COMMA_LOCKVAL_SRC_POS);
476
477 HRESULT rc = S_OK;
478
479 RTS3 hS3 = NULL;
480 float fPercentStep = 100.0f / aTask->filenames.size();
481 try
482 {
483 int vrc = RTS3Create(&hS3, m->strUsername.c_str(), m->strPassword.c_str(), m->strHostname.c_str(), "virtualbox-agent/"VBOX_VERSION_STRING);
484 if (RT_FAILURE(vrc))
485 throw setError(E_FAIL, tr ("Can't open S3 storage service (%Rrc)"), vrc);
486
487 RTS3SetProgressCallback(hS3, VFSExplorer::TaskVFSExplorer::uploadProgress, &aTask);
488
489 std::list<Utf8Str>::const_iterator it;
490 size_t i = 0;
491 for (it = aTask->filenames.begin();
492 it != aTask->filenames.end();
493 ++it, ++i)
494 {
495 vrc = RTS3DeleteKey(hS3, m->strBucket.c_str(), (*it).c_str());
496 if (RT_FAILURE(vrc))
497 throw setError(VBOX_E_FILE_ERROR, tr ("Can't delete file '%s' (%Rrc)"), (*it).c_str(), vrc);
498 if (aTask->progress)
499 aTask->progress->SetCurrentOperationProgress((ULONG)(fPercentStep * i));
500 }
501 }
502 catch(HRESULT aRC)
503 {
504 rc = aRC;
505 }
506
507 aTask->rc = rc;
508
509 if (hS3 != NULL)
510 RTS3Destroy(hS3);
511
512 if (!aTask->progress.isNull())
513 aTask->progress->notifyComplete(rc);
514
515 LogFlowFunc(("rc=%Rhrc\n", rc));
516 LogFlowFuncLeave();
517
518 return VINF_SUCCESS;
519}
520
521STDMETHODIMP VFSExplorer::Update(IProgress **aProgress)
522{
523 CheckComArgOutPointerValid(aProgress);
524
525 AutoCaller autoCaller(this);
526 if (FAILED(autoCaller.rc())) return autoCaller.rc();
527
528 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
529
530 HRESULT rc = S_OK;
531
532 ComObjPtr<Progress> progress;
533 try
534 {
535 Bstr progressDesc = BstrFmt(tr("Update directory info for '%s'"),
536 m->strPath.c_str());
537 /* Create the progress object */
538 progress.createObject();
539
540 rc = progress->init(mVirtualBox,
541 static_cast<IVFSExplorer*>(this),
542 progressDesc.raw(),
543 TRUE /* aCancelable */);
544 if (FAILED(rc)) throw rc;
545
546 /* Initialize our worker task */
547 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Update, this, progress));
548
549 rc = task->startThread();
550 if (FAILED(rc)) throw rc;
551
552 /* Don't destruct on success */
553 task.release();
554 }
555 catch (HRESULT aRC)
556 {
557 rc = aRC;
558 }
559
560 if (SUCCEEDED(rc))
561 /* Return progress to the caller */
562 progress.queryInterfaceTo(aProgress);
563
564 return rc;
565}
566
567STDMETHODIMP VFSExplorer::Cd(IN_BSTR aDir, IProgress **aProgress)
568{
569 CheckComArgStrNotEmptyOrNull(aDir);
570
571 AutoCaller autoCaller(this);
572 if (FAILED(autoCaller.rc())) return autoCaller.rc();
573
574 {
575 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
576 m->strPath = aDir;
577 }
578
579 return Update(aProgress);
580}
581
582STDMETHODIMP VFSExplorer::CdUp(IProgress **aProgress)
583{
584 AutoCaller autoCaller(this);
585 if (FAILED(autoCaller.rc())) return autoCaller.rc();
586
587 Utf8Str strUpPath;
588 {
589 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
590 /* Remove lowest dir entry in a platform neutral way. */
591 char *pszNewPath = RTStrDup(m->strPath.c_str());
592 RTPathStripTrailingSlash(pszNewPath);
593 RTPathStripFilename(pszNewPath);
594 strUpPath = pszNewPath;
595 RTStrFree(pszNewPath);
596 }
597
598 return Cd(Bstr(strUpPath).raw(), aProgress);
599}
600
601STDMETHODIMP VFSExplorer::EntryList(ComSafeArrayOut(BSTR, aNames), ComSafeArrayOut(VFSFileType_T, aTypes))
602{
603 if (ComSafeArrayOutIsNull(aNames) ||
604 ComSafeArrayOutIsNull(aTypes))
605 return E_POINTER;
606
607 AutoCaller autoCaller(this);
608 if (FAILED(autoCaller.rc())) return autoCaller.rc();
609
610 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
611
612 com::SafeArray<BSTR> sfaNames((ULONG)m->entryList.size());
613 com::SafeArray<ULONG> sfaTypes((VFSFileType_T)m->entryList.size());
614
615 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
616 size_t i = 0;
617 for (it = m->entryList.begin();
618 it != m->entryList.end();
619 ++it, ++i)
620 {
621 const VFSExplorer::Data::DirEntry &entry = (*it);
622 Bstr bstr(entry.name);
623 bstr.cloneTo(&sfaNames[i]);
624 sfaTypes[i] = entry.type;
625 }
626
627 sfaNames.detachTo(ComSafeArrayOutArg(aNames));
628 sfaTypes.detachTo(ComSafeArrayOutArg(aTypes));
629
630 return S_OK;
631}
632
633STDMETHODIMP VFSExplorer::Exists(ComSafeArrayIn(IN_BSTR, aNames), ComSafeArrayOut(BSTR, aExists))
634{
635 CheckComArgSafeArrayNotNull(aNames);
636
637 AutoCaller autoCaller(this);
638 if (FAILED(autoCaller.rc())) return autoCaller.rc();
639
640 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
641
642 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
643 std::list<BSTR> listExists;
644
645 for (size_t a=0; a < sfaNames.size(); ++a)
646 {
647 std::list<VFSExplorer::Data::DirEntry>::const_iterator it;
648 for (it = m->entryList.begin();
649 it != m->entryList.end();
650 ++it)
651 {
652 const VFSExplorer::Data::DirEntry &entry = (*it);
653 if (entry.name == RTPathFilename(Utf8Str(sfaNames[a]).c_str()))
654 {
655 BSTR name;
656 Bstr tmp(sfaNames[a]); /* gcc-3.3 cruft */
657 tmp.cloneTo(&name);
658 listExists.push_back(name);
659 }
660 }
661 }
662
663 com::SafeArray<BSTR> sfaExists(listExists);
664 sfaExists.detachTo(ComSafeArrayOutArg(aExists));
665
666 return S_OK;
667}
668
669STDMETHODIMP VFSExplorer::Remove(ComSafeArrayIn(IN_BSTR, aNames), IProgress **aProgress)
670{
671 CheckComArgSafeArrayNotNull(aNames);
672 CheckComArgOutPointerValid(aProgress);
673
674 AutoCaller autoCaller(this);
675 if (FAILED(autoCaller.rc())) return autoCaller.rc();
676
677 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
678
679 HRESULT rc = S_OK;
680
681 com::SafeArray<IN_BSTR> sfaNames(ComSafeArrayInArg(aNames));
682
683 ComObjPtr<Progress> progress;
684 try
685 {
686 /* Create the progress object */
687 progress.createObject();
688
689 rc = progress->init(mVirtualBox, static_cast<IVFSExplorer*>(this),
690 Bstr(tr("Delete files")).raw(),
691 TRUE /* aCancelable */);
692 if (FAILED(rc)) throw rc;
693
694 /* Initialize our worker task */
695 std::auto_ptr<TaskVFSExplorer> task(new TaskVFSExplorer(TaskVFSExplorer::Delete, this, progress));
696
697 /* Add all filenames to delete as task data */
698 for (size_t a=0; a < sfaNames.size(); ++a)
699 task->filenames.push_back(Utf8Str(sfaNames[a]));
700
701 rc = task->startThread();
702 if (FAILED(rc)) throw rc;
703
704 /* Don't destruct on success */
705 task.release();
706 }
707 catch (HRESULT aRC)
708 {
709 rc = aRC;
710 }
711
712 if (SUCCEEDED(rc))
713 /* Return progress to the caller */
714 progress.queryInterfaceTo(aProgress);
715
716 return rc;
717}
718
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