コード例 #1
0
TEST(LockManager, CancelWaitingConversionStrongModes) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));

    MMAPV1LockerImpl locker1;
    MMAPV1LockerImpl locker2;

    LockRequestCombo request1(&locker1);
    LockRequestCombo request2(&locker2);

    // First request granted right away
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S));
    ASSERT(request1.numNotifies == 0);

    // Second request is granted right away
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S));
    ASSERT(request2.numNotifies == 0);

    // Convert second request to conflicting
    ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request2, MODE_X));
    ASSERT(request2.mode == MODE_S);
    ASSERT(request2.convertMode == MODE_X);
    ASSERT(request2.numNotifies == 0);

    // Cancel the conflicting upgrade
    lockMgr.unlock(&request2);
    ASSERT(request2.mode == MODE_S);
    ASSERT(request2.convertMode == MODE_NONE);
    ASSERT(request2.numNotifies == 0);

    // Free the remaining locks so the LockManager destructor does not complain
    lockMgr.unlock(&request1);
    lockMgr.unlock(&request2);
}
コード例 #2
0
TEST(LockManager, ConflictingConversion) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));

    MMAPV1LockerImpl locker1;
    MMAPV1LockerImpl locker2;

    LockRequestCombo request1(&locker1);
    LockRequestCombo request2(&locker2);

    // The S requests are granted right away
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S));
    ASSERT(request1.numNotifies == 0);

    ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S));
    ASSERT(request2.numNotifies == 0);

    // Convert first request to conflicting
    ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request1, MODE_X));
    ASSERT(request1.numNotifies == 0);

    // Free the second lock and make sure the first is granted
    lockMgr.unlock(&request2);
    ASSERT(request1.mode == MODE_X);
    ASSERT(request1.numNotifies == 1);
    ASSERT(request2.numNotifies == 0);

    // Frees the first reference, mode remains X
    lockMgr.unlock(&request1);
    ASSERT(request1.mode == MODE_X);
    ASSERT(request1.recursiveCount == 1);

    lockMgr.unlock(&request1);
}
コード例 #3
0
QList<Account*>* ConnectionManager::GetAccountList(bool refresh) throw (const char*, QString)
{
    if (accountList != NULL && refresh)
    {
       accountList = NULL;
       groupList = NULL;
    }
    else if(accountList != NULL && !refresh)
    {
        return accountList;
    }

    QNetworkRequest request(QUrl(getCS(ConnectionManager::AccountList)));
    QNetworkReply *accountListReply = netManager->get(request);

    QEventLoop eventLoop;
    connect(accountListReply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
    eventLoop.exec();

    QString reply = QString::fromUtf8(accountListReply->readAll());

    delete accountListReply;

    QString result = getResult(reply);

    try
    {
        AccountListParser accountListParser(result);

        accountList = accountListParser.parse<Account>();
        groupList = accountListParser.parse<Group>();

        QNetworkRequest request2(QUrl(getCS(ConnectionManager::BalanceList)));
        QNetworkReply *balanceListReply = netManager->get(request2);

        QEventLoop eventLoop2;
        connect(balanceListReply, SIGNAL(finished()), &eventLoop2, SLOT(quit()));
        eventLoop2.exec();

        QString reply2 = QString::fromUtf8(balanceListReply->readAll());

        delete balanceListReply;

        QString result2 = getResult(reply2);

        BalanceListParser balanceListParser(result2);

        balanceListParser.parse(accountList);

        return accountList;
    }
    catch (const char* message)
    {
        throw message;
    }
    catch (QString message)
    {
        throw message;
    }
}
コード例 #4
0
void UT_CNATTraversalPendingRequest::TestL()
    {
    TUint32 requestId1 = 1;

    TNATTraversalPendingRequest request1(requestId1,this,*this);
    EUNIT_ASSERT(requestId1 == request1.RequestId());

    request1.CompleteRequest();
    EUNIT_ASSERT(iLastRequestId == request1.RequestId());

    iLastRequestId = 0;
    TNATTraversalPendingRequest::TimerExpired(&request1);
    EUNIT_ASSERT(iLastRequestId == request1.RequestId());
    EUNIT_ASSERT(iRequestCompletedCalled);

    TUint32 requestId2 = 2;
    TNATTraversalPendingRequest request2(requestId2,NULL,*this);
    // observer NULL
    iLastRequestId = 0;
    request2.CompleteRequest();
    EUNIT_ASSERT(0 == iLastRequestId);
    // compare
    EUNIT_ASSERT(-1 ==
        TNATTraversalPendingRequest::RequestOrder(request1,request2));
    EUNIT_ASSERT(1 ==
        TNATTraversalPendingRequest::RequestOrder(request2,request1));
    EUNIT_ASSERT(0 ==
        TNATTraversalPendingRequest::RequestOrder(request1,request1));
    }
コード例 #5
0
TEST(LockManager, CompatibleFirstImmediateGrant) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_GLOBAL, 0);

    MMAPV1LockerImpl locker1;
    LockRequestCombo request1(&locker1);

    MMAPV1LockerImpl locker2;
    LockRequestCombo request2(&locker2);
    request2.compatibleFirst = true;

    MMAPV1LockerImpl locker3;
    LockRequestCombo request3(&locker3);

    // Lock all in IS mode
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_IS));
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_IS));
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request3, MODE_IS));

    // Now an exclusive mode comes, which would block
    MMAPV1LockerImpl lockerX;
    LockRequestCombo requestX(&lockerX);

    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestX, MODE_X));

    // If an S comes, it should be granted, because of request2
    {
        MMAPV1LockerImpl lockerS;
        LockRequestCombo requestS(&lockerS);
        ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S));
        ASSERT(lockMgr.unlock(&requestS));
    }

    // If request1 goes away, the policy should still be compatible-first, because of request2
    ASSERT(lockMgr.unlock(&request1));

    // If S comes again, it should be granted, because of request2 still there
    {
        MMAPV1LockerImpl lockerS;
        LockRequestCombo requestS(&lockerS);
        ASSERT(LOCK_OK == lockMgr.lock(resId, &requestS, MODE_S));
        ASSERT(lockMgr.unlock(&requestS));
    }

    // With request2 gone the policy should go back to FIFO, even though request3 is active
    ASSERT(lockMgr.unlock(&request2));

    {
        MMAPV1LockerImpl lockerS;
        LockRequestCombo requestS(&lockerS);
        ASSERT(LOCK_WAITING == lockMgr.lock(resId, &requestS, MODE_S));
        ASSERT(lockMgr.unlock(&requestS));
    }

    // Unlock request3 to keep the lock mgr not assert for leaked locks
    ASSERT(lockMgr.unlock(&request3));
    ASSERT(lockMgr.unlock(&requestX));
}
コード例 #6
0
TEST_F(ResourceFetcherTest, RevalidateDeferedResourceFromTwoInitiators) {
    KURL url(ParsedURLString, "http://127.0.0.1:8000/font.woff");
    ResourceResponse response;
    response.setURL(url);
    response.setHTTPStatusCode(200);
    response.setHTTPHeaderField(HTTPNames::ETag, "1234567890");
    Platform::current()->getURLLoaderMockFactory()->registerURL(
        url, WrappedResourceResponse(response), "");

    ResourceFetcherTestMockFetchContext* context =
        ResourceFetcherTestMockFetchContext::create();
    ResourceFetcher* fetcher = ResourceFetcher::create(context);

    // Fetch to cache a resource.
    ResourceRequest request1(url);
    FetchRequest fetchRequest1 = FetchRequest(request1, FetchInitiatorInfo());
    Resource* resource1 = FontResource::fetch(fetchRequest1, fetcher);
    ASSERT_TRUE(resource1);
    fetcher->startLoad(resource1);
    Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests();
    EXPECT_TRUE(resource1->isLoaded());
    EXPECT_FALSE(resource1->errorOccurred());

    // Set the context as it is on reloads.
    context->setLoadComplete(true);
    context->setCachePolicy(CachePolicyRevalidate);

    // Revalidate the resource.
    ResourceRequest request2(url);
    FetchRequest fetchRequest2 = FetchRequest(request2, FetchInitiatorInfo());
    Resource* resource2 = FontResource::fetch(fetchRequest2, fetcher);
    ASSERT_TRUE(resource2);
    EXPECT_EQ(resource1, resource2);
    EXPECT_TRUE(resource2->isCacheValidator());
    EXPECT_TRUE(resource2->stillNeedsLoad());

    // Fetch the same resource again before actual load operation starts.
    ResourceRequest request3(url);
    FetchRequest fetchRequest3 = FetchRequest(request3, FetchInitiatorInfo());
    Resource* resource3 = FontResource::fetch(fetchRequest3, fetcher);
    ASSERT_TRUE(resource3);
    EXPECT_EQ(resource2, resource3);
    EXPECT_TRUE(resource3->isCacheValidator());
    EXPECT_TRUE(resource3->stillNeedsLoad());

    // startLoad() can be called from any initiator. Here, call it from the
    // latter.
    fetcher->startLoad(resource3);
    Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests();
    EXPECT_TRUE(resource3->isLoaded());
    EXPECT_FALSE(resource3->errorOccurred());
    EXPECT_TRUE(resource2->isLoaded());
    EXPECT_FALSE(resource2->errorOccurred());

    memoryCache()->remove(resource1);
}
コード例 #7
0
TEST_F(CachingCorrectnessTest, PostToSameURLTwice)
{
    ResourceRequest request1(KURL(ParsedURLString, kResourceURL));
    request1.setHTTPMethod(HTTPNames::POST);
    ResourcePtr<Resource> resource1 = new Resource(ResourceRequest(request1.url()), Resource::Raw);
    resource1->setLoading(true);
    memoryCache()->add(resource1.get());

    ResourceRequest request2(KURL(ParsedURLString, kResourceURL));
    request2.setHTTPMethod(HTTPNames::POST);
    FetchRequest fetch2(request2, FetchInitiatorInfo());
    ResourcePtr<Resource> resource2 = RawResource::fetchSynchronously(fetch2, fetcher());

    EXPECT_EQ(resource2, memoryCache()->resourceForURL(request2.url()));
    EXPECT_NE(resource1, resource2);
}
コード例 #8
0
ファイル: message.cpp プロジェクト: maxim-levy/raiblocks
TEST (message, keepalive_serialization)
{
	rai::keepalive request1;
	std::vector<uint8_t> bytes;
	{
		rai::vectorstream stream (bytes);
		request1.serialize (stream);
	}
	auto error (false);
	rai::bufferstream stream (bytes.data (), bytes.size ());
	rai::message_header header (error, stream);
	ASSERT_FALSE (error);
	rai::keepalive request2 (error, stream, header);
	ASSERT_FALSE (error);
	ASSERT_EQ (request1, request2);
}
コード例 #9
0
TEST(LockManager, ConvertUpgrade) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));

    MMAPV1LockerImpl locker1;
    LockRequestCombo request1(&locker1);
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S));

    MMAPV1LockerImpl locker2;
    LockRequestCombo request2(&locker2);
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request2, MODE_S));

    // Upgrade the S lock to X
    ASSERT(LOCK_WAITING == lockMgr.convert(resId, &request1, MODE_X));

    ASSERT(!lockMgr.unlock(&request1));
    ASSERT(lockMgr.unlock(&request1));

    ASSERT(lockMgr.unlock(&request2));
}
コード例 #10
0
TEST(LockManager, CompatibleFirstGrantAlreadyQueued) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_GLOBAL, 0);

    // This tests the following behavior:
    //   Lock held in X, queue: S IX IS, where S is compatibleFirst.
    //   Once X unlocks both the S and IS requests should proceed.

    MMAPV1LockerImpl locker1;
    LockRequestCombo request1(&locker1);

    MMAPV1LockerImpl locker2;
    LockRequestCombo request2(&locker2);
    request2.compatibleFirst = true;

    MMAPV1LockerImpl locker3;
    LockRequestCombo request3(&locker3);

    MMAPV1LockerImpl locker4;
    LockRequestCombo request4(&locker4);

    // Hold the lock in X and establish the S IX IS queue.
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_X));
    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request2, MODE_S));
    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request3, MODE_IX));
    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request4, MODE_IS));

    // Now unlock, so all readers should be able to proceed, while the IX remains queued.
    ASSERT(lockMgr.unlock(&request1));
    ASSERT(request2.lastResult == LOCK_OK);
    ASSERT(request3.lastResult == LOCK_INVALID);
    ASSERT(request4.lastResult == LOCK_OK);

    // Now unlock the S lock, and the IX succeeds as well.
    ASSERT(lockMgr.unlock(&request2));
    ASSERT(request3.lastResult == LOCK_OK);

    // Unlock remaining
    ASSERT(lockMgr.unlock(&request4));
    ASSERT(lockMgr.unlock(&request3));
}
コード例 #11
0
TEST(LockManager, Downgrade) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));

    MMAPV1LockerImpl locker1;
    LockRequestCombo request1(&locker1);
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_X));

    MMAPV1LockerImpl locker2;
    LockRequestCombo request2(&locker2);
    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request2, MODE_S));

    // Downgrade the X request to S
    lockMgr.downgrade(&request1, MODE_S);

    ASSERT(request2.numNotifies == 1);
    ASSERT(request2.lastResult == LOCK_OK);
    ASSERT(request2.recursiveCount == 1);

    ASSERT(lockMgr.unlock(&request1));
    ASSERT(lockMgr.unlock(&request2));
}
コード例 #12
0
TEST(LockManager, Conflict) {
    LockManager lockMgr;
    const ResourceId resId(RESOURCE_COLLECTION, std::string("TestDB.collection"));

    MMAPV1LockerImpl locker1;
    MMAPV1LockerImpl locker2;

    LockRequestCombo request1(&locker1);
    LockRequestCombo request2(&locker2);

    // First request granted right away
    ASSERT(LOCK_OK == lockMgr.lock(resId, &request1, MODE_S));
    ASSERT(request1.recursiveCount == 1);
    ASSERT(request1.numNotifies == 0);

    // Second request must block
    ASSERT(LOCK_WAITING == lockMgr.lock(resId, &request2, MODE_X));
    ASSERT(request2.mode == MODE_X);
    ASSERT(request2.recursiveCount == 1);
    ASSERT(request2.numNotifies == 0);

    // Release first request
    lockMgr.unlock(&request1);
    ASSERT(request1.recursiveCount == 0);
    ASSERT(request1.numNotifies == 0);

    ASSERT(request2.mode == MODE_X);
    ASSERT(request2.recursiveCount == 1);
    ASSERT(request2.numNotifies == 1);
    ASSERT(request2.lastResult == LOCK_OK);

    // Release second acquire
    lockMgr.unlock(&request2);
    ASSERT(request2.recursiveCount == 0);

    ASSERT(request1.numNotifies == 0);
    ASSERT(request2.numNotifies == 1);
}
コード例 #13
0
void tst_QMediaResource::equality()
{
    QMediaResource resource1(
            QUrl(QString::fromLatin1("http://test.com/test.mp4")),
            QString::fromLatin1("video/mp4"));
    QMediaResource resource2(
            QUrl(QString::fromLatin1("http://test.com/test.mp4")),
            QString::fromLatin1("video/mp4"));
    QMediaResource resource3(
            QUrl(QString::fromLatin1("file:///thumbs/test.jpg")));
    QMediaResource resource4(
            QUrl(QString::fromLatin1("file:///thumbs/test.jpg")));
    QMediaResource resource5(
            QUrl(QString::fromLatin1("http://test.com/test.mp3")),
            QString::fromLatin1("audio/mpeg"));

    QNetworkRequest request(QUrl("http://test.com/test.mp3"));
    QString requestMimeType("audio/mp3");

    QMediaResource requestResource1(request, requestMimeType);
    QMediaResource requestResource2(request, requestMimeType);

    QCOMPARE(requestResource1 == requestResource2, true);
    QCOMPARE(requestResource1 != requestResource2, false);
    QCOMPARE(requestResource1 != resource5, true);

    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    QCOMPARE(resource3 == resource4, true);
    QCOMPARE(resource3 != resource4, false);

    QCOMPARE(resource1 == resource3, false);
    QCOMPARE(resource1 != resource3, true);

    QCOMPARE(resource1 == resource5, false);
    QCOMPARE(resource1 != resource5, true);

    resource1.setAudioCodec(QString::fromLatin1("mp3"));
    resource2.setAudioCodec(QString::fromLatin1("aac"));

    // Not equal differing audio codecs.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource1.setAudioCodec(QString::fromLatin1("aac"));

    // Equal.
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setVideoCodec(QString());

    // Equal.
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setVideoCodec(QString::fromLatin1("h264"));

    // Not equal differing video codecs.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource2.setVideoCodec(QString::fromLatin1("h264"));

    // Equal.
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource2.setDataSize(0);

    // Equal.
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setDataSize(546423);

    // Not equal differing video codecs.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource2.setDataSize(546423);

    // Equal.
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setAudioBitRate(96000);
    resource1.setSampleRate(48000);
    resource2.setSampleRate(44100);
    resource1.setChannelCount(0);
    resource1.setVideoBitRate(900000);
    resource2.setLanguage(QString::fromLatin1("eng"));

    // Not equal, audio bit rate, sample rate, video bit rate, and
    // language.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource2.setAudioBitRate(96000);
    resource1.setSampleRate(44100);

    // Not equal, differing video bit rate, and language.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource2.setVideoBitRate(900000);
    resource1.setLanguage(QString::fromLatin1("eng"));

    // Equal
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setResolution(QSize());

    // Equal
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource2.setResolution(-1, -1);

    // Equal
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    resource1.setResolution(QSize(-640, -480));

    // Not equal, differing resolution.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);
    resource1.setResolution(QSize(640, 480));
    resource2.setResolution(QSize(800, 600));

    // Not equal, differing resolution.
    QCOMPARE(resource1 == resource2, false);
    QCOMPARE(resource1 != resource2, true);

    resource1.setResolution(800, 600);

    // Equal
    QCOMPARE(resource1 == resource2, true);
    QCOMPARE(resource1 != resource2, false);

    /* equality tests for constructor of QMediaresource(QNetworkrequest,mimeType)*/
    QNetworkRequest request2(QUrl(QString::fromLatin1("http://test.com/test.mp4")));
    QUrl url(QString::fromLatin1("http://test.com/test.mp4"));
    QString mimeType(QLatin1String("video/mp4"));

    QMediaResource resource6(request2,mimeType);
    QMediaResource resource7(request2,mimeType);


    QVERIFY(resource6.request()==request2);
    QVERIFY(resource6.mimeType()==mimeType);


    QVERIFY(resource7.request()==request2);
    QVERIFY(resource7.mimeType()==mimeType);

    QVERIFY(resource6.request()==resource7.request());
    QVERIFY(resource6.mimeType()==resource7.mimeType());

    QVERIFY(resource6==resource7);

    /*for copy constructor*/
    QMediaResource resource8(resource7);

    QVERIFY(resource8.request()==request2);
    QVERIFY(resource8.mimeType()==mimeType);


    QVERIFY(resource7.request()==request2);
    QVERIFY(resource7.mimeType()==mimeType);

    QVERIFY(resource8.request()==resource7.request());
    QVERIFY(resource8.mimeType()==resource7.mimeType());


    QVERIFY(resource8==resource7);

    /*for assign constructor*/

    QMediaResource resource9(request2,mimeType);

    QMediaResource resource10=resource9;

    QVERIFY(resource10.request()==request2);
    QVERIFY(resource10.mimeType()==mimeType);


    QVERIFY(resource9.request()==request2);
    QVERIFY(resource9.mimeType()==mimeType);

    QVERIFY(resource8.request()==resource7.request());
    QVERIFY(resource8.mimeType()==resource7.mimeType());

    QVERIFY(resource8==resource7);
}
コード例 #14
0
ファイル: fxusbdeviceum.cpp プロジェクト: AntejaVM/WDF
_Must_inspect_result_
NTSTATUS
FxUsbDevice::InitDevice(
    __in ULONG USBDClientContractVersionForWdfClient
    )
{
    HRESULT hr = S_OK;
    NTSTATUS status = STATUS_SUCCESS;
    
    IWudfDevice* device = NULL;
    IWudfDeviceStack* devstack = NULL;

    UMURB urb;
    USB_CONFIGURATION_DESCRIPTOR config;
    USHORT wTotalLength = 0;

    FxRequestBuffer buf;
    FxUsbDeviceControlContext context(FxUrbTypeLegacy);

    WDF_USB_CONTROL_SETUP_PACKET setupPacket;
    USHORT deviceStatus = 0;
    UCHAR deviceSpeed = 0;

    FxSyncRequest request(GetDriverGlobals(), NULL);
    FxSyncRequest request2(GetDriverGlobals(), &context);
    



    UNREFERENCED_PARAMETER(USBDClientContractVersionForWdfClient);

    status = request.Initialize();
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                            "Failed to initialize FxSyncRequest");
        goto Done;
    }

    status = request2.Initialize();
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                            "Failed to initialize second FxSyncRequest");
        goto Done;
    }

    status = request.m_TrueRequest->ValidateTarget(this);
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                            "Failed to validate FxSyncRequest target");
        goto Done;
    }

    status = request2.m_TrueRequest->ValidateTarget(this);
    if (!NT_SUCCESS(status)) {
        DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
                            "Failed to validate second FxSyncRequest target");
        goto Done;
    }

    RtlZeroMemory(&urb, sizeof(urb));

    device = m_DeviceBase->GetDeviceObject();
    devstack = device->GetDeviceStackInterface();

    if (m_pHostTargetFile == NULL) {
        hr = devstack->CreateWdfFile(device,
                                     device->GetAttachedDevice(),
                                     NULL,
                                     &m_pHostTargetFile);
        if (SUCCEEDED(hr)) {
            m_WinUsbHandle = (WINUSB_INTERFACE_HANDLE)m_pHostTargetFile->GetCreateContext();
        }
    }

    //
    // Get USB device descriptor
    //
    FxUsbUmInitDescriptorUrb(&urb,
                             m_WinUsbHandle,
                             USB_DEVICE_DESCRIPTOR_TYPE,
                             sizeof(m_DeviceDescriptor),
                             &m_DeviceDescriptor);
    FxUsbUmFormatRequest(request.m_TrueRequest,
                         &urb.UmUrbHeader,
                         m_pHostTargetFile,
                         TRUE);
    status = SendSyncRequest(&request, 5);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }

    //
    // Get USB configuration descriptor
    //
    FxUsbUmInitDescriptorUrb(&urb,
                             m_WinUsbHandle,
                             USB_CONFIGURATION_DESCRIPTOR_TYPE,
                             sizeof(config),
                             &config);
    FxUsbUmFormatRequest(request.m_TrueRequest,
                         &urb.UmUrbHeader,
                         m_pHostTargetFile,
                         TRUE);
    status = SendSyncRequest(&request, 5);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }

    if (config.wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) {

        //
        // Not enough info returned
        //
        status = STATUS_UNSUCCESSFUL;
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Could not retrieve config descriptor size, config.wTotalLength %d < "
            "sizeof(config descriptor) (%d), %!STATUS!",
            config.wTotalLength, sizeof(USB_CONFIGURATION_DESCRIPTOR), status);
        goto Done;
    }

    wTotalLength = config.wTotalLength;
    m_ConfigDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)
                             FxPoolAllocate(GetDriverGlobals(),
                                            NonPagedPool,
                                            wTotalLength);
    if (NULL == m_ConfigDescriptor) {
        status = STATUS_INSUFFICIENT_RESOURCES;
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Could not allocate %d bytes for config descriptor, %!STATUS!",
            sizeof(USB_CONFIGURATION_DESCRIPTOR), status);
        goto Done;
    }

    //
    // Get USB configuration descriptor and subsequent interface descriptors, etc.
    //
    FxUsbUmInitDescriptorUrb(&urb,
                             m_WinUsbHandle,
                             USB_CONFIGURATION_DESCRIPTOR_TYPE,
                             wTotalLength,
                             m_ConfigDescriptor);
    FxUsbUmFormatRequest(request.m_TrueRequest,
                         &urb.UmUrbHeader,
                         m_pHostTargetFile,
                         TRUE);
    status = SendSyncRequest(&request, 5);
    if (!NT_SUCCESS(status)) {
        goto Done;
    } else if (m_ConfigDescriptor->wTotalLength != wTotalLength) {
        //
        // Invalid wTotalLength
        //
        status = STATUS_DEVICE_DATA_ERROR;
        DoTraceLevelMessage(
            GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIOTARGET,
            "Defective USB device reported two different config descriptor "
            "wTotalLength values: %d and %d, %!STATUS!",
            wTotalLength, m_ConfigDescriptor->wTotalLength, status);
        goto Done;
    }

    m_NumInterfaces = m_ConfigDescriptor->bNumInterfaces;

    //
    // Check to see if we are wait wake capable
    //
    if (m_ConfigDescriptor->bmAttributes & USB_CONFIG_REMOTE_WAKEUP) {
        m_Traits |= WDF_USB_DEVICE_TRAIT_REMOTE_WAKE_CAPABLE;
    }

    //
    // Get the device status to check if device is self-powered.
    //
    WDF_USB_CONTROL_SETUP_PACKET_INIT_GET_STATUS(&setupPacket,
                                                 BmRequestToDevice,
                                                 0); // Device status

    buf.SetBuffer(&deviceStatus, sizeof(USHORT));
    
    status = FormatControlRequest(request2.m_TrueRequest,
                                  &setupPacket,
                                  &buf);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }
    
    status = SendSyncRequest(&request2, 5);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }

    if (deviceStatus & USB_GETSTATUS_SELF_POWERED) {
        m_Traits |= WDF_USB_DEVICE_TRAIT_SELF_POWERED;
    }

    //
    // Get device speed information.
    //
    FxUsbUmInitInformationUrb(&urb,
                              m_WinUsbHandle,
                              sizeof(UCHAR),
                              &deviceSpeed);
    FxUsbUmFormatRequest(request.m_TrueRequest,
                         &urb.UmUrbHeader,
                         m_pHostTargetFile,
                         TRUE);
    status = SendSyncRequest(&request, 5);
    if (!NT_SUCCESS(status)) {
        goto Done;
    }

    if (deviceSpeed == 3) {
        m_Traits |= WDF_USB_DEVICE_TRAIT_AT_HIGH_SPEED;
    }

    //
    // User-mode events must be initialized manually.
    //
    status = m_InterfaceIterationLock.Initialize();
    if (!NT_SUCCESS(status)) {
        goto Done;
    }

Done:
    return status;
}