ISearchJob->Release() stucking - c++

I'm using wuapi to find Windows Updates. I faced with the problem: pJob->Release(); stucking in the following code on some machines, but generally it works correct. What could be the reason of such behavior?
I have tried to change ISearchJob* to CComPtr and remove pJob->Release();, but issue isn't gone. In this case program stucks on the end of the function.
ISearchResult* pWUResult = NULL;
ISearchJob* pJob = NULL;
VARIANT pVar = { 0 };
ISCC completeCB;
hr = pWUSearcher->BeginSearch( bstrCriteria, &completeCB, pVar, &pJob );
if ( SUCCEEDED(hr) )
{
WaitForSingleObject( completeCB._Event, INFINITE );
hr = pWUSearcher->EndSearch( pJob, &pWUResult );
pJob->Release();
}

As #JonathanPotter suggested in comments, using pJob->CleanUp() instead of pJob->Release() was resolved the issue.

Related

Storport Virtual Miniport Driver stopping on AdapterControl

Why my StorPort Virtual Miniport Driver (KMDF) stops working after it's AdapterControl function is first called?
Currently, the following is happening after the driver is implemented (WinDbg):
DriverEntry is called. No errors.
HwFindAdapter is called. No errors.
HwInitialize is called. No errors.
HwStartIo is called. No errors. Parameter PSCSI_REQUEST_BLOCK ("SRB") -> Function is SRB_FUNCTION_STORAGE_REQUEST_BLOCK (this is OK for me because in the HwFindAdapter routine, I defined PPORT_CONFIGURATION_INFORMATION -> SrbType to equal SRB_TYPE_STORAGE_REQUEST_BLOCK).
AdapterControl is called. No errors. Parameter SCSI_ADAPTER_CONTROL_TYPE is called with ControlType ScsiQuerySupportedControlTypes (as is default behavior according to MS documentation for the first call).
And that's it. No more calls, and I couldn't find anything related in EventLog. As far as I know, at this point the StorPort sould make another call to my driver's AdapterControl routine and "ask" me to define a device.
--
Please note that the following is not the actual full code, but rather a structural overview:
DriverEntry (
_In_ PVOID DriverObject,
_In_ PVOID RegistryPath
)
{
HW_INITIALIZATION_DATA initdata = { 0 }
initdata.HwFindAdapter = HwFindAdapter;
initdata.HwInitialize = HwInitialize;
initdata.HwAdapterControl = AdapterControl;
initdata.HwResetBus = HwResetBus;
initdata.HwStartIo = HwStartIo;
initdata.HwFreeAdapterResources = HwFreeAdapterResources;
initdata.AdapterInterfaceType = Internal;
initdata.MultipleRequestPerLu = TRUE;
initdata.PortVersionFlags = 0;
status = StorPortInitialize(
DriverObject,
RegistryPath,
&initdata,
NULL
);
return status;
}
|
HwFindAdapter (AdapterExtension, HwContext, BusInformation, ArgumentString, ConfigInfo, Reserved3)
{
//ConfigInfo is referenced to PPORT_CONFIGURATION_INFORMATION in the parameters above.
ConfigInfo->AlignmentMask = FILE_BYTE_ALIGNMENT;
ConfigInfo->NumberOfBuses = 1
ConfigInfo->CachesData = FALSE;
ConfigInfo->MapBuffers = STOR_MAP_ALL_BUFFERS_INCLUDING_READ_WRITE;
ConfigInfo->MaximumNumberOfTargets = 255;
ConfigInfo->SrbType = SRB_TYPE_STORAGE_REQUEST_BLOCK;
ConfigInfo->AddressType = STORAGE_ADDRESS_TYPE_BTL8;
ConfigInfo->SynchronizationModel = StorSynchronizeFullDuplex;
ConfigInfo->HwMSInterruptRoutine = NULL;
ConfigInfo->InterruptSynchronizationMode = InterruptSupportNone;
ConfigInfo->VirtualDevice = TRUE;
ConfigInfo->DumpMode = DUMP_MODE_RESUME;
ConfigInfo->MaxNumberOfIO = 100;
ConfigInfo->BusResetHoldTime = 0;
ConfigInfo->FeatureSupport = 0x7f;
return SP_RETURN_FOUND;
}
HwInitialize is there but does nothing except returning STATUS_SUCCESS.
|
HwStartIo (
_In_ PVOID DeviceExtension,
_In_ PSCSI_REQUEST_BLOCK Srb
)
{
//Currently does nothing with data, as is not needed for now.
StorPortNotification(RequestComplete, DeviceExtension, Srb);
return TRUE;
}
|
AdapterControl (
_In_ PVOID DeviceExtension,
_In_ SCSI_ADAPTER_CONTROL_TYPE ControlType,
_In_ PVOID Parameters
)
{
PSCSI_SUPPORTED_CONTROL_TYPE_LIST controlTypeList;
switch (ControlType)
{
case ScsiQuerySupportedControlTypes:
controlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters; // get pointer to control type list
controlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
controlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
controlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
controlTypeList->SupportedTypeList[ScsiSetBootConfig] = TRUE;
//referenced cases are defined but not relevant for now.
}
return ScsiAdapterControlSuccess;
}
HwFreeAdapterResources is there but does nothing, and returns nothing because it is a VOID.
OK, so I found out what was wrong.
HwStartIo was called, but with value PSCSI_REQUEST_BLOCK->Function == "SRB_FUNCTION_PNP".
This indicates an error on any function called beforehand, in my case I had a wrong return code set (Function HwInitialize: I returned "STATUS_SUCCESS" (0xL) instead of "TRUE" (0x0).)
In normal operation, upon first initialization, PSCSI_REQUEST_BLOCK->Function should equal "SRB_FUNCTION_EXECUTE_SCSI" to gather SCSI Bus-, Target- and LUN information.

Opening a directory automatically after creating with CreateDirectory [duplicate]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I need to open an explorer window showing a specific folder, lets say "C:\\Windows" What function should I use to reach my goal? I'm using Windows so can use API, also I can use boost, but I can't use C++11.
You can use the SHOpenFolderAndSelectItems function to do this, rather than forcibly running Explorer yourself (what if the user has replaced Explorer as their default file manager, for example?).
LPCWSTR pszPathToOpen = L"C:\\Windows";
PIDLIST_ABSOLUTE pidl;
if (SUCCEEDED(SHParseDisplayName(pszPathToOpen, 0, &pidl, 0, 0)))
{
// we don't want to actually select anything in the folder, so we pass an empty
// PIDL in the array. if you want to select one or more items in the opened
// folder you'd need to build the PIDL array appropriately
ITEMIDLIST idNull = { 0 };
LPCITEMIDLIST pidlNull[1] = { &idNull };
SHOpenFolderAndSelectItems(pidl, 1, pidlNull, 0);
ILFree(pidl);
}
Alternatively, you can call ShellExecute on the folder directly to run its default action (which is normally to open in a browser window):
ShellExecute(NULL, NULL, L"C:\\Windows", NULL, NULL, SW_SHOWNORMAL);
An hour ago I just wrote similar function.
This function doesn't do 100% as you want, but you can use it to get that you want.
It opens explorer window and marks file you are pointing to. Lets say you specified "C:\Windows\System32" in this case you will have "C:\Windows" opened and System32 marked. If you want to go inside you need to use something like FindFirstFile. If directory is empty, my offered solution wouldn't work...
bool ExplorerGoTo (const String &Path)
{
TCHAR tcBuff[8] = {0};
lstrcpyn(tcBuff, Path.c_str(), 5);
String stParams = _T("/n, /select, ");
if( lstrcmpi(_T("\\??\\"), tcBuff) == 0 )
{
stParams += (Path[4]);
}
else
{
stParams += Path;
}
String stExplorer = _T("C:\\Windows\\explorer.exe");
//ExpandPath(stExplorer);
if (stExplorer.empty ()) stExplorer = _T("explorer.exe");
SHELLEXECUTEINFO shi = { 0 };
shi.cbSize = sizeof (SHELLEXECUTEINFO);
shi.lpVerb = _T("open");
shi.lpFile = stExplorer.c_str ();
shi.lpParameters = stParams.c_str ();
shi.nShow = SW_SHOW;
bool bRes = ShellExecuteEx( &shi );
if( bRes == FALSE && GetLastError() != 0 )
{
Sleep(200);
return ShellExecuteEx( &shi );
}
return bRes;
}
And never use system()

don't know how to use IShellWindows::Item correctly

I'm using VC6 on XP system.
The following is my code. It runs perfectly on my computer, but on other computers it seems that pisw->Item(v, &pidisp) doesn't equals to S_OK. Now I'm trying to figure out what's wrong here
IShellWindows *pisw;
if (SUCCEEDED(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL,
IID_IShellWindows, (void**)&pisw))) {
VARIANT v;
V_VT(&v) = VT_I4;
IDispatch *pidisp;
found = FALSE;
for (V_I4(&v) = 0; !found && pisw->Item(v, &pidisp) == S_OK; V_I4(&v)++) {
IWebBrowserApp *piwba;
if (SUCCEEDED(pidisp->QueryInterface(IID_IWebBrowserApp, (void**)&piwba))) {
// blablabla....do something..
}
So I changed some code to
...
IDispatch *pidisp;
hr = pisw->Item(v, &pidisp);
if (SUCCEEDED(hr))
{
for (V_I4(&v) = 0; !found ; V_I4(&v)++) {
IWebBrowserApp *piwba;
if (SUCCEEDED(pidisp->QueryInterface(IID_IWebBrowserApp, (void**)&piwba))) {
// blablabla....do something..
}
}
then the return value of hr becomes to 1. And it gets access violation errors when running to "pidisp->.." step. Can anyone help me?
The original code incorrectly tests the result of pisw->Item(v, &pidisp). Weird, because it does use the correct check later on.
The problem is that there are many success return values besides S_OK. Your fix is correct, you should use SUCCEEDED(hr), but you incorrectly moved the loop INSIDE the SUCCEEDED(hr) test. You should check SUCCEEDED(hr) for every value of V_I4(&v).
Your S_FALSE result is because you now call hr = pisw->Item(v, &pidisp); before the loop, which means v is uninitialized (garbage). Assume for a moment that its garbage value is 728365. S_FALSE means: the call succeeded, but there are less than 728365 windows.
MSDN IShellWindows::Item:
Return value Type: HRESULT S_FALSE (1) The specified window was not
found.
The item you are looking was not found, and you obviously don't get a valid pidisp. Trying to use it results - expectedly - in access violation.
You need to handle "item not found" case properly, and check your v argument as well.

WIA 2.0 - IWiaDevMgr2::GetImgDlg() - How to declare/init the ppbstrFilePaths parameter

I'm trying to implement some WIA 2.0 code in my VS2012 C++ library and have run into a problem with the IWiaDevMgr2::GetImageDlg call, specifically the ppbstrFilePaths paraneter. I'm not quite sure how to declare/initialize it.
From the documentation at http://msdn.microsoft.com/en-us/library/windows/desktop/aa359932(v=vs.85).aspx:
ppbstrFilePaths [in] TYPE - BSTR**
The address of a pointer to an array of paths for the scanned files. Initialize the pointer to point to an array of size zero (0) before IWiaDevMgr2::GetImageDlg is called. See Remarks.
I've tried all sorts of variations on declaring this with no success, for example:
// No scanner selection dialog, hr = E_OUTOFMEMORY
BSTR *files = new BSTR[0];
HRESULT hr = _pWiaDevMgr->GetImageDlg(0, NULL, *_parentHwnd, path, fileTemplate, numFiles, &files, &_pWiaItemRoot);
I've also tried things similar to this:
// No scanner selection dialog, hr = E_OUTOFMEMORY
BSTR **files = (BSTR**)CoTaskMemAlloc(0);
*files = new BSTR[0];
HRESULT hr = _pWiaDevMgr->GetImageDlg(0, NULL, *_parentHwnd, path, fileTemplate, &numFiles, files, &_pWiaItemRoot);
Can anyone point me in the right direction for declaring and initializing this BSTR**? I'm not a big C++ dev and pretty much guessing at this point.
Turns out I was on the right track with my first try:
CComBSTR path("D:\\TestWiaScan");
CComBSTR fileTemplate("FileName");
LONG numFiles = 0L;
BSTR *files = new BSTR[0];
HRESULT hr1 = _pWiaDevMgr->GetImageDlg(0, NULL, _parentHwnd, path, fileTemplate, &numFiles, &files, &_pWiaItemRoot);
if (files)
{
for(int i=0;i < numFiles;i++)
{
SysFreeString(files[i]);
}
}
CoTaskMemFree(files);
if (_pWiaItemRoot)
{
_pWiaItemRoot->Release();
_pWiaItemRoot = NULL;
}
The reason my first try wasn't working was because of issues with the BSTR parameters I was passing in. Using CComBSTR or SysAllocString resolved that.

Memory validate in difficult task within thread

I'm currently creating a sound system for my project. Every call PlayAsync creating instance of sound in std::thread callback. The sound data proceed in cycle in this callback. When thread proceeds it store sound instance in static vector. When thread ends (sound complete) - it delete sound instance and decrement instance count. When application ends - it must stop all sounds immediate, sending interrupt to every cycle of sound.
The problem is in array keeping these sounds. I am not sure, but I think vector isn't right choice for this purpose.. Here is a code.
void gSound::PlayAsync()
{
std::thread t(gSound::Play,mp_Audio,std::ref(*this));
t.detach();
}
HRESULT gSound::Play(IXAudio2* s_XAudio,gSound& sound)
{
gSound* pSound = new gSound(sound);
pSound->m_Disposed = false;
HRESULT hr;
// Create the source voice
IXAudio2SourceVoice* pSourceVoice;
if( FAILED( hr = s_XAudio->CreateSourceVoice( &pSourceVoice, pSound->pwfx ) ) )
{
gDebug::ShowMessage(L"Error creating source voice");
return hr;
}
// Submit the wave sample data using an XAUDIO2_BUFFER structure
XAUDIO2_BUFFER buffer = {0};
buffer.pAudioData = pSound->pbWaveData;
buffer.Flags = XAUDIO2_END_OF_STREAM; // tell the source voice not to expect any data after this buffer
buffer.AudioBytes = pSound->cbWaveSize;
if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
{
gDebug::ShowMessage(L"Error submitting source buffer");
pSourceVoice->DestroyVoice();
return hr;
}
hr = pSourceVoice->Start( 0 );
// Let the sound play
BOOL isRunning = TRUE;
m_soundInstanceCount++;
mp_SoundInstances.push_back(pSound); #MARK2
while( SUCCEEDED( hr ) && isRunning && pSourceVoice != nullptr && !pSound->m_Interrupted)
{
XAUDIO2_VOICE_STATE state;
pSourceVoice->GetState( &state );
isRunning = ( state.BuffersQueued > 0 ) != 0;
Sleep(10);
}
pSourceVoice->DestroyVoice();
delete pSound;pSound = nullptr; //its correct ??
m_soundInstanceCount--;
return 0;
}
void gSound::InterrupAllSoundInstances()
{
for(auto Iter = mp_SoundInstances.begin(); Iter != mp_SoundInstances.end(); Iter++)
{
if(*Iter != nullptr)//#MARK1
{
(*Iter)->m_Interrupted = true;
}
}
}
And this I call in application class before disposing sound objects, after main application loop immediate.
gSound::InterrupAllSoundInstances();
while (gSound::m_soundInstanceCount>0)//waiting for deleting all sound instances in threads
{
}
Questions:
So #MARK1 - How to check memory validation in vector? I don't have experience about it. And get errors when try check invalid memory (it's not equals null)
And #MARK2 - How to use vector correctly? Or maybe vector is bad choice? Every time I create sound instance it increases size. It's not good.
A typical issue:
delete pSound;
pSound = nullptr; // issue
This does not do what you think.
It will effectively set pSound to null, but there are other copies of the same pointer too (at least one in the vector) which do not get nullified. This is why you do not find nullptr in your vector.
Instead you could register the index into the vector and nullify that: mp_SoundInstances[index] = nullptr;.
However, I am afraid that you simply do not understand memory handling well and you lack structure. For memory handling, it's hard to tell without details and your system seems complicated enough that I am afraid it would tell too long to explain. For structure, you should read a bit about the Observer pattern.