windows-nt/Source/XPSP1/NT/base/pnp/setupapi/fusion.c
2020-09-26 16:20:57 +08:00

669 lines
15 KiB
C

/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
fusion.c
Abstract:
Wrappers and functions for fusionizing SetupAPI
without effecting 3rd party DLL's
and without dll-load overhead
Author:
Jamie Hunter (JamieHun) 12/4/2000
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#ifdef FUSIONAWARE
#undef CreateWindow
#undef CreateWindowEx
#undef CreateDialogParam
#undef CreateDialogIndirectParam
#undef DialogBoxParam
#undef DialogBoxIndirectParam
#undef MessageBox
#undef CreatePropertySheetPage
#undef DestroyPropertySheetPage
#undef PropertySheet
#undef ImageList_Create
#undef ImageList_Destroy
#undef ImageList_GetImageCount
#undef ImageList_SetImageCount
#undef ImageList_Add
#undef ImageList_ReplaceIcon
#undef ImageList_SetBkColor
#undef ImageList_GetBkColor
#undef ImageList_SetOverlayImage
#include <shfusion.h>
static CRITICAL_SECTION spFusionInitCritSec;
static BOOL spInitFusionCritSec = FALSE;
static BOOL spFusionDoneInit = FALSE;
BOOL spFusionInitialize()
/*++
Routine Description:
Called on DllLoad
do minimum possible
Arguments:
none
Return Value:
TRUE successful initialization
--*/
{
try {
InitializeCriticalSection(&spFusionInitCritSec);
spInitFusionCritSec = TRUE;
} except (EXCEPTION_EXECUTE_HANDLER) {
//
// spInitFusionCritSec remains FALSE
//
}
return spInitFusionCritSec;
}
VOID
spFusionInitLong()
/*++
Routine Description:
Called by internal stub to do real initialization
Arguments:
none
Return Value:
none
--*/
{
BOOL locked = FALSE;
BOOL success = FALSE;
INITCOMMONCONTROLSEX CommCtrl;
if(!spInitFusionCritSec) {
//
// critical section not initialized
// probably out of memory
// bail
//
MYASSERT(spInitFusionCritSec);
spFusionDoneInit = TRUE;
return;
}
try {
EnterCriticalSection(&spFusionInitCritSec);
locked = TRUE;
} except(EXCEPTION_EXECUTE_HANDLER) {
}
if(!locked) {
//
// wasn't able to grab lock - probably out of memory
// bail
//
spFusionDoneInit = TRUE;
return;
}
if(spFusionDoneInit) {
//
// by the time we grabbed critical section
// initialization was done
// bail
//
LeaveCriticalSection(&spFusionInitCritSec);
return;
}
//
// call shell's fusion enabler
//
success = SHFusionInitializeFromModuleID(MyDllModuleHandle,IDR_MANIFEST);
MYASSERT(success);
ZeroMemory(&CommCtrl,sizeof(CommCtrl));
CommCtrl.dwSize = sizeof(CommCtrl);
CommCtrl.dwICC = ICC_WIN95_CLASSES | ICC_LINK_CLASS;
success = InitCommonControlsEx(&CommCtrl);
MYASSERT(success);
//
// at this point, it's now safe for anyone else to assume initialization is done
// even if we haven't released critical section
//
spFusionDoneInit = TRUE;
LeaveCriticalSection(&spFusionInitCritSec);
}
__inline
VOID
spFusionCheckInit()
/*++
Routine Description:
Calls spFusionInitLong iff needed
Arguments:
none
Return Value:
none
--*/
{
if(!spFusionDoneInit) {
//
// either not initialized, or currently going through initialization
//
spFusionInitLong();
}
}
BOOL spFusionUninitialize(BOOL Full)
/*++
Routine Description:
Called at DLL exit (if DLL being unloaded but not process Exit)
Arguments:
none
Return Value:
TRUE successful cleanup
--*/
{
//
// cleanup anything initialized at spFusionInitialize
//
if(spInitFusionCritSec) {
DeleteCriticalSection(&spFusionInitCritSec);
spInitFusionCritSec = FALSE;
}
if(Full && spFusionDoneInit) {
SHFusionUninitialize();
}
return TRUE;
}
//
// generic functions for dealing with 3rd party DLL's
// that might be fusionized
//
HANDLE
spFusionContextFromModule(
IN PCTSTR ModuleName
)
/*++
Routine Description:
Called to get a fusion context for specified module name
given blah.dll look for
1) blah.dll.manifest in same directory as blah.dll
2) blah.dll with a fusion resource ID 123.
If either of these provide a valid manifest, use it
otherwise use app global manifest.
Arguments:
name of module that'll later be passed into LoadLibrary
Return Value:
fusion context
--*/
{
ACTCTX act = { 0 };
HANDLE hContext;
TCHAR ManifestName[MAX_PATH+10];
PTSTR End;
DWORD len;
act.cbSize = sizeof(act);
//
// based loosely on rundll32 code
// however we look for manifest in same directory as the dll
// so look for dll first
//
len = SearchPath(NULL,ModuleName,NULL,MAX_PATH,ManifestName,NULL);
if(len>=MAX_PATH) {
//
// path length of DLL too big, just use global context
//
goto deflt;
}
if(!len) {
len = lstrlen(ModuleName);
if(len>=MAX_PATH) {
goto deflt;
}
lstrcpy(ManifestName,ModuleName);
}
if(GetFileAttributes(ManifestName) == -1) {
//
// didn't find DLL?
//
goto deflt;
}
lstrcpy(ManifestName+len,TEXT(".Manifest"));
if(GetFileAttributes(ManifestName) != -1) {
//
// found manifest
//
act.lpSource = ManifestName;
act.dwFlags = 0;
hContext = CreateActCtx(&act);
if(hContext != INVALID_HANDLE_VALUE) {
//
// we created context based on manifest file
//
return hContext;
}
}
deflt:
//
// if the dll has a manifest resource
// then use that
//
act.lpSource = ModuleName;
// act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
// act.lpResourceName = MAKEINTRESOURCE(123);
act.dwFlags = 0;
hContext = CreateActCtx(&act);
if(hContext != INVALID_HANDLE_VALUE) {
//
// we created context based on resource
//
return hContext;
}
//
// if we couldn't find an alternative, use app-global
//
return NULL;
}
BOOL
spFusionKillContext(
IN HANDLE hContext
)
/*++
Routine Description:
Release a context previously obtained by
spFusionContextFromModule
Arguments:
fusion context
Return Value:
TRUE (always)
--*/
{
if(hContext) {
ReleaseActCtx(hContext);
}
return TRUE;
}
BOOL
spFusionEnterContext(
IN HANDLE hContext,
OUT PSPFUSIONINSTANCE pInst
)
/*++
Routine Description:
Enter into a manifest context
status of call is saved into pInst
so that return value does not need
to be checked
Arguments:
hContext = fusion context
pInst = structure to save the "push" information
Return Value:
TRUE if success, FALSE otherwise
--*/
{
pInst->Acquired = ActivateActCtx(hContext,&pInst->Cookie);
MYASSERT(pInst->Acquired);
return pInst->Acquired;
}
BOOL
spFusionLeaveContext(
IN PSPFUSIONINSTANCE pInst
)
/*++
Routine Description:
If pInst indicates that spFusionEnterContext
succeeded, leave same context
Arguments:
pInst = structure initialized by spFusionEnterContext
Return Value:
TRUE if spFusionEnterContext succeeded, FALSE otherwise
--*/
{
if(pInst->Acquired) {
pInst->Acquired = FALSE;
DeactivateActCtx(0,pInst->Cookie);
return TRUE;
} else {
return FALSE;
}
}
HWND spFusionCreateWindow(
LPCTSTR lpClassName, // registered class name
LPCTSTR lpWindowName, // window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // menu handle or child identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // window-creation data
)
{
spFusionCheckInit();
return SHFusionCreateWindow(lpClassName,
lpWindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam
);
}
HWND spFusionCreateWindowEx(
DWORD dwExStyle, // extended window style
LPCTSTR lpClassName, // registered class name
LPCTSTR lpWindowName, // window name
DWORD dwStyle, // window style
int x, // horizontal position of window
int y, // vertical position of window
int nWidth, // window width
int nHeight, // window height
HWND hWndParent, // handle to parent or owner window
HMENU hMenu, // menu handle or child identifier
HINSTANCE hInstance, // handle to application instance
LPVOID lpParam // window-creation data
)
{
spFusionCheckInit();
return SHFusionCreateWindowEx(dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam
);
}
HWND spFusionCreateDialogParam(
HINSTANCE hInstance, // handle to module
LPCTSTR lpTemplateName, // dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // dialog box procedure
LPARAM dwInitParam // initialization value
)
{
spFusionCheckInit();
return SHFusionCreateDialogParam(
hInstance,
lpTemplateName,
hWndParent,
lpDialogFunc,
dwInitParam
);
}
HWND spFusionCreateDialogIndirectParam(
HINSTANCE hInstance, // handle to module
LPCDLGTEMPLATE lpTemplate, // dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // dialog box procedure
LPARAM lParamInit // initialization value
)
{
spFusionCheckInit();
return SHFusionCreateDialogIndirectParam(
hInstance,
lpTemplate,
hWndParent,
lpDialogFunc,
lParamInit
);
}
INT_PTR spFusionDialogBoxParam(
HINSTANCE hInstance, // handle to module
LPCTSTR lpTemplateName, // dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // dialog box procedure
LPARAM dwInitParam // initialization value
)
{
spFusionCheckInit();
return SHFusionDialogBoxParam(
hInstance,
lpTemplateName,
hWndParent,
lpDialogFunc,
dwInitParam
);
}
INT_PTR spFusionDialogBoxIndirectParam(
HINSTANCE hInstance, // handle to module
LPCDLGTEMPLATE hDialogTemplate, // dialog box template
HWND hWndParent, // handle to owner window
DLGPROC lpDialogFunc, // dialog box procedure
LPARAM dwInitParam // initialization value
)
{
spFusionCheckInit();
return SHFusionDialogBoxIndirectParam(
hInstance,
hDialogTemplate,
hWndParent,
lpDialogFunc,
dwInitParam
);
}
int spFusionMessageBox(
IN HWND hWnd,
IN LPCTSTR lpText,
IN LPCTSTR lpCaption,
IN UINT uType
)
{
ULONG_PTR dwCookie;
BOOL act;
int iRes = 0;
spFusionCheckInit();
act = SHActivateContext(&dwCookie);
try {
iRes = MessageBoxW(
hWnd,
lpText,
lpCaption,
uType
);
} finally {
if(act) {
SHDeactivateContext(dwCookie);
}
}
return iRes;
}
INT_PTR spFusionPropertySheet(
LPCPROPSHEETHEADER pPropSheetHeader
)
{
spFusionCheckInit();
return PropertySheetW(pPropSheetHeader);
}
HPROPSHEETPAGE spFusionCreatePropertySheetPage(
LPPROPSHEETPAGE pPropSheetPage
)
{
spFusionCheckInit();
MYASSERT(pPropSheetPage->dwFlags & PSP_USEFUSIONCONTEXT);
MYASSERT(!pPropSheetPage->hActCtx);
MYASSERT(pPropSheetPage->dwSize >= sizeof(PROPSHEETPAGE));
return CreatePropertySheetPageW(pPropSheetPage);
}
BOOL spFusionDestroyPropertySheetPage(
HPROPSHEETPAGE hPropSheetPage
)
{
spFusionCheckInit();
return DestroyPropertySheetPage(
hPropSheetPage
);
}
HIMAGELIST spFusionImageList_Create(int cx, int cy, UINT flags, int cInitial, int cGrow)
{
spFusionCheckInit();
return ImageList_Create(
cx,
cy,
flags,
cInitial,
cGrow
);
}
BOOL spFusionImageList_Destroy(HIMAGELIST himl)
{
spFusionCheckInit();
return ImageList_Destroy(
himl
);
}
int spFusionImageList_Add(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
{
spFusionCheckInit();
return ImageList_Add(
himl,
hbmImage,
hbmMask
);
}
int spFusionImageList_ReplaceIcon(HIMAGELIST himl, int i, HICON hicon)
{
spFusionCheckInit();
return ImageList_ReplaceIcon(
himl,
i,
hicon
);
}
COLORREF spFusionImageList_SetBkColor(HIMAGELIST himl, COLORREF clrBk)
{
spFusionCheckInit();
return ImageList_SetBkColor(
himl,
clrBk
);
}
BOOL spFusionImageList_SetOverlayImage(HIMAGELIST himl, int iImage, int iOverlay)
{
spFusionCheckInit();
return ImageList_SetOverlayImage(
himl,
iImage,
iOverlay
);
}
BOOL spFusionGetOpenFileName(LPOPENFILENAME lpofn)
{
spFusionCheckInit();
return GetOpenFileNameW(lpofn);
}
#endif // FUSIONAWARE