Leaked source code of windows server 2003
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

/*******************************************************************************
*
* (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;
}