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.
397 lines
11 KiB
397 lines
11 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: dllinit.c *
|
|
* *
|
|
* Contains the GDI library initialization routines. *
|
|
* *
|
|
* Created: 07-Nov-1990 13:30:31 *
|
|
* Author: Eric Kutter [erick] *
|
|
* *
|
|
* Copyright (c) 1990-1999 Microsoft Corporation *
|
|
\**************************************************************************/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "glsup.h"
|
|
|
|
extern PVOID pAFRTNodeList;
|
|
extern VOID vSetCheckDBCSTrailByte(DWORD dwCodePage);
|
|
NTSTATUS GdiProcessSetup();
|
|
VOID GdiProcessShutdown();
|
|
|
|
#ifdef LANGPACK
|
|
#include "winuserp.h"
|
|
#endif
|
|
|
|
HBRUSH ghbrDCBrush;
|
|
HPEN ghbrDCPen;
|
|
|
|
BOOL gbWOW64 = FALSE;
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GdiDllInitialize *
|
|
* *
|
|
* This is the init procedure for GDI.DLL, which is called each time a new *
|
|
* process links to it. *
|
|
* *
|
|
* History: *
|
|
* Thu 30-May-1991 18:08:00 -by- Charles Whitmer [chuckwh] *
|
|
* Added Local Handle Table initialization. *
|
|
\**************************************************************************/
|
|
|
|
#if defined(_GDIPLUS_)
|
|
|
|
//
|
|
// The following are globals kept in 'gre':
|
|
//
|
|
|
|
extern PGDI_SHARED_MEMORY gpGdiSharedMemory;
|
|
extern PENTRY gpentHmgr;
|
|
extern PDEVCAPS gpGdiDevCaps;
|
|
|
|
#endif
|
|
|
|
PGDI_SHARED_MEMORY pGdiSharedMemory = NULL;
|
|
PENTRY pGdiSharedHandleTable = NULL;
|
|
PDEVCAPS pGdiDevCaps = NULL;
|
|
W32PID gW32PID;
|
|
UINT guintAcp;
|
|
UINT guintDBCScp;
|
|
|
|
PGDIHANDLECACHE pGdiHandleCache;
|
|
|
|
BOOL gbFirst = TRUE;
|
|
|
|
#ifdef LANGPACK
|
|
BOOL gbLpk = FALSE;
|
|
FPLPKEXTEXTOUT fpLpkExtTextOut;
|
|
FPLPKGETCHARACTERPLACEMENT fpLpkGetCharacterPlacement;
|
|
FPLPKGETTEXTEXTENTEXPOINT fpLpkGetTextExtentExPoint;
|
|
FPLPKUSEGDIWIDTHCACHE fpLpkUseGDIWidthCache;
|
|
|
|
VOID GdiInitializeLanguagePack(DWORD);
|
|
#endif
|
|
|
|
NTSTATUS GdiDllInitialize(
|
|
PVOID pvDllHandle,
|
|
ULONG ulReason)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
INT i;
|
|
PTEB pteb = NtCurrentTeb();
|
|
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DisableThreadLibraryCalls(pvDllHandle);
|
|
|
|
//
|
|
// force the kernel to initialize. This should be done last
|
|
// since ClientThreadSetup is going to get called before this returns.
|
|
//
|
|
|
|
if (NtGdiInit() != TRUE)
|
|
{
|
|
return(STATUS_NO_MEMORY);
|
|
}
|
|
|
|
Status = GdiProcessSetup();
|
|
|
|
ghbrDCBrush = GetStockObject (DC_BRUSH);
|
|
ghbrDCPen = GetStockObject (DC_PEN);
|
|
|
|
#ifdef BUILD_WOW6432
|
|
gbWOW64 = TRUE;
|
|
#endif
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
GdiProcessShutdown();
|
|
break;
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GdiProcessSetup()
|
|
*
|
|
* This gets called from two places. Once at dll init time and another when
|
|
* USER gets called back when the kernel initializes itself for this process.
|
|
* It is only after the kernel is initialized that the GdiSharedHandleTable
|
|
* is available but the other globals need to be setup right away.
|
|
*
|
|
* History:
|
|
* 11-Sep-1995 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
NTSTATUS GdiProcessSetup()
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PTEB pteb = NtCurrentTeb();
|
|
|
|
// who ever calls this first needs to initialize the global variables.
|
|
|
|
if (gbFirst)
|
|
{
|
|
//
|
|
// Initialize the GL metafile support semaphore
|
|
//
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semGlLoad);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Initialize the local semaphore and reserve the Local Handle Table
|
|
// for the process.
|
|
//
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semLocal);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Initialize critical sections for ICM
|
|
//
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semListIcmInfo);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semColorTransformCache);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semColorSpaceCache);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// Initialize critical section for UMPD
|
|
//
|
|
|
|
Status = (NTSTATUS)INITIALIZECRITICALSECTION(&semUMPD);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
WARNING("InitializeCriticalSection failed\n");
|
|
return(Status);
|
|
}
|
|
|
|
pAFRTNodeList = NULL;
|
|
guintAcp = GetACP();
|
|
|
|
if(IS_ANY_DBCS_CODEPAGE(guintAcp))
|
|
{
|
|
// if the default code page is a DBCS code page then set guintACP to 1252
|
|
// since we want to compute client wide widths for SBCS fonts for code page
|
|
// 1252 in addition to DBCS fonts for the default code page
|
|
|
|
vSetCheckDBCSTrailByte(guintAcp);
|
|
guintDBCScp = guintAcp;
|
|
guintAcp = 1252;
|
|
}
|
|
else
|
|
{
|
|
guintDBCScp = 0xFFFFFFFF; // assume this will never be a valid CP
|
|
}
|
|
|
|
#ifdef FE_SB
|
|
fFontAssocStatus = NtGdiQueryFontAssocInfo(NULL);
|
|
#endif
|
|
|
|
// assign unique process ID
|
|
|
|
gW32PID = (W32PID)((ULONG)((ULONG_PTR)pteb->ClientId.UniqueProcess & PID_BITS));
|
|
|
|
#ifdef LANGPACK
|
|
if(((PGDI_SHARED_MEMORY) NtCurrentPebShared()->GdiSharedHandleTable)->dwLpkShapingDLLs)
|
|
{
|
|
GdiInitializeLanguagePack(
|
|
((PGDI_SHARED_MEMORY)
|
|
NtCurrentPebShared()->GdiSharedHandleTable)->dwLpkShapingDLLs);
|
|
}
|
|
#endif
|
|
|
|
gbFirst = FALSE;
|
|
|
|
//
|
|
// ICM has not been initialized
|
|
//
|
|
|
|
ghICM = NULL;
|
|
|
|
InitializeListHead(&ListIcmInfo);
|
|
InitializeListHead(&ListCachedColorSpace);
|
|
InitializeListHead(&ListCachedColorTransform);
|
|
}
|
|
|
|
// The pshared handle table needs to be set everytime this routine gets
|
|
// called in case the PEB doesn't have it yet for the first.
|
|
|
|
#if !defined(_GDIPLUS_)
|
|
|
|
pGdiSharedMemory = (PGDI_SHARED_MEMORY) NtCurrentPebShared()->GdiSharedHandleTable;
|
|
pGdiSharedHandleTable = pGdiSharedMemory->aentryHmgr;
|
|
pGdiDevCaps = &pGdiSharedMemory->DevCaps;
|
|
|
|
if (GetAppCompatFlags2(VER40) & GACF2_NOBATCHING)
|
|
{
|
|
GdiBatchLimit = 0;
|
|
}
|
|
else
|
|
{
|
|
GdiBatchLimit = (NtCurrentPebShared()->GdiDCAttributeList) & 0xff;
|
|
}
|
|
|
|
pGdiHandleCache = (PGDIHANDLECACHE)(&NtCurrentPebShared()->GdiHandleBuffer[0]);
|
|
|
|
#else
|
|
|
|
pGdiSharedMemory = gpGdiSharedMemory;
|
|
pGdiSharedHandleTable = gpentHmgr;
|
|
pGdiDevCaps = gpGdiDevCaps;
|
|
|
|
//
|
|
// Be sure to disable batching and handle caching.
|
|
//
|
|
|
|
GdiBatchLimit = 0;
|
|
pGdiHandleCache = NULL;
|
|
|
|
#endif
|
|
|
|
// @@@ Add TrueType fonts
|
|
|
|
#if defined(_GDIPLUS_)
|
|
|
|
AddFontResourceW(L"arial.ttf");
|
|
AddFontResourceW(L"cour.ttf");
|
|
|
|
#endif // _GDIPLUS_
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GdiProcessShutdown()
|
|
*
|
|
* Historically, gdi32.dll has allowed process termination to release the
|
|
* user-mode resources. However, some apps may use LoadLibrary/FreeLibrary
|
|
* to hook gdi32.dll, in which case the FreeLibrary will not free any of
|
|
* the resources.
|
|
*
|
|
* As a system component, we should do a good job and cleanup after ourselves
|
|
* instead of relying on process termination.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GdiProcessShutdown()
|
|
{
|
|
if (gbWOW64)
|
|
{
|
|
vUMPDWow64Shutdown();
|
|
}
|
|
DELETECRITICALSECTION(&semUMPD);
|
|
DELETECRITICALSECTION(&semColorSpaceCache);
|
|
DELETECRITICALSECTION(&semColorTransformCache);
|
|
DELETECRITICALSECTION(&semListIcmInfo);
|
|
DELETECRITICALSECTION(&semLocal);
|
|
DELETECRITICALSECTION(&semGlLoad);
|
|
}
|
|
|
|
|
|
#ifdef LANGPACK
|
|
VOID GdiInitializeLanguagePack(DWORD dwLpkShapingDLLs)
|
|
{
|
|
FPLPKINITIALIZE fpLpkInitialize;
|
|
|
|
HANDLE hLpk = LoadLibraryW(L"LPK.DLL");
|
|
|
|
if (hLpk != NULL)
|
|
{
|
|
FARPROC fpUser[4];
|
|
|
|
fpLpkInitialize = (FPLPKINITIALIZE)
|
|
GetProcAddress(hLpk,"LpkInitialize");
|
|
|
|
fpLpkExtTextOut = (FPLPKEXTEXTOUT)
|
|
GetProcAddress(hLpk,"LpkExtTextOut");
|
|
|
|
fpLpkGetCharacterPlacement = (FPLPKGETCHARACTERPLACEMENT)
|
|
GetProcAddress(hLpk,"LpkGetCharacterPlacement");
|
|
|
|
|
|
fpLpkGetTextExtentExPoint = (FPLPKGETTEXTEXTENTEXPOINT)
|
|
GetProcAddress(hLpk,"LpkGetTextExtentExPoint");
|
|
|
|
fpLpkUseGDIWidthCache = (FPLPKUSEGDIWIDTHCACHE)
|
|
GetProcAddress(hLpk,"LpkUseGDIWidthCache");
|
|
|
|
fpUser[LPK_TABBED_TEXT_OUT] =
|
|
GetProcAddress(hLpk,"LpkTabbedTextOut");
|
|
|
|
|
|
fpUser[LPK_PSM_TEXT_OUT] =
|
|
GetProcAddress(hLpk,"LpkPSMTextOut");
|
|
|
|
|
|
fpUser[LPK_DRAW_TEXT_EX] =
|
|
GetProcAddress(hLpk,"LpkDrawTextEx");
|
|
|
|
fpUser[LPK_EDIT_CONTROL] =
|
|
GetProcAddress(hLpk,"LpkEditControl");
|
|
|
|
|
|
if(fpLpkInitialize &&
|
|
fpLpkExtTextOut &&
|
|
fpLpkGetCharacterPlacement &&
|
|
fpLpkGetTextExtentExPoint &&
|
|
fpLpkUseGDIWidthCache &&
|
|
fpUser[LPK_TABBED_TEXT_OUT] &&
|
|
fpUser[LPK_PSM_TEXT_OUT] &&
|
|
fpUser[LPK_DRAW_TEXT_EX] &&
|
|
fpUser[LPK_EDIT_CONTROL])
|
|
{
|
|
if((*fpLpkInitialize)(dwLpkShapingDLLs))
|
|
{
|
|
gbLpk = TRUE;
|
|
InitializeLpkHooks(fpUser);
|
|
}
|
|
else
|
|
{
|
|
WARNING("gdi32: LPK initialization routine return FALSE\n");
|
|
FreeLibrary(hLpk);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("gdi32: one or more require LPK functions missing\n");
|
|
FreeLibrary(hLpk);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("gdi32: unable to load LPK\n");
|
|
}
|
|
|
|
}
|
|
#endif
|