[RESOLVED] IShellDispatch: FolderItemVerbs? (Getting bizarre crash with CoUninitaialize!)
Hi!
I hope this is the correct sub-forum to post this issue.
I'm having a very bizarre problem with the IShellDispatch COM interface, more specifically with the FolderItemVerbs that drives me nuts!
Calling FolderItemVerbs::Release() followed by CoUninitialze() will result in crash. It's clearly reproducible, but only happens 1 out of 10 times :confused:
Running the problematic code in a loop 100% reproduces the crash :cry:
Please see the example program:
Code:
static int TestProc(const TCHAR *pcDirectoryName, const TCHAR *pcFileName)
{
int iSuccess = 0;
IShellDispatch *pShellDispatch = NULL;
Folder *pFolder = NULL; FolderItem *pItem = NULL;
FolderItemVerbs *pVerbs = NULL;
HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if(FAILED(hr) || (pShellDispatch == NULL))
{
iSuccess = -3;
return iSuccess;
}
variant_t vaDirectory(pcDirectoryName);
hr = pShellDispatch->NameSpace(vaDirectory, &pFolder);
if(FAILED(hr) || (pFolder == NULL))
{
iSuccess = -4;
pShellDispatch->Release();
return iSuccess;
}
variant_t vaFileName(pcFileName);
hr = pFolder->ParseName(vaFileName, &pItem);
if(FAILED(hr) || (pItem == NULL))
{
iSuccess = -5;
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}
hr = pItem->Verbs(&pVerbs);
if(FAILED(hr) || (pVerbs == NULL))
{
iSuccess = -6;
pItem->Release();
pFolder->Release();
pShellDispatch->Release();
return iSuccess;
}
/* Here we would do something with the FolderItemVerbs */
pVerbs->Release(); //If this line is commented out, we don't get a crash, but a massive memory leak!
pVerbs = NULL;
pItem->Release();
pItem = NULL;
pFolder->Release();
pFolder = NULL;
pShellDispatch->Release();
pShellDispatch = NULL;
iSuccess = 1;
return iSuccess;
}
//-----------------------------------------------------------------------------
static unsigned __stdcall ThreadProc(void* pArguments)
{
HRESULT hr = CoInitialize(NULL);
if((hr == S_OK) || (hr == S_FALSE))
{
threadParam_t *params = (threadParam_t*) pArguments;
params->returnValue = TestProc(params->pcDirectoryName, params->pcFileName);
CoUninitialize();
}
else
{
if(threadParam_t *params = (threadParam_t*) pArguments)
{
params->returnValue = -10;
}
}
return EXIT_SUCCESS;
}
Please download the *complete* example code is here:
http://pastie.org/private/0xsnajpia9lsmgnlf2afa
Please also note that I unambiguously tracked down to crash to FolderItemVerbs, because if I never create the FolderItemVerbs object, the crash is gone immediately.
Also if I never call "pVerbs->Release()" before CoUninitialize() the crash is gone too, but this will result in a massive memleak, obviously.
Another strange thing is that the crash will NOT happen, if I run the program under the Debugger! But I can run the program, wait for the crash and then let the Debugger handle the crash.
Unfortunately the Stack Trace that I get then doesn't help much:
http://pastie.org/private/cuwunlun2t5dc5lembpw
I don't think I'm doing anything wrong here. I have checked the code over and over again in the last two days. So this all seems to be a bug in FolderItemVerbs!
Has anybody encountered this before and/or can confirm that this is a bug in FolderItemVerbs? Also, is there any workaround for the problem?
Thanks in advance !!!
Re: IShellDispatch: FolderItemVerbs? (Getting bizarre crash with CoUninitaialize!)
Sorry, forgot to mention: The crash is an "0xC0000005: Access Violation" error.
(BTW: Am I blind or is there really no "Edit" button on this forum?)
Re: IShellDispatch: FolderItemVerbs? (Getting bizarre crash with CoUninitaialize!)
Quote:
Originally Posted by
MuldeR2
(BTW: Am I blind or is there really no "Edit" button on this forum?)
Edit button will appear after about five your posts.
And please:
- use Code tags, not PHP ones
- do NOT put more than one statements in one line
Otherwise your code is hard to read/understand!
Re: [RESOLVED] IShellDispatch: FolderItemVerbs? (Getting bizarre crash with CoUninita
Okay, got the answer elsewehre.
It turns out this was caused by a "problematic" Shell Extension. In my case it was Tortoise GIT.
And it could be resolved by explicitely dispacthing all messages before CoUninitialize().
Code:
static int TestProc(const TCHAR *pcDirectoryName, const TCHAR *pcFileName)
{
/*see above*/
}
static void DispatchPendingMessages(void)
{
const DWORD uiTimeout = GetTickCount() + 10000;
const HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
unsigned int counter = 0;
if(hEvent)
{
for(;;)
{
MSG Message;
while(PeekMessage(&Message, NULL, WM_NULL, WM_NULL, PM_REMOVE))
{
TranslateMessage(&Message);
DispatchMessage(&Message);
}
const DWORD nWaitResult = MsgWaitForMultipleObjects(1, &hEvent, FALSE, 250, QS_ALLINPUT | QS_ALLPOSTMESSAGE);
if((nWaitResult == WAIT_TIMEOUT) || (nWaitResult == WAIT_FAILED) || (GetTickCount() >= uiTimeout)) break;
}
CloseHandle(hEvent);
}
}
static unsigned __stdcall ThreadProc(void* pArguments)
{
HRESULT hr = CoInitialize(NULL);
if((hr == S_OK) || (hr == S_FALSE))
{
threadParam_t *params = (threadParam_t*) pArguments;
params->returnValue = TestProc(params->pcDirectoryName, params->pcFileName);
DispatchPendingMessages(); //This is required before CoUninitialize() to avoid crash with certain Shell Extensions !!!
CoUninitialize();
}
else
{
if(threadParam_t *params = (threadParam_t*) pArguments)
{
params->returnValue = -10;
}
}
return EXIT_SUCCESS;
}