~ubuntu-branches/ubuntu/oneiric/virtualbox/oneiric-updates

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-client/GuestCtrlImplDir.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2011-09-02 11:50:47 UTC
  • mfrom: (3.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20110902115047-kfhmsikrpydgyoji
Tags: 4.1.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox.files/source_virtualbox.py
    - debian/virtualbox.install
  - Drop *-source packages.
  - Add vboxguest modalias the to the package control field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: */
 
2
/** @file
 
3
 * VirtualBox Guest Control - Guest directory handling.
 
4
 */
 
5
 
 
6
/*
 
7
 * Copyright (C) 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 "GuestImpl.h"
 
19
#include "GuestCtrlImplPrivate.h"
 
20
#include "GuestDirEntryImpl.h"
 
21
 
 
22
#include "Global.h"
 
23
#include "ConsoleImpl.h"
 
24
#include "ProgressImpl.h"
 
25
#include "VMMDev.h"
 
26
 
 
27
#include "AutoCaller.h"
 
28
#include "Logging.h"
 
29
 
 
30
#include <VBox/VMMDev.h>
 
31
#ifdef VBOX_WITH_GUEST_CONTROL
 
32
# include <VBox/com/array.h>
 
33
# include <VBox/com/ErrorInfo.h>
 
34
#endif
 
35
 
 
36
STDMETHODIMP Guest::DirectoryClose(ULONG aHandle)
 
37
{
 
38
#ifndef VBOX_WITH_GUEST_CONTROL
 
39
    ReturnComNotImplemented();
 
40
#else /* VBOX_WITH_GUEST_CONTROL */
 
41
    using namespace guestControl;
 
42
 
 
43
    if (directoryHandleExists(aHandle))
 
44
    {
 
45
        directoryDestroyHandle(aHandle);
 
46
        return S_OK;
 
47
    }
 
48
 
 
49
    return setError(VBOX_E_IPRT_ERROR,
 
50
                    Guest::tr("Directory handle is invalid"));
 
51
#endif
 
52
}
 
53
 
 
54
STDMETHODIMP Guest::DirectoryCreate(IN_BSTR aDirectory,
 
55
                                    IN_BSTR aUserName, IN_BSTR aPassword,
 
56
                                    ULONG aMode, ULONG aFlags)
 
57
{
 
58
#ifndef VBOX_WITH_GUEST_CONTROL
 
59
    ReturnComNotImplemented();
 
60
#else  /* VBOX_WITH_GUEST_CONTROL */
 
61
    using namespace guestControl;
 
62
 
 
63
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
64
 
 
65
    /* Do not allow anonymous executions (with system rights). */
 
66
    if (RT_UNLIKELY((aUserName) == NULL || *(aUserName) == '\0'))
 
67
        return setError(E_INVALIDARG, tr("No user name specified"));
 
68
 
 
69
    LogRel(("Creating guest directory \"%s\" as  user \"%s\" ...\n",
 
70
            Utf8Str(aDirectory).c_str(), Utf8Str(aUserName).c_str()));
 
71
 
 
72
    return directoryCreateInternal(aDirectory,
 
73
                                   aUserName, aPassword,
 
74
                                   aMode, aFlags, NULL /* rc */);
 
75
#endif
 
76
}
 
77
 
 
78
#ifdef VBOX_WITH_GUEST_CONTROL
 
79
HRESULT Guest::directoryCreateInternal(IN_BSTR aDirectory,
 
80
                                       IN_BSTR aUsername, IN_BSTR aPassword,
 
81
                                       ULONG aMode, ULONG aFlags, int *pRC)
 
82
{
 
83
    using namespace guestControl;
 
84
 
 
85
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
86
 
 
87
    AutoCaller autoCaller(this);
 
88
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
89
 
 
90
    /* Validate flags. */
 
91
    if (aFlags != DirectoryCreateFlag_None)
 
92
    {
 
93
        if (!(aFlags & DirectoryCreateFlag_Parents))
 
94
        {
 
95
            return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
 
96
        }
 
97
    }
 
98
 
 
99
    HRESULT rc = S_OK;
 
100
    try
 
101
    {
 
102
        Utf8Str Utf8Directory(aDirectory);
 
103
 
 
104
        com::SafeArray<IN_BSTR> args;
 
105
        com::SafeArray<IN_BSTR> env;
 
106
 
 
107
        /*
 
108
         * Prepare tool command line.
 
109
         */
 
110
        if (aFlags & DirectoryCreateFlag_Parents)
 
111
            args.push_back(Bstr("--parents").raw());        /* We also want to create the parent directories. */
 
112
        if (aMode > 0)
 
113
        {
 
114
            args.push_back(Bstr("--mode").raw());           /* Set the creation mode. */
 
115
 
 
116
            char szMode[16];
 
117
            RTStrPrintf(szMode, sizeof(szMode), "%o", aMode);
 
118
            args.push_back(Bstr(szMode).raw());
 
119
        }
 
120
        args.push_back(Bstr(Utf8Directory).raw());  /* The directory we want to create. */
 
121
 
 
122
        rc = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_MKDIR).raw(), Bstr("Creating directory").raw(),
 
123
                                   ComSafeArrayAsInParam(args),
 
124
                                   ComSafeArrayAsInParam(env),
 
125
                                   aUsername, aPassword,
 
126
                                   NULL /* Progress */, NULL /* PID */);
 
127
    }
 
128
    catch (std::bad_alloc &)
 
129
    {
 
130
        rc = E_OUTOFMEMORY;
 
131
    }
 
132
    return rc;
 
133
}
 
134
 
 
135
/**
 
136
 * Creates a new directory handle ID and returns it. Returns VERR_TOO_MUCH_DATA
 
137
 * if no free handles left, otherwise VINF_SUCCESS (or some other IPRT error).
 
138
 *
 
139
 * @return IPRT status code.
 
140
 * @param puHandle             Pointer where the handle gets stored to. Optional.
 
141
 * @param uPID                 PID of guest process running the associated "vbox_ls".
 
142
 * @param aDirectory           Directory the handle is assigned to.
 
143
 * @param aFilter              Directory filter.  Optional.
 
144
 * @param uFlags               Directory open flags.
 
145
 *
 
146
 */
 
147
int Guest::directoryCreateHandle(ULONG *puHandle, ULONG uPID,
 
148
                                 IN_BSTR aDirectory, IN_BSTR aFilter, ULONG uFlags)
 
149
{
 
150
    AssertReturn(uPID, VERR_INVALID_PARAMETER);
 
151
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
152
    /* aFilter is optional. */
 
153
    /* uFlags are optional. */
 
154
 
 
155
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
156
 
 
157
    int rc = VERR_TOO_MUCH_DATA;
 
158
    for (uint32_t i = 0; i < UINT32_MAX - 1; i++)
 
159
    {
 
160
        /* Create a new context ID ... */
 
161
        uint32_t uHandleTry = ASMAtomicIncU32(&mNextDirectoryID);
 
162
        GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandleTry);
 
163
        if (it == mGuestDirectoryMap.end()) /* We found a free slot ... */
 
164
        {
 
165
            mGuestDirectoryMap[uHandleTry].mDirectory = aDirectory;
 
166
            mGuestDirectoryMap[uHandleTry].mFilter = aFilter;
 
167
            mGuestDirectoryMap[uHandleTry].mPID = uPID;
 
168
            mGuestDirectoryMap[uHandleTry].mFlags = uFlags;
 
169
            Assert(mGuestDirectoryMap.size());
 
170
 
 
171
            rc = VINF_SUCCESS;
 
172
 
 
173
            if (puHandle)
 
174
                *puHandle = uHandleTry;
 
175
            break;
 
176
        }
 
177
    }
 
178
 
 
179
    return rc;
 
180
}
 
181
 
 
182
/**
 
183
 * Destroys a previously created directory handle and its
 
184
 * associated data.
 
185
 *
 
186
 * @return  IPRT status code.
 
187
 * @param   uHandle             Handle to destroy.
 
188
 */
 
189
void Guest::directoryDestroyHandle(uint32_t uHandle)
 
190
{
 
191
    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
192
 
 
193
    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
 
194
    if (it != mGuestDirectoryMap.end())
 
195
    {
 
196
        /* Destroy raw guest stream buffer - not used
 
197
         * anymore. */
 
198
        it->second.mStream.Destroy();
 
199
 
 
200
        /* Remove callback context (not used anymore). */
 
201
        mGuestDirectoryMap.erase(it);
 
202
    }
 
203
}
 
204
 
 
205
#if 0
 
206
STDMETHODIMP Guest::DirectoryExists(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
 
207
{
 
208
#ifndef VBOX_WITH_GUEST_CONTROL
 
209
    ReturnComNotImplemented();
 
210
#else /* VBOX_WITH_GUEST_CONTROL */
 
211
    using namespace guestControl;
 
212
 
 
213
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
214
 
 
215
    /* Do not allow anonymous executions (with system rights). */
 
216
    if (RT_UNLIKELY((aUsername) == NULL || *(aUsername) == '\0'))
 
217
        return setError(E_INVALIDARG, tr("No user name specified"));
 
218
 
 
219
    return directoryExistsInternal(aDirectory,
 
220
                                   aUsername, aPassword, aExists);
 
221
#endif
 
222
}
 
223
#endif
 
224
 
 
225
#ifdef VBOX_WITH_GUEST_CONTROL
 
226
HRESULT Guest::directoryExistsInternal(IN_BSTR aDirectory, IN_BSTR aUsername, IN_BSTR aPassword, BOOL *aExists)
 
227
{
 
228
    using namespace guestControl;
 
229
 
 
230
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
231
 
 
232
    AutoCaller autoCaller(this);
 
233
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
234
 
 
235
    int rc;
 
236
    HRESULT hr = directoryQueryInfoInternal(aDirectory,
 
237
                                            aUsername, aPassword,
 
238
                                            NULL /* No RTFSOBJINFO needed */,
 
239
                                            RTFSOBJATTRADD_NOTHING, &rc);
 
240
    if (SUCCEEDED(hr))
 
241
    {
 
242
        switch (rc)
 
243
        {
 
244
            case VINF_SUCCESS:
 
245
                *aExists = TRUE;
 
246
                break;
 
247
 
 
248
            case VERR_FILE_NOT_FOUND:
 
249
                *aExists = FALSE;
 
250
                break;
 
251
 
 
252
            case VERR_NOT_FOUND:
 
253
                rc = setError(VBOX_E_IPRT_ERROR,
 
254
                              Guest::tr("Unable to query directory existence"));
 
255
                break;
 
256
 
 
257
            default:
 
258
                AssertReleaseMsgFailed(("directoryExistsInternal: Unknown return value (%Rrc)\n", rc));
 
259
                break;
 
260
        }
 
261
    }
 
262
    return hr;
 
263
}
 
264
#endif
 
265
 
 
266
/**
 
267
 * Gets the associated PID from a directory handle.
 
268
 *
 
269
 * @return  uint32_t                Associated PID, 0 if handle not found/invalid.
 
270
 * @param   uHandle                 Directory handle to get PID for.
 
271
 */
 
272
uint32_t Guest::directoryGetPID(uint32_t uHandle)
 
273
{
 
274
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
275
 
 
276
    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
 
277
    if (it != mGuestDirectoryMap.end())
 
278
        return it->second.mPID;
 
279
 
 
280
    return 0;
 
281
}
 
282
 
 
283
/**
 
284
 * Returns the next directory entry of an open guest directory.
 
285
 * Returns VERR_NO_DATA if no more entries available or VERR_NOT_FOUND
 
286
 * if directory handle is invalid.
 
287
 *
 
288
 * @return  IPRT status code.
 
289
 * @param   uHandle                 Directory handle to get entry for.
 
290
 * @param   streamBlock             Reference that receives the next stream block data.
 
291
 */
 
292
int Guest::directoryGetNextEntry(uint32_t uHandle, GuestProcessStreamBlock &streamBlock)
 
293
{
 
294
    // LOCK DOES NOT WORK HERE!?
 
295
    //AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
 
296
 
 
297
    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
 
298
    if (it != mGuestDirectoryMap.end())
 
299
    {
 
300
        return executeStreamGetNextBlock(it->second.mPID,
 
301
                                         it->second.mStream, streamBlock);
 
302
    }
 
303
 
 
304
    return VERR_NOT_FOUND;
 
305
}
 
306
 
 
307
/**
 
308
 * Checks whether a specified directory handle exists (is valid)
 
309
 * or not.
 
310
 *
 
311
 * @return  bool                    True if handle exists, false if not.
 
312
 * @param   uHandle                 Directory handle to check.
 
313
 */
 
314
bool Guest::directoryHandleExists(uint32_t uHandle)
 
315
{
 
316
    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
317
 
 
318
    GuestDirectoryMapIter it = mGuestDirectoryMap.find(uHandle);
 
319
    if (it != mGuestDirectoryMap.end())
 
320
        return true;
 
321
 
 
322
    return false;
 
323
}
 
324
#endif /* VBOX_WITH_GUEST_CONTROL */
 
325
 
 
326
STDMETHODIMP Guest::DirectoryOpen(IN_BSTR aDirectory, IN_BSTR aFilter,
 
327
                                  ULONG aFlags, IN_BSTR aUserName, IN_BSTR aPassword,
 
328
                                  ULONG *aHandle)
 
329
{
 
330
#ifndef VBOX_WITH_GUEST_CONTROL
 
331
    ReturnComNotImplemented();
 
332
#else /* VBOX_WITH_GUEST_CONTROL */
 
333
    using namespace guestControl;
 
334
 
 
335
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
336
    CheckComArgNotNull(aHandle);
 
337
 
 
338
    /* Do not allow anonymous executions (with system rights). */
 
339
    if (RT_UNLIKELY((aUserName) == NULL || *(aUserName) == '\0'))
 
340
        return setError(E_INVALIDARG, tr("No user name specified"));
 
341
 
 
342
    return directoryOpenInternal(aDirectory, aFilter,
 
343
                                 aFlags,
 
344
                                 aUserName, aPassword,
 
345
                                 aHandle, NULL /* rc */);
 
346
#endif
 
347
}
 
348
 
 
349
#ifdef VBOX_WITH_GUEST_CONTROL
 
350
HRESULT Guest::directoryOpenInternal(IN_BSTR aDirectory, IN_BSTR aFilter,
 
351
                                     ULONG aFlags,
 
352
                                     IN_BSTR aUsername, IN_BSTR aPassword,
 
353
                                     ULONG *aHandle, int *pRC)
 
354
{
 
355
    using namespace guestControl;
 
356
 
 
357
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
358
    CheckComArgNotNull(aHandle);
 
359
 
 
360
    AutoCaller autoCaller(this);
 
361
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
362
 
 
363
    /* Validate flags. No flags supported yet. */
 
364
    if (aFlags != DirectoryOpenFlag_None)
 
365
        return setError(E_INVALIDARG, tr("Unknown flags (%#x)"), aFlags);
 
366
 
 
367
    HRESULT hr = S_OK;
 
368
    try
 
369
    {
 
370
        Utf8Str Utf8Directory(aDirectory);
 
371
        Utf8Str Utf8Filter(aFilter);
 
372
 
 
373
        com::SafeArray<IN_BSTR> args;
 
374
        com::SafeArray<IN_BSTR> env;
 
375
 
 
376
        /*
 
377
         * Prepare tool command line.
 
378
         */
 
379
 
 
380
        /* We need to get output which is machine-readable in form
 
381
         * of "key=value\0..key=value\0\0". */
 
382
        args.push_back(Bstr("--machinereadable").raw());
 
383
 
 
384
        /* We want the long output format. Handy for getting a lot of
 
385
         * details we could (should?) use (later). */
 
386
        args.push_back(Bstr("-l").raw());
 
387
 
 
388
        /* As we want to keep this stuff simple we don't do recursive (-R)
 
389
         * or dereferencing (--dereference) lookups here. This has to be done by
 
390
         * the user. */
 
391
 
 
392
        /* Construct and hand in actual directory name + filter we want to open. */
 
393
        char *pszDirectoryFinal;
 
394
        int cbRet;
 
395
        if (Utf8Filter.isEmpty())
 
396
            cbRet = RTStrAPrintf(&pszDirectoryFinal, "%s", Utf8Directory.c_str());
 
397
        else
 
398
            cbRet = RTStrAPrintf(&pszDirectoryFinal, "%s/%s",
 
399
                                 Utf8Directory.c_str(), Utf8Filter.c_str());
 
400
        if (!cbRet)
 
401
            return setError(E_OUTOFMEMORY, tr("Out of memory while allocating final directory"));
 
402
 
 
403
        args.push_back(Bstr(pszDirectoryFinal).raw());  /* The directory we want to open. */
 
404
 
 
405
        ULONG uPID;
 
406
        /** @todo Don't wait for tool to finish! Might take a lot of time! */
 
407
        hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_LS).raw(), Bstr("Opening directory").raw(),
 
408
                                   ComSafeArrayAsInParam(args),
 
409
                                   ComSafeArrayAsInParam(env),
 
410
                                   aUsername, aPassword,
 
411
                                   NULL /* Progress */, &uPID);
 
412
        if (SUCCEEDED(hr))
 
413
        {
 
414
            /* Assign new directory handle ID. */
 
415
            ULONG uHandleNew;
 
416
            int vrc = directoryCreateHandle(&uHandleNew, uPID,
 
417
                                            aDirectory, aFilter, aFlags);
 
418
            if (RT_SUCCESS(vrc))
 
419
            {
 
420
                *aHandle = uHandleNew;
 
421
            }
 
422
            else
 
423
                hr = setError(VBOX_E_IPRT_ERROR,
 
424
                              tr("Unable to create guest directory handle (%Rrc)"), vrc);
 
425
        }
 
426
    }
 
427
    catch (std::bad_alloc &)
 
428
    {
 
429
        hr = E_OUTOFMEMORY;
 
430
    }
 
431
    return hr;
 
432
}
 
433
 
 
434
HRESULT Guest::directoryQueryInfoInternal(IN_BSTR aDirectory,
 
435
                                          IN_BSTR aUsername, IN_BSTR aPassword,
 
436
                                          PRTFSOBJINFO aObjInfo, RTFSOBJATTRADD enmAddAttribs,
 
437
                                          int *pRC)
 
438
{
 
439
    using namespace guestControl;
 
440
 
 
441
    /** @todo Search directory cache first? */
 
442
 
 
443
    CheckComArgStrNotEmptyOrNull(aDirectory);
 
444
    /* aUsername is optional. */
 
445
    /* aPassword is optional. */
 
446
    /* aObjInfo is optional. */
 
447
 
 
448
    AutoCaller autoCaller(this);
 
449
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
450
 
 
451
    HRESULT hr = S_OK;
 
452
    try
 
453
    {
 
454
        Utf8Str Utf8Dir(aDirectory);
 
455
        Utf8Str Utf8Username(aUsername);
 
456
        Utf8Str Utf8Password(aPassword);
 
457
 
 
458
        com::SafeArray<IN_BSTR> args;
 
459
        com::SafeArray<IN_BSTR> env;
 
460
 
 
461
        /*
 
462
         * Prepare tool command line.
 
463
         */
 
464
 
 
465
        /* We need to get output which is machine-readable in form
 
466
         * of "key=value\0..key=value\0\0". */
 
467
        args.push_back(Bstr("--machinereadable").raw());
 
468
 
 
469
        /* Only the actual file name to chekc is needed for now. */
 
470
        args.push_back(Bstr(Utf8Dir).raw());
 
471
 
 
472
        /*
 
473
         * Execute guest process.
 
474
         */
 
475
        ULONG uPID;
 
476
        hr = executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_STAT).raw(), Bstr("Querying directory information").raw(),
 
477
                                   ComSafeArrayAsInParam(args),
 
478
                                   ComSafeArrayAsInParam(env),
 
479
                                   aUsername, aPassword,
 
480
                                   NULL /* Progress */, &uPID);
 
481
        if (SUCCEEDED(hr))
 
482
        {
 
483
            GuestCtrlStreamObjects streamObjs;
 
484
            hr = executeStreamParse(uPID, streamObjs);
 
485
            if (SUCCEEDED(hr))
 
486
            {
 
487
                int rc = VINF_SUCCESS;
 
488
 
 
489
                Assert(streamObjs.size());
 
490
                const char *pszFsType = streamObjs[0].GetString("ftype");
 
491
                if (!pszFsType) /* Attribute missing? */
 
492
                     rc = VERR_NOT_FOUND;
 
493
                if (   RT_SUCCESS(rc)
 
494
                    && strcmp(pszFsType, "d")) /* Directory? */
 
495
                {
 
496
                     rc = VERR_FILE_NOT_FOUND;
 
497
                     /* This is not critical for Main, so don't set hr --
 
498
                      * we will take care of rc then. */
 
499
                }
 
500
                if (   RT_SUCCESS(rc)
 
501
                    && aObjInfo) /* Do we want object details? */
 
502
                {
 
503
                    hr = executeStreamQueryFsObjInfo(aDirectory, streamObjs[0],
 
504
                                                     aObjInfo, enmAddAttribs);
 
505
                }
 
506
 
 
507
                if (pRC)
 
508
                    *pRC = rc;
 
509
            }
 
510
        }
 
511
    }
 
512
    catch (std::bad_alloc &)
 
513
    {
 
514
        hr = E_OUTOFMEMORY;
 
515
    }
 
516
    return hr;
 
517
}
 
518
#endif /* VBOX_WITH_GUEST_CONTROL */
 
519
 
 
520
STDMETHODIMP Guest::DirectoryRead(ULONG aHandle, IGuestDirEntry **aDirEntry)
 
521
{
 
522
#ifndef VBOX_WITH_GUEST_CONTROL
 
523
    ReturnComNotImplemented();
 
524
#else /* VBOX_WITH_GUEST_CONTROL */
 
525
    using namespace guestControl;
 
526
 
 
527
    CheckComArgOutPointerValid(aDirEntry);
 
528
 
 
529
    AutoCaller autoCaller(this);
 
530
    if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
531
 
 
532
    HRESULT hr = S_OK;
 
533
    try
 
534
    {
 
535
        GuestProcessStreamBlock streamBlock;
 
536
        int rc = directoryGetNextEntry(aHandle, streamBlock);
 
537
        if (RT_SUCCESS(rc))
 
538
        {
 
539
            ComObjPtr <GuestDirEntry> pDirEntry;
 
540
            hr = pDirEntry.createObject();
 
541
            ComAssertComRC(hr);
 
542
 
 
543
            Assert(streamBlock.GetCount());
 
544
            hr = pDirEntry->init(this, streamBlock);
 
545
            if (SUCCEEDED(hr))
 
546
            {
 
547
                pDirEntry.queryInterfaceTo(aDirEntry);
 
548
            }
 
549
            else
 
550
                hr = setError(VBOX_E_IPRT_ERROR,
 
551
                              Guest::tr("Failed to init guest directory entry"));
 
552
        }
 
553
        else if (rc == VERR_NO_DATA)
 
554
        {
 
555
            /* No more directory entries to read. That's fine. */
 
556
            hr = E_ABORT; /** @todo Find/define a better rc! */
 
557
        }
 
558
        else
 
559
            hr = setError(VBOX_E_IPRT_ERROR,
 
560
                          Guest::tr("Failed getting next directory entry (%Rrc)"), rc);
 
561
    }
 
562
    catch (std::bad_alloc &)
 
563
    {
 
564
        hr = E_OUTOFMEMORY;
 
565
    }
 
566
    return hr;
 
567
#endif
 
568
}
 
569