I need help for this issue. i want to uses WMI in my project, so that i can use WQL to get some data fom Windows OS. Here is my code
QList<Drive> SystemDrive::getSystemDrive()
{
QList<Drive> list;
#ifdef _WIN64
HRESULT hRes;
hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED );
if(hRes == RPC_E_CHANGED_MODE)
{
//qDebug() << "Unable to launch COM: 0x" << QString::number(hRes, 16) << endl;
//OleUninitialize();
CoUninitialize();
hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hRes))
{
qDebug() << "Unable to launch COM: 0x" << QString::number(hRes, 16);
}
//return 1;
}
qDebug() << "CoInitializeEx result 0x" << QString::number(hRes, 16);
if((FAILED(hRes = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0))))
{
qDebug() << "Unable to initialize security: 0x" << QString::number(hRes, 16);
}
IWbemLocator* pLocator = NULL;
if(FAILED(hRes = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pLocator))))
{
qDebug() << "Unable to create a WbemLocator: " << std::hex << hRes << endl;
//return 1;
}
IWbemServices* pService = NULL;
if(FAILED(hRes = pLocator->ConnectServer(L"root\\CIMV2", NULL, NULL, NULL, WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pService)))
{
pLocator->Release();
qDebug() << "Unable to connect to \"CIMV2\": " << std::hex << hRes << endl;
//return 1;
}
IEnumWbemClassObject* pEnumerator = NULL;
if(FAILED(hRes = pService->ExecQuery(L"WQL", L"SELECT * FROM Win32_LogicalDisk", WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator)))
{
pLocator->Release();
pService->Release();
qDebug() << "Unable to retrive Logical Disk: " << QString::number(hRes, 16) << endl;
//return 1;
}
IWbemClassObject* clsObj = NULL;
int numElems;
while((hRes = pEnumerator->Next(WBEM_INFINITE, 1, &clsObj, (ULONG*)&numElems)) != WBEM_S_FALSE)
{
if(FAILED(hRes))
break;
Drive *tmpDrive;
VARIANT vRet;
VariantInit(&vRet);
if(SUCCEEDED(clsObj->Get(L"Caption", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR)
{
tmpDrive = new Drive(QString((QChar*) vRet.bstrVal, SysStringLen(vRet.bstrVal)));
tmpDrive->setType(Drive::DRIVE_TYPE::DRIVE_LOGICAL);
VariantClear(&vRet);
}
VariantInit(&vRet);
if(SUCCEEDED(clsObj->Get(L"DeviceID", 0, &vRet, NULL, NULL)) && vRet.vt == VT_BSTR)
{
QString id = "\\\\.\\";
id.append(QString((QChar*) vRet.bstrVal, SysStringLen(vRet.bstrVal)));
tmpDrive->setId(id);
VariantClear(&vRet);
}
clsObj->Release();
list.append(*tmpDrive);
}
pEnumerator->Release();
pService->Release();
pLocator->Release();
CoUninitialize();
#endif
return list;
}
that code run perfectly every time i call it. I can get what i need (List of Logical drive). The problem is when i call QFileDialog
object and then call that function, that code will not work. I get error for coInitializeSecurity
with error RPC_E_TOO_LATE
and as result my ExecQuery
will fail with error code 0x80041003
(WBEM_E_ACCESS_DENIED).
I think QFileDialog
create COM object because there is mesage output in Aplication Output Tab
(stdout) when I call QFileDialog
object.
CoCreateInstance failed ()
CoCreateInstance failed ()
If I Call QFileDialog
object first before that function, these message will not occur, and that function still not work. I need that function run normally without any interuption from any COM objects.
My questions :
Are there any way to detect what COM object that created by QT?
How can I know which security that initialized (CoInitializeSecurity) by QT?
EDITED
After read answers from Hans and Daniel, I change my code. So I put CoInitializeEx
in first time my app running with COINIT_APARTMENTTHREADED
, after that I initialize CoInitializeSecurity
, and then erase all CoInitializeEx
, CoInitializeSecurity
, and 'CoUninitialize' in that function. It works, i can call that function after opening QFileDialog
.
Now,
WMI
and QFileDialog
) destroyed properly? asume that I release all interface and enumeration from WMI like in my code, and for QFileDialog
I call it in stack memory.CoInitializeSecurity
should be called only once for a process. RPC_E_TOO_LATE
means that it has already been called. Move call earlier, probably into initialization section of your process.
User contributions licensed under CC BY-SA 3.0