/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1998 * * TITLE: Main.Cpp * * VERSION: 2.0 * * AUTHOR: ReedB * * DATE: 9 Jan, 1998 * * DESCRIPTION: * * Implementation of WinMain for WIA device manager server device object. * *******************************************************************************/ #include "precomp.h" #include "stiexe.h" #include "wiamindr.h" #include "wiacfact.h" #include "devmgr.h" #include "wialog.h" #include "wiaevntp.h" // // Image transfer critical section. // CRITICAL_SECTION g_semDeviceMan; // // Critical section for event node, should only be used in event notifier // CRITICAL_SECTION g_semEventNode; // // data to initialize WiaDevMgr CLSID // FACTORY_DATA g_FactoryData[] = { {CWiaDevMgr::CreateInstance, // Object creator NULL, // Pointer to running class factory 0, // ID for running object &CLSID_WiaDevMgr, // Class ID &LIBID_WiaDevMgr, // Type Library ID TEXT("WIA Device Manager"), // Friendly Name TEXT("WiaDevMgr.1"), // Program ID TEXT("WiaDevMgr"), // Version-independent Program ID TEXT("StiSvc"), // Service ID SERVICE_FILE_NAME} // Filename }; UINT g_uiFactoryDataCount = sizeof(g_FactoryData) / sizeof(FACTORY_DATA); // // data to initialize WiaLog CLSID // FACTORY_DATA g_LogFactoryData[] = { {CWiaLog::CreateInstance, // Object creator NULL, // Pointer to running class factory 0, // ID for running object &CLSID_WiaLog, // Class ID &LIBID_WiaDevMgr, // Type Library ID (Logging shares Type lib) TEXT("WIA Logger"), // Friendly Name TEXT("WiaLog.1"), // Program ID TEXT("WiaLog"), // Version-independent Program ID TEXT("StiSvc"), // Service ID (Logging uses same service) SERVICE_FILE_NAME} // Filename (Logging uses same .exe) }; UINT g_uiLogFactoryDataCount = sizeof(g_LogFactoryData) / sizeof(FACTORY_DATA); // // Private function proto's: // LRESULT CALLBACK WiaMainWndProc(HWND, UINT, UINT, LONG); /**************************************************************************\ * ProcessWiaMsg * * !!! minimal message server: is this needed * * Arguments: * * hwnd - window handle * uMsg - message * wParam - param * lParam - param * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT ProcessWiaMsg(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_CREATE: break; case WM_DESTROY: if (CFactory::CanUnloadNow() != S_OK) { // // Don't let STI process this message. // return S_OK; } break; case WM_CLOSE: break; } // // Let STI handle the message. // return S_FALSE; } #if 0 /**************************************************************************\ * DispatchWiaMsg * * Handle Event messages * * * !!! WM_NOTIFY_WIA_VOLUME_EVENT is a temp hack and needs to be * added for real or removed * * Arguments: * * pMsg WM_NOTIFY_WIA_DEV_EVENT or WM_NOTIFY_WIA_VOLUME_EVENT * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT DispatchWiaMsg(MSG *pMsg) { DBG_FN(::DispatchWiaMsg); PWIANOTIFY pwn; if (pMsg->message == WM_NOTIFY_WIA_DEV_EVENT) { // // find out if this is a valid WIA event, call handler // DBG_ERR(("WIA Processing WM_NOTIFY_WIA_DEV_EVENT: shouldn't be called")); // // event are now directly fired, not posted // #if 0 pwn = (PWIANOTIFY) pMsg->lParam; if (pwn && (pwn->lSize == sizeof(WIANOTIFY))) { if (g_eventNotifier.NotifySTIEvent(pwn) == S_FALSE) { DBG_WRN(("::DispatchWiaMsg, No Applications were registered for this event")); } SysFreeString(pwn->bstrDevId); LocalFree(pwn); } else { DBG_ERR(("::DispatchWiaMsg, Bad WIA notify data")); } #endif } else if (pMsg->message == WM_NOTIFY_WIA_VOLUME_EVENT) { // // WIA volume arrival // DBG_TRC(("::DispatchWiaMsg, WIA Processing WM_NOTIFY_WIA_VOLUME_EVENT")); PWIANOTIFY_VOLUME pwn = (PWIANOTIFY_VOLUME) pMsg->lParam; if (pwn && (pwn->lSize == sizeof(WIANOTIFY_VOLUME))) { // // look at root fo volume for WIA File wia.cmd // int i; char c = 'A'; DWORD mask = pwn->unitmask; // // find drive letter // if (mask & 0x07ffffff) { for (i=0;i<24;i++) { if (mask & 0x00000001) { break; } c++; mask >>= 1; } // // build file name // char FileName[MAX_PATH]; FileName[0] = c; FileName[1] = ':'; FileName[2] = '\\'; FileName[3] = 'w'; FileName[4] = 'i'; FileName[5] = 'a'; FileName[6] = '.'; FileName[7] = 'c'; FileName[8] = 'm'; FileName[9] = 'd'; FileName[10] = '\0'; // // open file // HANDLE hFile = CreateFileA( FileName, GENERIC_WRITE | GENERIC_READ , FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hFile != INVALID_HANDLE_VALUE) { // // file name is on volume root // if (g_eventNotifier.NotifyVolumeEvent(pwn) == S_FALSE) { DBG_WRN(("::DispatchWiaMsg, No Applications were registered for this Volume event")); } CloseHandle(hFile); } } // // free message // LocalFree(pwn); } else { DBG_ERR(("::DispatchWiaMsg, Bad WIA notify data")); } } // // Let STI handle the message. // return S_FALSE; } #endif /**************************************************************************\ * RegisterWiaDevMan * * Register WiaDevMgr class factory * * Arguments: * * bRegister - register/unregister * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT RegisterWiaDevMan(BOOLEAN bRegister) { HRESULT hr = CFactory::RegisterUnregisterAll(g_FactoryData, g_uiFactoryDataCount, bRegister, TRUE); if(SUCCEEDED(hr)) { hr = CFactory::RegisterUnregisterAll(g_LogFactoryData, g_uiLogFactoryDataCount, bRegister, TRUE); } return hr; } /**************************************************************************\ * StartLOGClassFactories * * Starts the Class factories for WIA logging object * * Arguments: * * none * * Return Value: * * Status * * History: * * 8/23/1999 Original Version * \**************************************************************************/ HRESULT StartLOGClassFactories() { #ifdef WINNT HRESULT hr = S_OK; // // Set COM security options. // NOTE: Calling CoInitializeSecurity will override any DCOM // AccessPermissions that have been set (these are stored under // our AppID key). We really want to use these permissions and // not a hardcoded security descriptor, so that if a vendor wanted // to enable shared/remote scanning, all they need to do is adjust // the DCOM AccessPermissions on the Wia Device Manager object. // This can be done either through DCOM Config GUI, or programatically // via the vendor's installation program. (See our ClassFactory for // an example of how to set the AccessPermissions. When we are installed, // we set default access permissions when doing our COM registration). // The way we get COM to use the DCOM AccessPermissions for the WIA // Device Manager, is we pass in the AppID (as a pointer to a GUID); and // the EOAC_APPID flag indicating that the first parameter is an AppID // rather than a security descriptor. This informs COM that the // security descriptor should be taken from this objects AppID entry // in the registry. // hr = CoInitializeSecurity((PVOID)&CLSID_WiaDevMgr, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_DYNAMIC_CLOAKING | EOAC_APPID, NULL); if (FAILED(hr)) { DBG_ERR(("StartLOGClassFactories() CoInitializeSecurity failed, hr = 0x%08X", hr)); ::CoUninitialize(); } #endif if (CFactory::StartFactories(g_LogFactoryData, g_uiLogFactoryDataCount)) return S_OK; else return E_FAIL; } /**************************************************************************\ * InitWiaDevMan * * Wia Initialization called from STI * * Arguments: * * action - Action to be taken * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT InitWiaDevMan( WIA_SERVICE_INIT_ACTION action) { DBG_FN("InitWiaDevMan"); HRESULT hr = E_FAIL; switch (action) { case WiaInitialize: // // Get Thread ID and process handle for the class factory. // CFactory::s_dwThreadID = GetCurrentThreadId(); CFactory::s_hModule = g_hInst; /* // // This was moved to StartLOGClassFactories(), because of COM security's need // to be initialized before an object can be CoCreated correctly. // (investigate better way to do this..) // #ifdef WINNT // // Set COM security options. For now we set no security. // We will need to investigate this before shipping. // hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, 0, NULL); if (FAILED(hr)) { DBG_ERR(("CoInitializeSecurity failed (0x%X)", hr)); ::CoUninitialize(); break; } #endif */ // // Register all of the class factories. // if (CFactory::StartFactories(g_FactoryData, g_uiFactoryDataCount)) { // // Restore persistent Event Callbacks // hr = g_eventNotifier.RestoreAllPersistentCBs(); } hr = E_FAIL; break; case WiaUninitialize: // // Unregister the class factories. // CFactory::StopFactories(g_FactoryData, g_uiFactoryDataCount); CFactory::StopFactories(g_LogFactoryData, g_uiLogFactoryDataCount); hr = S_OK; break; case WiaRegister: hr = RegisterWiaDevMan(TRUE); break; case WiaUnregister: hr = RegisterWiaDevMan(FALSE); break; } return hr; } /**************************************************************************\ * NotifyWiaDeviceEvent * * Called by STI service when WIA needs an async notification. * * Arguments: * * pwszDevID - ID of device generating event * pEventGUID - event GUID * dwThreadId - thread event msg needs to be posted to * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT NotifyWiaDeviceEvent( LPWSTR pwszDevID, const GUID *pEventGUID, PBYTE pNotificationData, ULONG ulEventType, DWORD dwThreadId) { DBG_FN(NotifyWiaDeviceEvent); HRESULT hr; BSTR bstrDevId; WIANOTIFY wn; DBG_TRC(("NotifyWiaDeviceEvent, pwszDevID= %S", pwszDevID)); bstrDevId = SysAllocString(pwszDevID); if (bstrDevId != NULL) { wn.lSize = sizeof(WIANOTIFY); wn.bstrDevId = bstrDevId; wn.stiNotify.dwSize = sizeof(STINOTIFY); wn.stiNotify.guidNotificationCode = *pEventGUID; if (! pNotificationData) { ZeroMemory(&wn.stiNotify.abNotificationData, MAX_NOTIFICATION_DATA); } else { CopyMemory( &wn.stiNotify.abNotificationData, pNotificationData, MAX_NOTIFICATION_DATA); } g_eventNotifier.NotifySTIEvent(&wn, ulEventType, NULL); // // We should return S_TRUE for events that we want STI to // handle also. // SysFreeString(bstrDevId); hr = S_FALSE; } else { hr = E_OUTOFMEMORY; } return hr; } /**************************************************************************\ * NotifyWiaVolumeEvent * * Called by STI service when a removable volume arrives * * Arguments: * * dbcv_unitmask - volume information flags * dwThreadId - msg thread * * Return Value: * * Status * * History: * * 4/8/1999 Original Version * \**************************************************************************/ HRESULT WINAPI NotifyWiaVolumeEvent( DWORD dbcv_unitmask, DWORD dwThreadId) { PWIANOTIFY_VOLUME pwn; // // Validate the thread ID. // if (!dwThreadId) { return E_FAIL; } // // Allocate and fill in WIANOTIFY structure for msg post. // pwn = (PWIANOTIFY_VOLUME)LocalAlloc(LPTR, sizeof(WIANOTIFY_VOLUME)); if (pwn) { pwn->lSize = sizeof(WIANOTIFY_VOLUME); pwn->unitmask = dbcv_unitmask; PostThreadMessage(dwThreadId, WM_NOTIFY_WIA_VOLUME_EVENT, 0, (LPARAM)pwn); } else { return E_OUTOFMEMORY; } // // We should return S_TRUE for events that we want STI to // handle also. // return S_FALSE; }