// wiaacmgr.cpp : Implementation of WinMain // Note: Proxy/Stub Information // To build a separate proxy/stub DLL, // run nmake -f wiaacmgrps.mk in the project directory. #include "precomp.h" #include "resource.h" #include "wiaacmgr.h" #include #include #include #include "wiaacmgr_i.c" #include "acqmgr.h" #include "eventprompt.h" #include "runwiz.h" #include HINSTANCE g_hInstance; #if defined(DBG_GENERATE_PRETEND_EVENT) extern "C" int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) { WIA_DEBUG_CREATE( hInstance ); SHFusionInitializeFromModuleID( hInstance, 123 ); g_hInstance = hInstance; HRESULT hr = CoInitialize(NULL); if (SUCCEEDED(hr)) { IWiaDevMgr *pIWiaDevMgr = NULL; hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&pIWiaDevMgr ); if (SUCCEEDED(hr)) { BSTR bstrDeviceID; hr = pIWiaDevMgr->SelectDeviceDlgID( NULL, 0, 0, &bstrDeviceID ); if (hr == S_OK) { CEventParameters EventParameters; EventParameters.EventGUID = WIA_EVENT_DEVICE_CONNECTED; EventParameters.strEventDescription = L""; EventParameters.strDeviceID = static_cast(bstrDeviceID); EventParameters.strDeviceDescription = L""; EventParameters.ulEventType = 0; EventParameters.ulReserved = 0; EventParameters.hwndParent = NULL; HANDLE hThread = CAcquisitionThread::Create( EventParameters ); if (hThread) WaitForSingleObject(hThread,INFINITE); SysFreeString(bstrDeviceID); } pIWiaDevMgr->Release(); } CoUninitialize(); } SHFusionUninitialize(); WIA_REPORT_LEAKS(); WIA_DEBUG_DESTROY(); return 0; } #else // !defined(DBG_GENERATE_PRETEND_EVENT) const DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting down const DWORD dwPause = 1000; // time to wait for threads to finish up // Passed to CreateThread to monitor the shutdown event static DWORD WINAPI MonitorProc(void* pv) { CExeModule* p = (CExeModule*)pv; p->MonitorShutdown(); return 0; } LONG CExeModule::Unlock() { LONG l = CComModule::Unlock(); if (l == 0) { bActivity = true; SetEvent(hEventShutdown); // tell monitor that we transitioned to zero } return l; } //Monitors the shutdown event void CExeModule::MonitorShutdown() { while (1) { WaitForSingleObject(hEventShutdown, INFINITE); DWORD dwWait=0; do { bActivity = false; dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut); } while (dwWait == WAIT_OBJECT_0); // timed out if (!bActivity && m_nLockCnt == 0) // if no activity let's really bail { #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) CoSuspendClassObjects(); if (!bActivity && m_nLockCnt == 0) #endif break; } } CloseHandle(hEventShutdown); PostThreadMessage(dwThreadID, WM_QUIT, 0, 0); } bool CExeModule::StartMonitor() { hEventShutdown = CreateEvent(NULL, false, false, NULL); if (hEventShutdown == NULL) return false; DWORD dwThreadID; HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); return (h != NULL); } CExeModule _Module; BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_AcquisitionManager, CAcquisitionManager) OBJECT_ENTRY(CLSID_MinimalTransfer, CMinimalTransfer) OBJECT_ENTRY(WIA_EVENT_HANDLER_PROMPT, CEventPrompt) OBJECT_ENTRY(CLSID_StiEventHandler, CStiEventHandler) END_OBJECT_MAP() LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) { while (p1 != NULL && *p1 != NULL) { LPCTSTR p = p2; while (p != NULL && *p != NULL) { if (*p1 == *p) return CharNext(p1); p = CharNext(p); } p1 = CharNext(p1); } return NULL; } // // This MUST be removed before we ship. To remove it, remove // the define ENABLE_SETUP_LOGGING from the sources file // #if defined(ENABLE_SETUP_LOGGING) void _WizardPrintLogFileMessage( LPCTSTR pszFormat, ... ) { // // The name of the log file // static const TCHAR c_szLogFileName[] = TEXT("wiaacmgr.log"); // // The path to the log file // static TCHAR szLogFilePathName[MAX_PATH] = {0}; // // If we don't have a pathname, create it // if (!lstrlen(szLogFilePathName)) { if (GetWindowsDirectory( szLogFilePathName, ARRAYSIZE(szLogFilePathName) )) { lstrcat( szLogFilePathName, TEXT("\\") ); lstrcat( szLogFilePathName, c_szLogFileName ); } } // // If we still don't have a pathname, return // if (!lstrlen(szLogFilePathName)) { return; } // // Add the date and time to the output string // TCHAR szMessage[1500] = {0}; GetDateFormat( LOCALE_SYSTEM_DEFAULT, 0, NULL, TEXT("MM'/'dd'/'yy' '"), szMessage+lstrlen(szMessage), ARRAYSIZE(szMessage)-lstrlen(szMessage) ); GetTimeFormat( LOCALE_SYSTEM_DEFAULT, 0, NULL, TEXT("HH':'mm':'ss' '"), szMessage+lstrlen(szMessage), ARRAYSIZE(szMessage)-lstrlen(szMessage) ); // // Add the process ID and thread ID to the output string // wsprintf( szMessage+lstrlen(szMessage), TEXT("%08X %08X : "), GetCurrentProcessId(), GetCurrentThreadId() ); // // Format the output string // va_list pArgs; va_start( pArgs, pszFormat ); wvsprintf( szMessage+lstrlen(szMessage), pszFormat, pArgs ); va_end( pArgs ); lstrcat( szMessage, TEXT("\r\n" ) ); // // Open the file // HANDLE hFile = CreateFile( szLogFilePathName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile) { // // Go to the end of the file // if (INVALID_SET_FILE_POINTER != SetFilePointer(hFile,0,NULL,FILE_END)) { // // Write out the string // DWORD dwWritten; WriteFile(hFile,szMessage,lstrlen(szMessage)*sizeof(TCHAR),&dwWritten,NULL); } // // Close the file // CloseHandle(hFile); } } #define LOG_MESSAGE(x) _WizardPrintLogFileMessage x #else #define LOG_MESSAGE(x) #endif ENABLE_SETUP_LOGGING static HRESULT RegisterForWiaEvents( LPCWSTR pszDevice, const CLSID &clsidHandler, const IID &iidEvent, int nName, int nDescription, int nIcon, bool bDefault, bool bRegister ) { WIA_PUSH_FUNCTION((TEXT("RegisterForWiaEvents( device: %ws, default: %d, register: %d )"), pszDevice, bDefault, bRegister )); WIA_PRINTGUID((clsidHandler,TEXT("Handler:"))); WIA_PRINTGUID((iidEvent,TEXT("Event:"))); CComPtr pWiaDevMgr; HRESULT hr = CoCreateInstance( CLSID_WiaDevMgr, NULL, CLSCTX_LOCAL_SERVER, IID_IWiaDevMgr, (void**)&pWiaDevMgr ); LOG_MESSAGE((TEXT(" 0x%08X CoCreateInstance( CLSID_WiaDevMgr )"), hr )); if (SUCCEEDED(hr)) { CSimpleBStr bstrDeviceId(pszDevice); CSimpleBStr bstrName(CSimpleString(nName,_Module.m_hInst)); CSimpleBStr bstrDescription(CSimpleString(nDescription,_Module.m_hInst)); CSimpleBStr bstrIcon(CSimpleString(nIcon,_Module.m_hInst)); WIA_TRACE((TEXT("device: %ws"), pszDevice )); WIA_TRACE((TEXT("name : %ws"), bstrName.BString() )); WIA_TRACE((TEXT("desc : %ws"), bstrDescription.BString() )); WIA_TRACE((TEXT("icon : %ws"), bstrIcon.BString() )); if (bRegister) { if (bstrName.BString() && bstrDescription.BString() && bstrIcon.BString()) { hr = pWiaDevMgr->RegisterEventCallbackCLSID( WIA_REGISTER_EVENT_CALLBACK, pszDevice ? bstrDeviceId.BString() : NULL, &iidEvent, &clsidHandler, bstrName, bstrDescription, bstrIcon ); LOG_MESSAGE((TEXT(" 0x%08X RegisterEventCallbackCLSID( WIA_REGISTER_EVENT_CALLBACK, \"%ws\" )"), hr, bstrDeviceId.BString() )); if (SUCCEEDED(hr) && bDefault) { hr = pWiaDevMgr->RegisterEventCallbackCLSID( WIA_SET_DEFAULT_HANDLER, pszDevice ? bstrDeviceId.BString() : NULL, &iidEvent, &clsidHandler, bstrName, bstrDescription, bstrIcon ); LOG_MESSAGE((TEXT(" 0x%08X RegisterEventCallbackCLSID( WIA_SET_DEFAULT_HANDLER, \"%ws\" )"), hr, bstrDeviceId.BString() )); if (FAILED(hr)) { WIA_PRINTHRESULT((hr,TEXT("WIA_SET_DEFAULT_HANDLER failed"))); } } else if (FAILED(hr)) { WIA_PRINTHRESULT((hr,TEXT("WIA_REGISTER_EVENT_CALLBACK failed"))); } } } else { hr = pWiaDevMgr->RegisterEventCallbackCLSID( WIA_UNREGISTER_EVENT_CALLBACK, pszDevice ? bstrDeviceId.BString() : NULL, &iidEvent, &clsidHandler, bstrName, bstrDescription, bstrIcon ); LOG_MESSAGE((TEXT(" 0x%08X RegisterEventCallbackCLSID( WIA_UNREGISTER_EVENT_CALLBACK, \"%ws\" )"), hr, bstrDeviceId.BString() )); if (FAILED(hr)) { WIA_PRINTHRESULT((hr,TEXT("WIA_SET_DEFAULT_HANDLER failed"))); } } } if (FAILED(hr)) { WIA_PRINTHRESULT((hr,TEXT("Unable to register for the event!"))); } return hr; } struct CRegistryEntry { HKEY hKeyParent; LPCTSTR pszKey; LPCTSTR pszValueName; DWORD dwType; LPARAM nValue; DWORD dwSize; bool bOverwrite; }; bool SetRegistryValues( CRegistryEntry *pRegistryEntries, int nEntryCount ) { if (!pRegistryEntries) { return FALSE; } // // Assume success // bool bResult = true; // // Create the registry entries // for (int i=0;i(pRegistryEntries[i].nValue), pRegistryEntries[i].dwSize )) { bResult = false; } } } } return bResult; } ///////////////////////////////////////////////////////////////////////////// // extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/) { // // Save the global hInstance // g_hInstance = hInstance; LOG_MESSAGE((TEXT("Entering main: %s"), GetCommandLine())); // // Create the debugger // WIA_DEBUG_CREATE( hInstance ); // // this line necessary for _ATL_MIN_CRT // lpCmdLine = GetCommandLine(); // // Initialize fusion // SHFusionInitializeFromModuleID( hInstance, 123 ); #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED) HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED); #else HRESULT hRes = CoInitialize(NULL); #endif int nRet = 0; if (SUCCEEDED(hRes)) { _Module.Init(ObjectMap, hInstance, &LIBID_WIAACMGRLib); _Module.dwThreadID = GetCurrentThreadId(); TCHAR szTokens[] = _T("-/"); // // Assume we'll be running as a server // BOOL bRun = TRUE; // // Assume we won't be selecting a device and running the wizard // BOOL bRunWizard = FALSE; // // If there are no switches, we are not going to run the server // int nSwitchCount = 0; LPCTSTR lpszToken = FindOneOf( lpCmdLine, szTokens ); while (lpszToken != NULL) { // // One more switch. If we don't have any, we are going to do the selection dialog instead. // nSwitchCount++; if (lstrcmpi(lpszToken, _T("RegServer"))==0) { // // Register the server // LOG_MESSAGE((TEXT("Begin handling /RegServer"))); hRes = _Module.UpdateRegistryFromResource(IDR_ACQUISITIONMANAGER, TRUE); LOG_MESSAGE((TEXT(" 0x%08X _Module.UpdateRegistryFromResource(IDR_ACQUISITIONMANAGER)"), hRes )); _Module.UpdateRegistryFromResource(IDR_MINIMALTRANSFER,TRUE); LOG_MESSAGE((TEXT(" 0x%08X _Module.UpdateRegistryFromResource(IDR_MINIMALTRANSFER)"), hRes )); _Module.UpdateRegistryFromResource(IDR_STIEVENTHANDLER,TRUE); LOG_MESSAGE((TEXT(" 0x%08X _Module.UpdateRegistryFromResource(IDR_STIEVENTHANDLER)"), hRes )); nRet = _Module.RegisterServer(TRUE); LOG_MESSAGE((TEXT(" 0x%08X _Module.RegisterServer(TRUE)"), nRet )); hRes = RegisterForWiaEvents( NULL, CLSID_AcquisitionManager, WIA_EVENT_DEVICE_CONNECTED, IDS_DOWNLOADMANAGER_NAME, IDS_DOWNLOADMANAGER_DESC, IDS_DOWNLOADMANAGER_ICON, false, true ); LOG_MESSAGE((TEXT(" 0x%08X RegisterForWiaEvents( WIA_EVENT_DEVICE_CONNECTED )"), hRes )); #if defined(TESTING_STI_EVENT_HANDLER) hRes = RegisterForWiaEvents( NULL, CLSID_StiEventHandler, WIA_EVENT_DEVICE_CONNECTED, IDS_DOWNLOADMANAGER_NAME, IDS_DOWNLOADMANAGER_DESC, IDS_DOWNLOADMANAGER_ICON, false, true ); MessageBox( NULL, TEXT("Test-only code"), TEXT("DEBUG"), 0 ); #endif RegisterForWiaEvents( NULL, CLSID_AcquisitionManager, GUID_ScanImage, IDS_DOWNLOADMANAGER_NAME, IDS_DOWNLOADMANAGER_DESC, IDS_DOWNLOADMANAGER_ICON, false, true ); LOG_MESSAGE((TEXT(" 0x%08X RegisterForWiaEvents( GUID_ScanImage )"), hRes )); bRun = FALSE; LOG_MESSAGE((TEXT("End handling /RegServer\r\n"))); break; } if (lstrcmpi(lpszToken, _T("UnregServer"))==0) { _Module.UpdateRegistryFromResource(IDR_ACQUISITIONMANAGER, FALSE); _Module.UpdateRegistryFromResource(IDR_MINIMALTRANSFER,FALSE); nRet = _Module.UnregisterServer(TRUE); RegisterForWiaEvents( NULL, CLSID_AcquisitionManager, WIA_EVENT_DEVICE_CONNECTED, IDS_DOWNLOADMANAGER_NAME, IDS_DOWNLOADMANAGER_DESC, IDS_DOWNLOADMANAGER_ICON, false, false ); RegisterForWiaEvents( NULL, CLSID_AcquisitionManager, GUID_ScanImage, IDS_DOWNLOADMANAGER_NAME, IDS_DOWNLOADMANAGER_DESC, IDS_DOWNLOADMANAGER_ICON, false, false ); bRun = FALSE; break; } if (CSimpleString(lpszToken).ToUpper().Left(12)==CSimpleString(TEXT("SELECTDEVICE"))) { bRunWizard = TRUE; bRun = FALSE; break; } if (CSimpleString(lpszToken).ToUpper().Left(10)==CSimpleString(TEXT("REGCONNECT"))) { lpszToken = FindOneOf(lpszToken, TEXT(" ")); WIA_TRACE((TEXT("Handling RegConnect for %s"), lpszToken )); hRes = RegisterForWiaEvents( CSimpleStringConvert::WideString(CSimpleString(lpszToken)), CLSID_MinimalTransfer, WIA_EVENT_DEVICE_CONNECTED, IDS_MINIMALTRANSFER_NAME, IDS_MINIMALTRANSFER_DESC, IDS_MINIMALTRANSFER_ICON, true, true ); bRun = FALSE; break; } if (CSimpleString(lpszToken).ToUpper().Left(12)==CSimpleString(TEXT("UNREGCONNECT"))) { lpszToken = FindOneOf(lpszToken, TEXT(" ")); WIA_TRACE((TEXT("Handling RegUnconnect for %s"), lpszToken )); hRes = RegisterForWiaEvents( CSimpleStringConvert::WideString(CSimpleString(lpszToken)), CLSID_MinimalTransfer, WIA_EVENT_DEVICE_CONNECTED, IDS_MINIMALTRANSFER_NAME, IDS_MINIMALTRANSFER_DESC, IDS_MINIMALTRANSFER_ICON, false, false ); bRun = FALSE; break; } lpszToken = FindOneOf(lpszToken, szTokens); } // // if /SelectDevice was specified, or no arguments were specified, we want to start the wizard // if (bRunWizard || !nSwitchCount) { HRESULT hr = RunWiaWizard::RunWizard( NULL, NULL, TEXT("WiaWizardSingleInstanceDeviceSelection") ); if (FAILED(hr)) { MessageBox( NULL, CSimpleString( IDS_NO_DEVICE_TEXT, g_hInstance ), CSimpleString( IDS_ERROR_TITLE, g_hInstance ), MB_ICONHAND ); } } // // Otherwise run embedded // else if (bRun) { _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)) DispatchMessage(&msg); _Module.RevokeClassObjects(); } _Module.Term(); CoUninitialize(); } // // Uninitialize fusion // SHFusionUninitialize(); WIA_REPORT_LEAKS(); WIA_DEBUG_DESTROY(); LOG_MESSAGE((TEXT("Exiting main\r\n"))); return nRet; } #endif // DBG_GENERATE_PRETEND_EVENT