为什么我的Qt应用程序在访问IWMPMedia界面时崩溃了?

时间:2017-01-28 13:02:32

标签: c++ multithreading qt com wmp

我构建了一个Qt(5.7)应用程序,它与Windows Media Player COM API连接以解析跟踪元数据。出于某些明确原因,我的应用程序在调用IWMPMedia3::getAttributeCountByType时崩溃。

崩溃持续发生的行是:

if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here

它不会在第一个实例上崩溃,它需要几百个循环,并且当调用重复返回0时似乎连接到它。如果我切换到我知道存在的属性,那么它运行正常。

下面发布的是右后方剥离的对象,但它仍然崩溃。此对象旨在在其自己的QThread中运行,并且所有COM符号都已定义并包含在QThread中。

代码构成了一个更大的应用程序的一部分,它使用了许多其他Qt模块,GUI,Web引擎是最大的两个。

#include "WMPMLImport.h"
#include <QDebug>
#include "Wininet.h"

#define WMP_CLSID        L"{6BF52A52-394A-11d3-B153-00C04F79FAA6}"
#define WMP_REFIID       L"{D84CCA99-CCE2-11d2-9ECC-0000F8085981}"

#define WMP_PL_ALL_MUSIC    L"All Music"

#define SAFE_RELEASE(ptr) if(NULL!=(ptr)){(ptr)->Release();ptr=NULL;}
#define BSTR_RELEASE(bstr) {SysFreeString(bstr);(bstr)=NULL;}

class CCoInitialize
{
public:
    CCoInitialize() :
        m_hr(CoInitialize(NULL))
    {}

    ~CCoInitialize()
    {
        if(SUCCEEDED(m_hr)) {
            qDebug() << "CCoInitialize: DTOR";
            CoUninitialize();
        }
    }

    HRESULT m_hr;
};

/**
 Worker class that will step through the WMP COM interface
 and extact the audio meta data contained within it,
 */
class WMPMLComHandler : public QObject
{
public:
    WMPMLComHandler(WMPMLImport* t) :
        m_thread(t)
    {
        qDebug() << "WMPMLComHandler::CTOR" << QThread::currentThreadId();
    }

    ~WMPMLComHandler()
    {
        qDebug() << "WMPMLComHandler::DTOR" << QThread::currentThreadId();
    }

    /**
     Method responsible for walking through the COM interface and extracting
     all the track and playlist metadata including the artwork.
     @returns Return false if the COM API was not parsed correctly.
     */
    bool parse()
    {
        bool b = true;

        CCoInitialize cCoInit;

        IWMPCore* pIWMPCore = NULL;
        IWMPCore3* pIWMPCore3 = NULL;

        IWMPPlaylistCollection *pPlaylistCollection;
        IWMPPlaylist *pMainLibplaylist;

        CLSID clsID;
        CLSID refID;
        CLSIDFromString(WMP_CLSID, &clsID);
        CLSIDFromString(WMP_REFIID, &refID);

        if(SUCCEEDED(CoCreateInstance(clsID, NULL, CLSCTX_ALL, refID, (void**)&pIWMPCore)))
        {
            if(SUCCEEDED(pIWMPCore->get_playlistCollection(&pPlaylistCollection)))
            {
                if(SUCCEEDED(pIWMPCore->QueryInterface(__uuidof(IWMPCore3), reinterpret_cast<void**>(&pIWMPCore3))))
                {
                    IWMPPlaylistArray* pPlaylistArray = NULL;

                    if(SUCCEEDED(pPlaylistCollection->getAll(&pPlaylistArray)))
                    {
                        long playlistCount = 0;

                        if(SUCCEEDED(pPlaylistArray->get_count(&playlistCount)))
                        {
                            IWMPPlaylist* pPlaylist = NULL;

                            for(int playlistIndex=0; playlistIndex < playlistCount; playlistIndex++)
                            {
                                if (SUCCEEDED(pPlaylistArray->item(playlistIndex, &pPlaylist)))
                                {
                                    long lMediaCount = 0;
                                    if (SUCCEEDED(pPlaylist->get_count(&lMediaCount)))
                                    {
                                        fetchPlaylist(pPlaylist, NULL, playlistIndex, lMediaCount);
                                    }
                                    SAFE_RELEASE(pPlaylist);
                                }
                            }
                        }
                        SAFE_RELEASE(pPlaylistArray);
                    }
                    SAFE_RELEASE(pIWMPCore3);
                }
                SAFE_RELEASE(pPlaylistCollection);
            }
            SAFE_RELEASE(pIWMPCore);
        }
        SAFE_RELEASE(pMainLibplaylist);

        return b;
    }

private:

    void fetchPlaylist(IWMPPlaylist* pPlaylist, BSTR bstrName, unsigned int playlistIndex, long count)
    {
        //get the playlist items
        for(long mediaIndex=0; mediaIndex<count-1; mediaIndex++)
        {
            IWMPMedia* pMediaItem = NULL;

            if(SUCCEEDED(pPlaylist->get_item(mediaIndex, &pMediaItem)))
            {
                IWMPMedia3 *pMedia3Item = NULL;

                if (pMediaItem->QueryInterface(__uuidof(IWMPMedia3), reinterpret_cast<void **>(&pMedia3Item)) == S_OK)
                {
                    long l = 0;

                    qDebug() << "About to call method for" << mediaIndex << "time";

                    if (pMedia3Item && pMedia3Item->getAttributeCountByType(L"TrackingID", 0, &l) == S_OK) //Will eventually crash here
                    {
                        qDebug() << "Exited method for" << mediaIndex << "time";
                    }
                }

                SAFE_RELEASE(pMedia3Item);
                SAFE_RELEASE(pMediaItem);
           }
        }
        qDebug() << "*********COMPLETE*********";
    }

    WMPMLImport* m_thread;
};

//==

WMPMLImport::WMPMLImport() :
    m_comHandler(NULL)
{
    qDebug() << "WMPMLImporter CTOR" << QThread::currentThreadId();
}

WMPMLImport::~WMPMLImport()
{
}

/**
 Reimplemented function that runs the function contents in a new thread context.
 The parsing of the COM is all ran through this thread. Returning out of this
 thread will end its execution.
 */
void WMPMLImport::run()
{
    QMutexLocker g(&m_lock);

    m_comHandler = new WMPMLComHandler(this);

    g.unlock();
    bool parseOk = m_comHandler->parse();
    g.relock();

    delete m_comHandler;
    m_comHandler = NULL;
}

0 个答案:

没有答案