While playing around with a camera DirectShow video source filter, AMCap, which is widely used sample and which I believed to be very stable, started crashing in an inner call CDeviceMoniker::IsEqual:
devenum.dll!CDeviceMoniker::IsEqual() + 0x13 bytes > AmCap.exe!ChooseDevices(IMoniker * pmVideo=0x003e9a38, IMoniker * pmAudio=0x00000000) Line 2672 + 0x2a bytes C++ AmCap.exe!ChooseDevices(wchar_t * szVideo=0x0013f5b8, wchar_t * szAudio=0x0013edb0) Line 2753 + 0x13 bytes C++ AmCap.exe!AppInit(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * hPrev=0x00000000, int sw=1) Line 379 + 0x13 bytes C++ AmCap.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * hPrev=0x00000000, char * szCmdLine=0x00161f32, int sw=1) Line 453 + 0x11 bytes C++ AmCap.exe!__tmainCRTStartup() Line 578 + 0x35 bytes C AmCap.exe!WinMainCRTStartup() Line 403 C kernel32.dll!_BaseProcessStart@4() + 0x23 bytes
It appeared that while setting a checkmark on proper menu item the code does not check for the moniker tobe not NULL and a NULL IMoniker pointer passed as an argument into IMoniker::IsEqual is not checked inside devenum.dll (which is obviously a bug for an API entry).
To hotfix the problem, it is necessary to add an extra check near line 2650 of amcap.cpp:
int i; for(i = 0; i < NUMELMS(gcap.rgpmVideoMenu); i++) { if(gcap.rgpmVideoMenu[i] == NULL) break; // HOTFIX: Avoid calling IMoniker::IsEqual(NULL) due to possible memory access violation if(!gcap.pmVideo) continue; CheckMenuItem(GetMenu(ghwndApp), MENU_VDEVICE0 + i, (S_OK == gcap.rgpmVideoMenu[i]->IsEqual(gcap.pmVideo)) ? MF_CHECKED : MF_UNCHECKED); } for(i = 0; i < NUMELMS(gcap.rgpmAudioMenu); i++) { if(gcap.rgpmAudioMenu[i] == NULL) break; // HOTFIX: Avoid calling IMoniker::IsEqual(NULL) due to possible memory access violation if(!gcap.pmAudio) continue; CheckMenuItem(GetMenu(ghwndApp), MENU_ADEVICE0 + i, (S_OK == gcap.rgpmAudioMenu[i]->IsEqual(gcap.pmAudio)) ? MF_CHECKED : MF_UNCHECKED); }