You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
645 lines
16 KiB
645 lines
16 KiB
/*******************************************************************************
|
|
*
|
|
* (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;
|
|
}
|
|
|
|
|