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.
 
 
 
 
 
 

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);
}