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 useSUCCEEDED(hr)
, but you incorrectly moved the loop INSIDE theSUCCEEDED(hr)
test. You should checkSUCCEEDED(hr)
for every value ofV_I4(&v)
.Your
S_FALSE
result is because you now callhr = pisw->Item(v, &pidisp);
before the loop, which meansv
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
: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.