don't know how to use IShellWindows::Item correctly - c++

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.

Related

GetAce() returning unrecognizable Trustee (SID)

I'm continuing my quest to find the Holy Grail - or, really, just to write some C++ code that does some very basic ACL modifications on files. And, I'm continuing to bang my head against this wall with various challenges. The most recent one is that the "Trustee" returned by the GetAce() function doesn't seem to be a recognizable Trustee, even though I know exactly what it should be.
At a high level, what I'm currently trying to do is remove an Explicit ACE on a specific file that is DENYing access to the well-known Everyone group. Interestingly, if, instead of GetAce(), I use GetExplicitEntriesFromAcl(), I am able to get a recognizable SID and it compares correctly to the Everyone SID using EqualSid(); however, I don't know how to take the information from GetExplicitEntriesFromAcl() and then use that to remove the ACE from the ACL completely, because I don't get the absolute index of the ACE at that point, and there doesn't seem to be a RemoveExplicitEntriesFromAcl()-type function.
Current code, using GetAce() is below, but I'm open to other suggestions on how to reliably locate and remove a DENY ACE for the Everyone group.
BOOL removeAce(LPTSTR filePath) {
PACL existingAcl;
PSECURITY_DESCRIPTOR securityDescriptor;
PSID everyoneSid;
// Get PSID for well-known "Everyone" group
SID_IDENTIFIER_AUTHORITY sidAuthority = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(&sidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyoneSid))
return false;
// Make sure we really have a file path
if (filePath == NULL || wcscmp(filePath, L"") == 0)
return false;
// Retrieve the ACL for the file, or bail out.
if (GetNamedSecurityInfo(filePath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &existingAcl, NULL, &securityDescriptor) != ERROR_SUCCESS)
return false;
EXPLICIT_ACCESS* aclEntries;
ULONG numEntries = existingAcl->AceCount;
// Loop through all ACEs
for (DWORD i = 0; i < numEntries; i++) {
// Going to cast as a ACCESS_DENIED_ACE entry.
ACCESS_DENIED_ACE* entry;
// Try to get the ACE at current index, or continue to next one.
if (!GetAce(existingAcl, i, (LPVOID*) &entry))
continue;
// We're only interested in DENY entries.
if (entry->Header.AceType != ACCESS_DENIED_ACE_TYPE)
continue;
// Cast a couple of things to make it easier below
PSID thisSid = (PSID)entry->SidStart;
EXPLICIT_ACCESS* eaEntry = (EXPLICIT_ACCESS*)entry;
/* This is where I start to have problems - I put this code
* in strictly for debug purposes, and it always hits the
* default case, indicating that the TrusteeForm is either
* some unknown type, or I'm doing something insanely
* wrong and pointing to the wrong block of memory
* somewhere.
*/
switch (thisEntry->Trustee.TrusteeForm) {
case TRUSTEE_IS_SID:
OutputDebugString(L"We have a SID.\n");
break;
case TRUSTEE_IS_NAME:
OutputDebugString(L"We have a name.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_SID:
OutputDebugString(L"We have objects and a SID.\n");
break;
case TRUSTEE_IS_OBJECTS_AND_NAME:
OutputDebugString(L"We have objects and a name.\n");
break;
default:
OutputDebugString(L"We have an alien Trustee type.\n");
}
/* This is the ultimate goal - being able to match the Trustee
* of the current ACE being evaluated with the Everyone SID, but
* this if statement never evaluates to True, and, so far, it
* seems to be because the TrusteeForm isn't recognized as a SID
* - or anything else for that matter.
*/
if (eaEntry->Trustee.TrusteeForm == TRUSTEE_IS_SID
&& EqualSid((PSID)entry->SidStart, everyoneSid))
OutputDebugString(L"This is our EVERYONE entry.\n");
}
return true;
}
SidStart is not a pointer to a SID; it is the first 4 bytes of a SID. You need to access it like so:
PSID thisSid = (PSID)&(entry->SidStart);

ISearchJob->Release() stucking

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.

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.

ReadDebuggeeMemoryEx failed to read debuggee

I have write a debugger extension for my VisualStuido2010 to display my class type. I write my code base on the EEAddin sample provided by Microsoft. But I failed on call ReadDebuggeeMemoryEx.
I can't get any reason for this fail. GetLastError() returns 0.
ObjectId objid;
DWORD nGot;
int state = E_FAIL;
if ( pHelper->ReadDebuggeeMemoryEx(pHelper, pHelper->GetRealAddress(pHelper), sizeof(ObjectId), &objid, &nGot) )
{
}else { log("Fail ReadDebuggeeMemoryEx %d\n", GetLastError());}
The function ReadDebuggeeMemoryEx(...) returns a HRESULT not a BOOL.
Try something like :
if (pHelper->ReadDebuggeeMemoryEx(...) == S_OK) {
// good
} else {
// bad
}

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.