I have a DCOM server running and it creates a Tray icon. The tray icon can be right clicked and a menu pops up. One of the menu items is to Close the program.
On WinNT machines, when you try to close the program this way or by sending WM_CLOSE to it, it gives me an Access Violation in Ole32.dll @ 0x77b45677. Its happening in the RevokeClassObjects function but that's all I can decipher.
Has anyone else had any similar experience? I can't find anything like this on the net. Please help!
Here is some code:
void CExeModule::MonitorShutdown()
{
while (1)
{
WaitForSingleObject(hEventShutdown, INFINITE);
DWORD dwWait=0;
do
{
bActivity = false;
dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
} while (dwWait == WAIT_OBJECT_0);
if (!bActivity && m_nLockCnt == 0 && bOKToShutDown)
{
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
CoSuspendClassObjects();
if (!bActivity && m_nLockCnt == 0)
#endif
break;
}
}
CloseHandle(hEventShutdown);
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case UM_NOTIFY_ICON:
switch(lParam)
{
case WM_LBUTTONDBLCLK:
::SendMessage(hwnd, WM_COMMAND, IDM_ABOUT, 0);
break;
case WM_RBUTTONUP:
{
POINT point;
HMENU hMenu, hSubMenu;
GetCursorPos(&point);
hMenu = LoadMenu(hInstCopy, MAKEINTRESOURCE(IDR_ESINETCONNECT_MENU));
hSubMenu = GetSubMenu(hMenu, 0);
SetMenuDefaultItem(hSubMenu, IDCLOSE, FALSE);
SetForegroundWindow(hwnd);
TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_LEFTALIGN,
point.x, point.y, 0, hwnd, NULL);
PostMessage(hwnd, WM_NULL, 0, 0);
DestroyMenu(hMenu);
}
break;
default:
return FALSE;
}
break;
case WM_COMMAND:
switch (wParam)
{
case IDCLOSE:
PostMessage(hwnd, WM_CLOSE, 0, 0);
break;
case IDM_ABOUT:
::MessageBox(hwnd, szMessage, szTitle, MB_OK);
break;
default:
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE , LPTSTR lpCmdLine, int )
{
HWND hwnd = NULL;
WNDCLASSEX wc;
NOTIFYICONDATA nid;
HKEY phkResult = NULL;
hwnd = FindWindow("name withheld", szTitle);
if (hwnd != NULL) return 0;
hwnd = CreateWindow("name withheld", szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, HWND_DESKTOP, NULL,
hInstance, NULL);
if (RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Key\\Key",
0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &phkResult, NULL) == ERROR_SUCCESS)
{
RegSetValueEx(phkResult, "HandleToHwnd", NULL, REG_DWORD, (LPBYTE)&hwnd, sizeof(DWORD));
RegCloseKey(phkResult);
}
hInstCopy = hInstance;
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.uID = ID_TRAYICON;
nid.hWnd = hwnd;
nid.hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_MYICON), IMAGE_ICON, 16, 16, 0);
nid.uCallbackMessage = UM_NOTIFY_ICON;
nid.uFlags = NIF_ICON | NIF_TIP| NIF_MESSAGE;
strcpy(nid.szTip, szTitle);
Shell_NotifyIcon(NIM_ADD, &nid);
_Module.bOKToShutDown = FALSE;
lpCmdLine = GetCommandLine();
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
HRESULT hRes = CoInitialize(NULL);
#endif
CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
_ASSERTE(SUCCEEDED(hRes));
_Module.Init(ObjectMap, hInstance, &LIBID_ESINETCONNECTLib);
_Module.dwThreadID = GetCurrentThreadId();
TCHAR szTokens[] = _T("-/");
int nRet = 0;
BOOL bRun = TRUE;
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
{
_Module.UpdateRegistryFromResource(IDR_Esinetconnect, FALSE);
nRet = _Module.UnregisterServer(TRUE);
bRun = FALSE;
break;
}
if (lstrcmpi(lpszToken, _T("RegServer"))==0)
{
_Module.UpdateRegistryFromResource(IDR_Esinetconnect, TRUE);
nRet = _Module.RegisterServer(TRUE);
bRun = FALSE;
break;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
if (bRun)
{
ShowWindow(hwnd, SW_HIDE);
UpdateWindow(hwnd);
_Module.StartMonitor();
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
_ASSERTE(SUCCEEDED(hRes));
hRes = CoResumeClassObjects();
#else
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
REGCLS_MULTIPLEUSE);
#endif
_ASSERTE(SUCCEEDED(hRes));
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
if (msg.message == WM_CLOSE)
_Module.bOKToShutDown = TRUE;
DispatchMessage(&msg);
}
_Module.RevokeClassObjects();
Sleep(dwPause);
}
Shell_NotifyIcon(NIM_DELETE, &nid);
RegDeleteKey(HKEY_CURRENT_USER, "Software\\Key\\Key");
_Module.Term();
CoUninitialize();
return nRet;
}
Like it or not, I'm right.
|