~ubuntu-branches/ubuntu/quantal/virtualbox/quantal

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-server/VirtualBoxImpl.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2012-04-05 12:41:55 UTC
  • mfrom: (3.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120405124155-i7b39tv5ddwhubbe
Tags: 4.1.12-dfsg-2
* Upstream has replaced the 4.1.12 tarball with a new one that fixes a
  crash when creating host only interfaces. (Closes: #667460)
  - Add 36-tarball-respin.patch which contains the diff between the old
    and the new tarball.

Show diffs side-by-side

added added

removed removed

Lines of Context:
627
627
                                 strMachineFolder);
628
628
        if (FAILED(rc)) return rc;
629
629
 
630
 
        rc = registerHardDisk(pHardDisk, NULL /* pllRegistriesThatNeedSaving */);
 
630
        rc = registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk, NULL /* pllRegistriesThatNeedSaving */);
631
631
        if (FAILED(rc)) return rc;
632
632
    }
633
633
 
647
647
                              strMachineFolder);
648
648
        if (FAILED(rc)) return rc;
649
649
 
650
 
        rc = registerImage(pImage,
651
 
                           DeviceType_DVD,
652
 
                           NULL /* pllRegistriesThatNeedSaving */);
 
650
        rc = registerMedium(pImage, &pImage,
 
651
                            DeviceType_DVD,
 
652
                            NULL /* pllRegistriesThatNeedSaving */);
653
653
        if (FAILED(rc)) return rc;
654
654
    }
655
655
 
669
669
                              strMachineFolder);
670
670
        if (FAILED(rc)) return rc;
671
671
 
672
 
        rc = registerImage(pImage,
673
 
                           DeviceType_Floppy,
674
 
                           NULL /* pllRegistriesThatNeedSaving */);
 
672
        rc = registerMedium(pImage, &pImage,
 
673
                            DeviceType_Floppy,
 
674
                            NULL /* pllRegistriesThatNeedSaving */);
675
675
        if (FAILED(rc)) return rc;
676
676
    }
677
677
 
1616
1616
    if (pMedium.isNull())
1617
1617
    {
1618
1618
        pMedium.createObject();
 
1619
        treeLock.release();
1619
1620
        rc = pMedium->init(this,
1620
1621
                           aLocation,
1621
1622
                           (accessMode == AccessMode_ReadWrite) ? Medium::OpenReadWrite : Medium::OpenReadOnly,
1622
 
                           fForceNewUuid,
 
1623
                           !!fForceNewUuid,
1623
1624
                           deviceType);
 
1625
        treeLock.acquire();
1624
1626
 
1625
1627
        if (SUCCEEDED(rc))
1626
1628
        {
1627
 
            switch (deviceType)
1628
 
            {
1629
 
                case DeviceType_HardDisk:
1630
 
                    rc = registerHardDisk(pMedium, NULL /* pllRegistriesThatNeedSaving */);
1631
 
                break;
1632
 
 
1633
 
                case DeviceType_DVD:
1634
 
                case DeviceType_Floppy:
1635
 
                    rc = registerImage(pMedium,
1636
 
                                       deviceType,
1637
 
                                       NULL /* pllRegistriesThatNeedSaving */);
1638
 
                break;
1639
 
            }
 
1629
            rc = registerMedium(pMedium, &pMedium, deviceType, NULL /* pllRegistriesThatNeedSaving */);
1640
1630
 
1641
1631
            treeLock.release();
1642
1632
 
3133
3123
 * @param aId           UUID to check.
3134
3124
 * @param aLocation     Location to check.
3135
3125
 * @param aConflict     Where to return parameters of the conflicting medium.
 
3126
 * @param ppMedium      Medium reference in case this is simply a duplicate.
3136
3127
 *
3137
3128
 * @note Locks the media tree and media objects for reading.
3138
3129
 */
3139
3130
HRESULT VirtualBox::checkMediaForConflicts(const Guid &aId,
3140
3131
                                           const Utf8Str &aLocation,
3141
3132
                                           Utf8Str &aConflict,
3142
 
                                           bool &fIdentical)
 
3133
                                           ComObjPtr<Medium> *ppMedium)
3143
3134
{
3144
 
    aConflict.setNull();
3145
 
 
3146
3135
    AssertReturn(!aId.isEmpty() && !aLocation.isEmpty(), E_FAIL);
 
3136
    AssertReturn(ppMedium, E_INVALIDARG);
 
3137
 
 
3138
    aConflict.setNull();
 
3139
    ppMedium->setNull();
3147
3140
 
3148
3141
    AutoReadLock alock(getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);
3149
3142
 
3150
3143
    HRESULT rc = S_OK;
3151
3144
 
3152
 
    aConflict.setNull();
3153
 
    fIdentical = false;
3154
 
 
3155
3145
    ComObjPtr<Medium> pMediumFound;
3156
3146
    const char *pcszType = NULL;
3157
3147
 
3187
3177
        if (    (RTPathCompare(strLocFound.c_str(), aLocation.c_str()) == 0)
3188
3178
             && (idFound == aId)
3189
3179
           )
3190
 
            fIdentical = true;
 
3180
            *ppMedium = pMediumFound;
3191
3181
 
3192
3182
        aConflict = Utf8StrFmt(tr("%s '%s' with UUID {%RTuuid}"),
3193
3183
                               pcszType,
3475
3465
}
3476
3466
 
3477
3467
/**
3478
 
 * Remembers the given hard disk by storing it in either the global hard disk registry
3479
 
 * or a machine one.
3480
 
 *
3481
 
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
3482
 
 *
3483
 
 * @param aHardDisk Hard disk object to remember.
3484
 
 * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
 
3468
 * Remembers the given medium object by storing it in either the global
 
3469
 * medium registry or a machine one.
 
3470
 *
 
3471
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
 
3472
 *
 
3473
 * @param pMedium   Medium object to remember.
 
3474
 * @param ppMedium  Actually stored medium object. Can be different if due
 
3475
 *                  to an unavoidable race there was a duplicate Medium object
 
3476
 *                  created.
 
3477
 * @param argType   Either DeviceType_HardDisk, DeviceType_DVD or DeviceType_Floppy.
3485
3478
 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
3486
3479
 * @return
3487
3480
 */
3488
 
HRESULT VirtualBox::registerHardDisk(Medium *pMedium,
3489
 
                                     GuidList *pllRegistriesThatNeedSaving)
 
3481
HRESULT VirtualBox::registerMedium(const ComObjPtr<Medium> &pMedium,
 
3482
                                   ComObjPtr<Medium> *ppMedium,
 
3483
                                   DeviceType_T argType,
 
3484
                                   GuidList *pllRegistriesThatNeedSaving)
3490
3485
{
3491
3486
    AssertReturn(pMedium != NULL, E_INVALIDARG);
 
3487
    AssertReturn(ppMedium != NULL, E_INVALIDARG);
3492
3488
 
3493
3489
    AutoCaller autoCaller(this);
3494
3490
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
3495
3491
 
3496
 
    AutoCaller hardDiskCaller(pMedium);
3497
 
    AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
 
3492
    AutoCaller mediumCaller(pMedium);
 
3493
    AssertComRCReturn(mediumCaller.rc(), mediumCaller.rc());
 
3494
 
 
3495
    const char *pszDevType = NULL;
 
3496
    ObjectsList<Medium> *pall = NULL;
 
3497
    switch (argType)
 
3498
    {
 
3499
        case DeviceType_HardDisk:
 
3500
            pall = &m->allHardDisks;
 
3501
            pszDevType = tr("hard disk");
 
3502
            break;
 
3503
        case DeviceType_DVD:
 
3504
            pszDevType = tr("DVD image");
 
3505
            pall = &m->allDVDImages;
 
3506
            break;
 
3507
        case DeviceType_Floppy:
 
3508
            pszDevType = tr("floppy image");
 
3509
            pall = &m->allFloppyImages;
 
3510
            break;
 
3511
        default:
 
3512
            AssertMsgFailedReturn(("invalid device type %d", argType), E_INVALIDARG);
 
3513
    }
3498
3514
 
3499
3515
    // caller must hold the media tree write lock
3500
3516
    Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
3503
3519
    Utf8Str strLocationFull;
3504
3520
    ComObjPtr<Medium> pParent;
3505
3521
    {
3506
 
        AutoReadLock hardDiskLock(pMedium COMMA_LOCKVAL_SRC_POS);
 
3522
        AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
3507
3523
        id = pMedium->getId();
3508
3524
        strLocationFull = pMedium->getLocationFull();
3509
3525
        pParent = pMedium->getParent();
3512
3528
    HRESULT rc;
3513
3529
 
3514
3530
    Utf8Str strConflict;
3515
 
    bool fIdentical;
 
3531
    ComObjPtr<Medium> pDupMedium;
3516
3532
    rc = checkMediaForConflicts(id,
3517
3533
                                strLocationFull,
3518
3534
                                strConflict,
3519
 
                                fIdentical);
 
3535
                                &pDupMedium);
3520
3536
    if (FAILED(rc)) return rc;
3521
3537
 
3522
 
    if (!fIdentical)
 
3538
    if (pDupMedium.isNull())
3523
3539
    {
3524
3540
        if (strConflict.length())
3525
3541
            return setError(E_INVALIDARG,
3526
 
                            tr("Cannot register the hard disk '%s' {%RTuuid} because a %s already exists"),
 
3542
                            tr("Cannot register the %s '%s' {%RTuuid} because a %s already exists"),
 
3543
                            pszDevType,
3527
3544
                            strLocationFull.c_str(),
3528
3545
                            id.raw(),
3529
3546
                            strConflict.c_str(),
3530
3547
                            m->strSettingsFilePath.c_str());
3531
3548
 
3532
 
        // store base (root) hard disks in the list
 
3549
        // add to the collection if it is a base medium
3533
3550
        if (pParent.isNull())
3534
 
            m->allHardDisks.getList().push_back(pMedium);
3535
 
                    // access the list directly because we already locked the list above
 
3551
            pall->getList().push_back(pMedium);
3536
3552
 
3537
3553
        // store all hard disks (even differencing images) in the map
3538
 
        m->mapHardDisks[id] = pMedium;
 
3554
        if (argType == DeviceType_HardDisk)
 
3555
            m->mapHardDisks[id] = pMedium;
 
3556
 
 
3557
        *ppMedium = pMedium;
3539
3558
 
3540
3559
        if (pllRegistriesThatNeedSaving)
3541
3560
            pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
 
3561
 
 
3562
        *ppMedium = pMedium;
 
3563
    }
 
3564
    else
 
3565
    {
 
3566
        // pMedium may be the last reference to the Medium object, and the
 
3567
        // caller may have specified the same ComObjPtr as the output parameter.
 
3568
        // In this case the assignment will uninit the object, and we must not
 
3569
        // have a caller pending.
 
3570
        mediumCaller.release();
 
3571
        *ppMedium = pDupMedium;
 
3572
 
 
3573
        // no need to update pllRegistriesThatNeedSaving since there must be
 
3574
        // already some saved medium registry which contains the data.
3542
3575
    }
3543
3576
 
3544
3577
    return rc;
3545
3578
}
3546
3579
 
3547
3580
/**
3548
 
 * Removes the given hard disk from the hard disk registry.
3549
 
 *
3550
 
 * @param aHardDisk     Hard disk object to remove.
3551
 
 * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
3552
 
 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
3553
 
 *
3554
 
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a aHardDisk for reading
 
3581
 * Removes the given medium from the respective registry.
 
3582
 *
 
3583
 * @param pMedium   Hard disk object to remove.
 
3584
 * @param pllRegistriesThatNeedSaving Optional pointer to a list of UUIDs of media registries that need saving.
 
3585
 *
 
3586
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a pMedium for reading
3555
3587
 */
3556
 
HRESULT VirtualBox::unregisterHardDisk(Medium *aHardDisk,
3557
 
                                       GuidList *pllRegistriesThatNeedSaving)
 
3588
HRESULT VirtualBox::unregisterMedium(Medium *pMedium,
 
3589
                                     GuidList *pllRegistriesThatNeedSaving)
3558
3590
{
3559
 
    AssertReturn(aHardDisk != NULL, E_INVALIDARG);
 
3591
    AssertReturn(pMedium != NULL, E_INVALIDARG);
3560
3592
 
3561
3593
    AutoCaller autoCaller(this);
3562
3594
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
3563
3595
 
3564
 
    AutoCaller hardDiskCaller(aHardDisk);
3565
 
    AssertComRCReturn(hardDiskCaller.rc(), hardDiskCaller.rc());
 
3596
    AutoCaller mediumCaller(pMedium);
 
3597
    AssertComRCReturn(mediumCaller.rc(), mediumCaller.rc());
3566
3598
 
3567
3599
    // caller must hold the media tree write lock
3568
3600
    Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
3569
3601
 
3570
3602
    Guid id;
3571
3603
    ComObjPtr<Medium> pParent;
3572
 
    {
3573
 
        AutoReadLock hardDiskLock(aHardDisk COMMA_LOCKVAL_SRC_POS);
3574
 
        id = aHardDisk->getId();
3575
 
        pParent = aHardDisk->getParent();
3576
 
    }
3577
 
 
3578
 
    // remove base (root) hard disks from the list
 
3604
    DeviceType_T devType;
 
3605
    {
 
3606
        AutoReadLock mediumLock(pMedium COMMA_LOCKVAL_SRC_POS);
 
3607
        id = pMedium->getId();
 
3608
        pParent = pMedium->getParent();
 
3609
        devType = pMedium->getDeviceType();
 
3610
    }
 
3611
 
 
3612
    ObjectsList<Medium> *pall = NULL;
 
3613
    switch (devType)
 
3614
    {
 
3615
        case DeviceType_HardDisk:
 
3616
            pall = &m->allHardDisks;
 
3617
            break;
 
3618
        case DeviceType_DVD:
 
3619
            pall = &m->allDVDImages;
 
3620
            break;
 
3621
        case DeviceType_Floppy:
 
3622
            pall = &m->allFloppyImages;
 
3623
            break;
 
3624
        default:
 
3625
            AssertMsgFailedReturn(("invalid device type %d", devType), E_INVALIDARG);
 
3626
    }
 
3627
 
 
3628
    // remove from the collection if it is a base medium
3579
3629
    if (pParent.isNull())
3580
 
        m->allHardDisks.getList().remove(aHardDisk);
3581
 
                // access the list directly because caller must have locked the list
 
3630
        pall->getList().remove(pMedium);
3582
3631
 
3583
3632
    // remove all hard disks (even differencing images) from map
3584
 
    size_t cnt = m->mapHardDisks.erase(id);
3585
 
    Assert(cnt == 1);
3586
 
    NOREF(cnt);
 
3633
    if (devType == DeviceType_HardDisk)
 
3634
    {
 
3635
        size_t cnt = m->mapHardDisks.erase(id);
 
3636
        Assert(cnt == 1);
 
3637
        NOREF(cnt);
 
3638
    }
3587
3639
 
3588
3640
    if (pllRegistriesThatNeedSaving)
3589
 
        aHardDisk->addToRegistryIDList(*pllRegistriesThatNeedSaving);
 
3641
        pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
3590
3642
 
3591
3643
    return S_OK;
3592
3644
}
3593
3645
 
3594
3646
/**
3595
 
 * Remembers the given image by storing it in the CD/DVD or floppy image registry.
3596
 
 *
3597
 
 * @param argImage      Image object to remember.
3598
 
 * @param argType       Either DeviceType_DVD or DeviceType_Floppy.
3599
 
 * @param uuidMachineRegistry UUID of machine whose registry should be used, or a NULL UUID for the global registry.
3600
 
 *
3601
 
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
3602
 
 */
3603
 
HRESULT VirtualBox::registerImage(Medium *pMedium,
3604
 
                                  DeviceType_T argType,
3605
 
                                  GuidList *pllRegistriesThatNeedSaving)
3606
 
{
3607
 
    AssertReturn(pMedium != NULL, E_INVALIDARG);
3608
 
 
3609
 
    AutoCaller autoCaller(this);
3610
 
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
3611
 
 
3612
 
    AutoCaller imageCaller(pMedium);
3613
 
    AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
3614
 
 
3615
 
    // caller must hold the media tree write lock
3616
 
    Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
3617
 
 
3618
 
    Guid id;
3619
 
    Utf8Str strLocationFull;
3620
 
    ComObjPtr<Medium> pParent;
3621
 
    {
3622
 
        AutoReadLock al(pMedium COMMA_LOCKVAL_SRC_POS);
3623
 
        id = pMedium->getId();
3624
 
        strLocationFull = pMedium->getLocationFull();
3625
 
        pParent = pMedium->getParent();
3626
 
    }
3627
 
 
3628
 
    // work on DVDs or floppies list?
3629
 
    ObjectsList<Medium> &all = (argType == DeviceType_DVD) ? m->allDVDImages : m->allFloppyImages;
3630
 
 
3631
 
    HRESULT rc;
3632
 
    // lock the images lists (list + map) while checking for conflicts
3633
 
    AutoWriteLock al(all.getLockHandle() COMMA_LOCKVAL_SRC_POS);
3634
 
 
3635
 
    Utf8Str strConflict;
3636
 
    bool fIdentical;
3637
 
    rc = checkMediaForConflicts(id,
3638
 
                                strLocationFull,
3639
 
                                strConflict,
3640
 
                                fIdentical);
3641
 
    if (FAILED(rc)) return rc;
3642
 
 
3643
 
    if (!fIdentical)
3644
 
    {
3645
 
        if (strConflict.length())
3646
 
            return setError(VBOX_E_INVALID_OBJECT_STATE,
3647
 
                            tr("Cannot register the image '%s' with UUID {%RTuuid} because a %s already exists"),
3648
 
                            strLocationFull.c_str(),
3649
 
                            id.raw(),
3650
 
                            strConflict.c_str());
3651
 
 
3652
 
        // add to the collection
3653
 
        all.getList().push_back(pMedium);
3654
 
                // access the list directly because we already locked the list above
3655
 
 
3656
 
        if (pllRegistriesThatNeedSaving)
3657
 
            pMedium->addToRegistryIDList(*pllRegistriesThatNeedSaving);
3658
 
    }
3659
 
 
3660
 
    return rc;
3661
 
}
3662
 
 
3663
 
/**
3664
 
 * Removes the given image from the CD/DVD or floppy image registry.
3665
 
 *
3666
 
 * @param argImage        Image object to remove.
3667
 
 * @param argType         Either DeviceType_DVD or DeviceType_Floppy.
3668
 
 * @param pfNeedsGlobalSaveSettings Optional pointer to a bool that must have been initialized to false and that will be set to true
3669
 
 *                by this function if the caller should invoke VirtualBox::saveSettings() because the global settings have changed.
3670
 
 *
3671
 
 * @note Caller must hold the media tree lock for writing; in addition, this locks @a argImage for reading
3672
 
 */
3673
 
HRESULT VirtualBox::unregisterImage(Medium *argImage,
3674
 
                                    DeviceType_T argType,
3675
 
                                    GuidList *pllRegistriesThatNeedSaving)
3676
 
{
3677
 
    AssertReturn(argImage != NULL, E_INVALIDARG);
3678
 
 
3679
 
    AutoCaller autoCaller(this);
3680
 
    AssertComRCReturn(autoCaller.rc(), autoCaller.rc());
3681
 
 
3682
 
    AutoCaller imageCaller(argImage);
3683
 
    AssertComRCReturn(imageCaller.rc(), imageCaller.rc());
3684
 
 
3685
 
    // caller must hold the media tree write lock
3686
 
    Assert(getMediaTreeLockHandle().isWriteLockOnCurrentThread());
3687
 
 
3688
 
    Guid id;
3689
 
    ComObjPtr<Medium> pParent;
3690
 
    {
3691
 
        AutoReadLock al(argImage COMMA_LOCKVAL_SRC_POS);
3692
 
        id = argImage->getId();
3693
 
        pParent = argImage->getParent();
3694
 
    }
3695
 
 
3696
 
    // work on DVDs or floppies list?
3697
 
    ObjectsList<Medium> &all = (argType == DeviceType_DVD) ? m->allDVDImages : m->allFloppyImages;
3698
 
 
3699
 
    // access the list directly because the caller must have requested the lock
3700
 
    all.getList().remove(argImage);
3701
 
 
3702
 
    HRESULT rc = S_OK;
3703
 
 
3704
 
    if (pllRegistriesThatNeedSaving)
3705
 
        argImage->addToRegistryIDList(*pllRegistriesThatNeedSaving);
3706
 
 
3707
 
    return rc;
3708
 
}
3709
 
 
3710
 
/**
3711
3647
 * Little helper called from unregisterMachineMedia() to recursively add media to the given list,
3712
3648
 * with children appearing before their parents.
3713
3649
 * @param llMedia
3777
3713
        ComObjPtr<Medium> pMedium = *it;
3778
3714
        Log(("Closing medium %RTuuid\n", pMedium->getId().raw()));
3779
3715
        AutoCaller mac(pMedium);
3780
 
        pMedium->close(NULL /* pfNeedsGlobalSaveSettings*/, mac);
 
3716
        pMedium->close(NULL /* pllRegistriesThatNeedSaving */, mac);
3781
3717
    }
3782
3718
 
3783
3719
    LogFlowFuncLeave();
3884
3820
 * hold any locks before calling this.
3885
3821
 *
3886
3822
 * @param llRegistriesThatNeedSaving
3887
 
 * @return
3888
3823
 */
3889
 
HRESULT VirtualBox::saveRegistries(const GuidList &llRegistriesThatNeedSaving)
 
3824
void VirtualBox::saveRegistries(const GuidList &llRegistriesThatNeedSaving)
3890
3825
{
3891
3826
    bool fNeedsGlobalSettings = false;
3892
3827
    HRESULT rc = S_OK;
3910
3845
            if (SUCCEEDED(rc))
3911
3846
            {
3912
3847
                AutoCaller autoCaller(pMachine);
3913
 
                if (FAILED(autoCaller.rc())) return autoCaller.rc();
 
3848
                if (FAILED(autoCaller.rc())) continue;
3914
3849
                AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
3915
3850
                rc = pMachine->saveSettings(&fNeedsGlobalSettings,
3916
3851
                                            Machine::SaveS_Force);           // caller said save, so stop arguing
3917
3852
            }
3918
3853
 
3919
 
            if (FAILED(rc))
3920
 
                return rc;
 
3854
            // There are inherent races (the VM where the media registry was
 
3855
            // when the list was created has been deleted in the mean time),
 
3856
            // so do not thread a failure at findMachine as fatal. Likewise
 
3857
            // saveSettings can fail if the machine has been uninitialized.
3921
3858
        }
3922
3859
    }
3923
3860
 
3926
3863
        AutoWriteLock vlock(this COMMA_LOCKVAL_SRC_POS);
3927
3864
        rc = saveSettings();
3928
3865
    }
3929
 
 
3930
 
    return S_OK;
3931
3866
}
3932
3867
 
3933
3868
/**
4067
4002
 
4068
4003
#if defined(RT_OS_WINDOWS)
4069
4004
 
4070
 
    HRESULT hrc;
4071
 
 
4072
4005
    /// @todo (dmik) processes reaping!
4073
4006
 
4074
4007
    HANDLE handles[MAXIMUM_WAIT_OBJECTS];