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.
587 lines
15 KiB
587 lines
15 KiB
/*****************************************************************************
|
|
*
|
|
* Sti.c
|
|
*
|
|
* Copyright (C) Microsoft Corporation, 1996 - 1998 All Rights Reserved.
|
|
*
|
|
* Abstract:
|
|
*
|
|
* DLL Initialization/termination routines and global
|
|
* exported functions
|
|
*
|
|
* Contents:
|
|
*
|
|
* StiCreateInstance() - exported function to create top level instance
|
|
*
|
|
*****************************************************************************/
|
|
|
|
|
|
#define INITGUID
|
|
#include "pch.h"
|
|
|
|
//
|
|
// Externs found in STIRT
|
|
//
|
|
extern DWORD g_cRef;
|
|
extern CRITICAL_SECTION g_crstDll;
|
|
extern CHAR szProcessCommandLine[MAX_PATH];
|
|
|
|
#ifdef DEBUG
|
|
extern int g_cCrit;
|
|
#endif
|
|
|
|
extern VOID RegSTIforWiaHelper(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
|
|
extern VOID MigrateSTIAppsHelper(HWND hWnd, HINSTANCE hInst, PTSTR pszCommandLine, INT iParam);
|
|
|
|
#include <rpcproxy.h>
|
|
#define DbgFl DbgFlSti
|
|
|
|
|
|
BOOL APIENTRY
|
|
DmPrxyDllMain(
|
|
HINSTANCE hinst,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved
|
|
);
|
|
|
|
|
|
STDAPI
|
|
DmPrxyDllGetClassObject(
|
|
REFCLSID rclsid,
|
|
RIID riid,
|
|
PPV ppvObj
|
|
);
|
|
|
|
STDMETHODIMP
|
|
DmPrxyDllCanUnloadNow(
|
|
void
|
|
);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | DllEnterCrit |
|
|
*
|
|
* Take the DLL critical section.
|
|
*
|
|
* The DLL critical section is the lowest level critical section.
|
|
* You may not attempt to acquire any other critical sections or
|
|
* yield while the DLL critical section is held.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
DllEnterCrit(void)
|
|
{
|
|
EnterCriticalSection(&g_crstDll);
|
|
#ifdef DEBUG
|
|
|
|
// Save thread ID , taking critical section first , it becomes owner
|
|
if (++g_cCrit == 0) {
|
|
g_thidCrit = GetCurrentThreadId();
|
|
}
|
|
AssertF(g_thidCrit == GetCurrentThreadId());
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | DllLeaveCrit |
|
|
*
|
|
* Leave the DLL critical section.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
DllLeaveCrit(void)
|
|
{
|
|
#ifdef DEBUG
|
|
AssertF(g_thidCrit == GetCurrentThreadId());
|
|
AssertF(g_cCrit >= 0);
|
|
if (--g_cCrit < 0) {
|
|
g_thidCrit = 0;
|
|
}
|
|
#endif
|
|
LeaveCriticalSection(&g_crstDll);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | DllAddRef |
|
|
*
|
|
* Increment the reference count on the DLL.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
DllAddRef(void)
|
|
{
|
|
InterlockedIncrement((LPLONG)&g_cRef);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func void | DllRelease |
|
|
*
|
|
* Decrement the reference count on the DLL.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL
|
|
DllRelease(void)
|
|
{
|
|
InterlockedDecrement((LPLONG)&g_cRef);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULT | DllGetClassObject |
|
|
*
|
|
* Create an <i IClassFactory> instance for this DLL.
|
|
*
|
|
* @parm REFCLSID | rclsid |
|
|
*
|
|
* The object being requested.
|
|
*
|
|
* @parm RIID | riid |
|
|
*
|
|
* The desired interface on the object.
|
|
*
|
|
* @parm PPV | ppvOut |
|
|
*
|
|
* Output pointer.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#pragma BEGIN_CONST_DATA
|
|
|
|
CLSIDMAP c_rgclsidmap[cclsidmap] = {
|
|
{ &CLSID_Sti, CStiObj_New, IDS_STIOBJ },
|
|
// { &CLSID_StiDevice, CStiDevice_New, IDS_STIDEVICE },
|
|
};
|
|
|
|
#pragma END_CONST_DATA
|
|
|
|
STDAPI
|
|
DllGetClassObject(REFCLSID rclsid, RIID riid, PPV ppvObj)
|
|
{
|
|
HRESULT hres;
|
|
UINT iclsidmap;
|
|
EnterProcR(DllGetClassObject, (_ "G", rclsid));
|
|
|
|
//
|
|
// Bump global ref count temporarily. By doing so we minimize chances of
|
|
// faulting on potential race condition when another thread just called
|
|
// DllCanUnloadNow while we are inside ClassFactory.
|
|
//
|
|
DllAddRef();
|
|
for (iclsidmap = 0; iclsidmap < cA(c_rgclsidmap); iclsidmap++) {
|
|
if (IsEqualIID(rclsid, c_rgclsidmap[iclsidmap].rclsid)) {
|
|
hres = CSti_Factory_New(c_rgclsidmap[iclsidmap].pfnCreate,
|
|
riid, ppvObj);
|
|
goto done;
|
|
}
|
|
}
|
|
DebugOutPtszV(DbgFlDll | DbgFlError, TEXT("%s: Wrong CLSID"),"");
|
|
*ppvObj = 0;
|
|
hres = CLASS_E_CLASSNOTAVAILABLE;
|
|
|
|
done:;
|
|
|
|
//
|
|
// If unsucessful - try DM Proxy
|
|
//
|
|
if (!SUCCEEDED(hres)) {
|
|
hres = DmPrxyDllGetClassObject(rclsid, riid, ppvObj);
|
|
}
|
|
|
|
ExitOleProcPpv(ppvObj);
|
|
DllRelease();
|
|
return hres;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULT | DllCanUnloadNow |
|
|
*
|
|
* Determine whether the DLL has any outstanding interfaces.
|
|
*
|
|
* @returns
|
|
*
|
|
* Returns <c S_OK> if the DLL can unload, <c S_FALSE> if
|
|
* it is not safe to unload.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDMETHODIMP
|
|
DllCanUnloadNow(void)
|
|
{
|
|
HRESULT hres;
|
|
|
|
//
|
|
// First ask DM proxy and it says OK - check out ref count
|
|
//
|
|
hres = DmPrxyDllCanUnloadNow();
|
|
if (hres == S_OK) {
|
|
#ifdef DEBUG
|
|
DebugOutPtszV(DbgFlDll, TEXT("DllCanUnloadNow() - g_cRef = %d"), g_cRef);
|
|
Common_DumpObjects();
|
|
#endif
|
|
hres = g_cRef ? S_FALSE : S_OK;
|
|
}
|
|
|
|
return hres;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func BOOL | DllEntryPoint |
|
|
*
|
|
* Called to notify the DLL about various things that can happen.
|
|
*
|
|
* We are not interested in thread attaches and detaches,
|
|
* so we disable thread notifications for performance reasons.
|
|
*
|
|
* @parm HINSTANCE | hinst |
|
|
*
|
|
* The instance handle of this DLL.
|
|
*
|
|
* @parm DWORD | dwReason |
|
|
*
|
|
* Notification code.
|
|
*
|
|
* @parm LPVOID | lpReserved |
|
|
*
|
|
* Not used.
|
|
*
|
|
* @returns
|
|
*
|
|
* Returns <c TRUE> to allow the DLL to load.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#pragma BEGIN_CONST_DATA
|
|
|
|
#pragma END_CONST_DATA
|
|
|
|
BOOL APIENTRY
|
|
DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
//RPC_STATUS RpcStatus;
|
|
DWORD dwLocalSTIServerVer = 0;
|
|
UINT uiCmdLineLength;
|
|
|
|
switch (dwReason) {
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
g_hInst = hinst;
|
|
|
|
__try {
|
|
// Disable thread library calls to avoid
|
|
// deadlock when we spin up the worker thread
|
|
|
|
DisableThreadLibraryCalls(hinst);
|
|
if(!InitializeCriticalSectionAndSpinCount(&g_crstDll, MINLONG)) {
|
|
// refuse to load if we can't initialize critsect
|
|
return FALSE;
|
|
}
|
|
|
|
// Set global flags
|
|
g_NoUnicodePlatform = !OSUtil_IsPlatformUnicode();
|
|
|
|
//
|
|
// Save command line for use in GetLaunchInformation
|
|
//
|
|
uiCmdLineLength = min(lstrlenA(GetCommandLineA()),sizeof(szProcessCommandLine)-1);
|
|
lstrcpyn(szProcessCommandLine,GetCommandLineA(),uiCmdLineLength);
|
|
szProcessCommandLine[uiCmdLineLength] = '\0';
|
|
|
|
#ifdef DEBUG
|
|
// Debugging flags
|
|
InitializeDebuggingSupport();
|
|
#endif
|
|
|
|
//
|
|
// Initialize file logging
|
|
//
|
|
|
|
g_hStiFileLog = CreateStiFileLog(TEXT("STICLI"),NULL,
|
|
STI_TRACE_ERROR |
|
|
STI_TRACE_ADD_THREAD | STI_TRACE_ADD_PROCESS
|
|
);
|
|
|
|
#if CHECK_LOCAL_SERVER
|
|
// Check version of the local server
|
|
RpcStatus = RpcStiApiGetVersion(NULL,
|
|
0,
|
|
&dwLocalSTIServerVer);
|
|
|
|
DebugOutPtszV(DbgFlDll, TEXT("STIINIT : Getting server version : RpcStatus = %d LocalServerVer=%d"),
|
|
RpcStatus,dwLocalSTIServerVer);
|
|
#endif
|
|
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
if (g_cRef) {
|
|
DebugOutPtszV(DbgFl,"Unloaded before all objects Release()d! Crash soon!\r\n");
|
|
}
|
|
|
|
// Close file logging
|
|
CloseStiFileLog(g_hStiFileLog);
|
|
|
|
//
|
|
// Don't forget to delete our critical section. (It is safe to
|
|
// do this because we definitely tried to initialize it and so
|
|
// it should be in a sane state)
|
|
//
|
|
|
|
DeleteCriticalSection(&g_crstDll);
|
|
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
BOOL APIENTRY
|
|
DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
// First call proxy dll main
|
|
DmPrxyDllMain(hinst, dwReason, lpReserved);
|
|
|
|
return DllEntryPoint(hinst, dwReason, lpReserved);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc EXTERNAL
|
|
*
|
|
* @func HRESULT | StiCreateInstance |
|
|
*
|
|
* <bnew>This function creates a new Sti object
|
|
* which supports the <i ISti> COM interface.
|
|
*
|
|
* On success, the function returns a pointer to the new object in
|
|
* *<p lplpSti>.
|
|
* <enew>
|
|
*
|
|
* @parm IN HINSTANCE | hinst |
|
|
*
|
|
* Instance handle of the application or DLL that is creating
|
|
* the Sti object.
|
|
*
|
|
* Sti uses this value to determine whether the
|
|
* application or DLL has been certified.
|
|
*
|
|
* @parm DWORD | dwVersion |
|
|
*
|
|
* Version number of the sti.h header file that was used.
|
|
* This value must be <c STI_VERSION>.
|
|
*
|
|
* Sti uses this value to determine what version of
|
|
* Sti the application or DLL was designed for.
|
|
*
|
|
* @parm OUT LPSti * | lplpSti |
|
|
* Points to where to return
|
|
* the pointer to the <i ISti> interface, if successful.
|
|
*
|
|
* @parm IN LPUNKNOWN | punkOuter | Pointer to controlling unknown
|
|
* for OLE aggregation, or 0 if the interface is not aggregated.
|
|
* Most callers will pass 0.
|
|
*
|
|
* Note that if aggregation is requested, the object returned
|
|
* in *<p lplpSti> will be a pointer to an
|
|
* <i IUnknown> rather than an <i ISti>, as required
|
|
* by OLE aggregation.
|
|
*
|
|
* @returns
|
|
*
|
|
* Returns a COM error code. The following error codes are
|
|
* intended to be illustrative and not necessarily comprehensive.
|
|
*
|
|
* <c STI_OK> = <c S_OK>: The operation completed successfully.
|
|
*
|
|
* <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
|
|
* <p lplpSti> parameter is not a valid pointer.
|
|
*
|
|
* <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
|
|
* Out of memory.
|
|
*
|
|
* <c STIERR_STIERR_OLDStiVERSION>: The application
|
|
* requires a newer version of Sti.
|
|
*
|
|
* <c STIERR_STIERR_BETAStiVERSION>: The application
|
|
* was written for an unsupported prerelease version
|
|
* of Sti.
|
|
*
|
|
* @comm Calling this function with <p punkOuter> = NULL
|
|
* is equivalent to creating the object via
|
|
* <f CoCreateInstance>(&CLSID_Sti, <p punkOuter>,
|
|
* CLSCTX_INPROC_SERVER, &IID_ISti, <p lplpSti>);
|
|
* then initializing it with <f Initialize>.
|
|
*
|
|
* Calling this function with <p punkOuter> != NULL
|
|
* is equivalent to creating the object via
|
|
* <f CoCreateInstance>(&CLSID_Sti, <p punkOuter>,
|
|
* CLSCTX_INPROC_SERVER, &IID_IUnknown, <p lplpSti>).
|
|
* The aggregated object must be initialized manually.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDMETHODIMP
|
|
StiCreateInstanceW(HINSTANCE hinst, DWORD dwVer, PSTI *ppSti, PUNK punkOuter)
|
|
{
|
|
HRESULT hres;
|
|
EnterProc(StiCreateInstance, (_ "xxx", hinst, dwVer, punkOuter));
|
|
|
|
hres = StiCreateHelper(hinst, dwVer, (PPV)ppSti, punkOuter,&IID_IStillImageW);
|
|
|
|
ExitOleProcPpv(ppSti);
|
|
return hres;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
StiCreateInstanceA(HINSTANCE hinst, DWORD dwVer, PSTIA *ppSti, PUNK punkOuter)
|
|
{
|
|
HRESULT hres;
|
|
EnterProc(StiCreateInstance, (_ "xxx", hinst, dwVer, punkOuter));
|
|
|
|
hres = StiCreateHelper(hinst, dwVer, (PPV)ppSti, punkOuter,&IID_IStillImageA);
|
|
|
|
ExitOleProcPpv(ppSti);
|
|
return hres;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULT | DllInitializeCOM |
|
|
*
|
|
* Initialize COM libraries
|
|
*
|
|
* @parm IN | |
|
|
*
|
|
* @returns
|
|
*
|
|
* Returns a boolean error code.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL
|
|
EXTERNAL
|
|
DllInitializeCOM(
|
|
void
|
|
)
|
|
{
|
|
DllEnterCrit();
|
|
|
|
if(!g_COMInitialized) {
|
|
#ifdef USE_REAL_OLE32
|
|
if(SUCCEEDED(CoInitializeEx(NULL,
|
|
COINIT_MULTITHREADED |
|
|
COINIT_DISABLE_OLE1DDE))
|
|
) {
|
|
g_COMInitialized = TRUE;
|
|
}
|
|
#else
|
|
g_COMInitialized = TRUE;
|
|
#endif
|
|
}
|
|
|
|
DllLeaveCrit();
|
|
|
|
return g_COMInitialized;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func HRESULT | DllUnInitializeCOM |
|
|
*
|
|
* UnInitialize COM libraries
|
|
*
|
|
* @parm IN | |
|
|
*
|
|
* @returns
|
|
*
|
|
* Returns a boolean error code.
|
|
*
|
|
*****************************************************************************/
|
|
BOOL EXTERNAL
|
|
DllUnInitializeCOM(
|
|
void
|
|
)
|
|
{
|
|
DllEnterCrit();
|
|
|
|
#ifdef USE_REAL_OLE32
|
|
if(g_COMInitialized) {
|
|
CoUninitialize();
|
|
g_COMInitialized = FALSE;
|
|
}
|
|
#endif
|
|
|
|
DllLeaveCrit();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @func VOID | RegSTIforWia |
|
|
*
|
|
* Private server entry point to register STI apps for WIA events
|
|
*
|
|
* @parm IN | |
|
|
*
|
|
* @returns
|
|
*
|
|
* VOID
|
|
*
|
|
*****************************************************************************/
|
|
|
|
VOID
|
|
EXTERNAL
|
|
RegSTIforWia(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
|
{
|
|
RegSTIforWiaHelper(hwnd, hinst, lpszCmdLine, nCmdShow);
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
MigrateRegisteredSTIAppsForWIAEvents(
|
|
HWND hWnd,
|
|
HINSTANCE hInst,
|
|
PTSTR pszCommandLine,
|
|
INT iParam
|
|
)
|
|
{
|
|
MigrateSTIAppsHelper(hWnd,
|
|
hInst,
|
|
pszCommandLine,
|
|
iParam);
|
|
}
|
|
|