/******************************Module*Header*******************************\ * Module Name: init.cxx * * Engine initialization * * Copyright (c) 1990-1999 Microsoft Corporation \**************************************************************************/ #include "precomp.hxx" #include "verifier.hxx" #include "winsta.h" extern "C" USHORT gProtocolType; BOOLEAN gIsTerminalServer; extern BOOL G_fConsole; extern BOOL G_fDoubleDpi; extern "C" BOOL bInitPALOBJ(); // palobj.cxx extern "C" VOID vInitXLATE(); // ylateobj.cxx extern "C" BOOL bInitBMOBJ(); // surfeng.cxx extern "C" BOOL InitializeScripts(); // fontsup.cxx extern "C" BOOL bInitICM(); // icmapi.cxx extern "C" BOOL bInitFontTables(); // pftobj.cxx extern "C" BOOL bInitStockFonts(VOID); // stockfnt.cxx extern "C" VOID vInitFontSubTable(); // fontsub.cxx extern "C" BOOL bInitBRUSHOBJ(); // brushobj.cxx extern "C" VOID vInitMapper(); // fontmap.cxx extern USHORT GetLanguageID(); // Prototypes from font drivers. extern "C" BOOL BmfdEnableDriver(ULONG iEngineVersion,ULONG cj, PDRVENABLEDATA pded); extern "C" BOOL ttfdEnableDriver(ULONG iEngineVersion,ULONG cj, PDRVENABLEDATA pded); extern "C" BOOL vtfdEnableDriver(ULONG iEngineVersion,ULONG cj, PDRVENABLEDATA pded); extern "C" BOOL atmfdEnableDriver(ULONG iEngineVersion,ULONG cj, PDRVENABLEDATA pded); extern "C" NTSTATUS FontDriverQueryRoutine( IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext ); extern "C" BOOL bRegisterFontServer(VOID); extern "C" BOOL bUserModeFontDrivers(VOID); #ifdef LANGPACK extern "C" NTSTATUS LpkShapeQueryRoutine( IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext ); #endif // // Prototypes from halftone // extern "C" BOOL PASCAL EnableHalftone(VOID); extern "C" VOID PASCAL DisableHalftone(VOID); // // Hydra prototypes // extern "C" BOOL MultiUserGreCleanupInit(); extern "C" BOOL GreEngLoadModuleTrackInit(); // // Functions are located in INIT segment // #pragma alloc_text(INIT, InitializeGre) #pragma alloc_text(INIT, FontDriverQueryRoutine) #ifdef LANGPACK #pragma alloc_text(INIT, LpkShapeQueryRoutine) #endif #pragma alloc_text(INIT, bLoadProcessHandleQuota) #pragma alloc_text(INIT, bRegisterFontServer) /**************************************************************************\ * \**************************************************************************/ #if defined(i386) && !defined(_GDIPLUS_) extern "C" PVOID GDIpLockPrefixTable; extern "C" PVOID __safe_se_handler_table[]; /* base of safe handler entry table */ extern "C" BYTE __safe_se_handler_count; /* absolute symbol whose address is the count of table entries */ // // Specify address of kernel32 lock prefixes // extern "C" IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { sizeof(_load_config_used), // Reserved 0, // Reserved 0, // Reserved 0, // Reserved 0, // GlobalFlagsClear 0, // GlobalFlagsSet 0, // CriticalSectionTimeout (milliseconds) 0, // DeCommitFreeBlockThreshold 0, // DeCommitTotalFreeThreshold (ULONG) &GDIpLockPrefixTable, // LockPrefixTable 0, 0, 0, 0, 0, 0, 0, // Reserved 0, // & security_cookie (ULONG)__safe_se_handler_table, (ULONG)&__safe_se_handler_count }; #endif LONG gProcessHandleQuota; #if defined (_X86_) BOOL gbMMXProcessor = FALSE; #endif extern "C" VOID vConvertCodePageToCharSet(WORD src, DWORD *pfsRet, BYTE *pjRet); VOID vGetJpn98FixPitch(); /******************************Public*Routine******************************\ * bEnableFontDriver * * Enables an internal, statically-linked font driver. * \**************************************************************************/ BOOL bEnableFontDriver(PFN pfnFdEnable, ULONG fl) { // // Load driver. // PLDEV pldev; pldev = ldevLoadInternal(pfnFdEnable, LDEV_FONT); // // Validate the new LDEV // if (pldev) { // // Create the PDEV for this (the PDEV won't have anything in it // except the dispatch table. // PDEVOBJ po(pldev, NULL, // PDEVMODEW pdriv, NULL, // PWSZ pwszLogAddr, NULL, // PWSZ pwszDataFile, NULL, // PWSZ pwszDeviceName, NULL, // HANDLE hSpool, NULL // PREMOTETYPEONENODE pRemoteTypeOne, ); if (po.bValid()) { // // Was it the TrueType driver? We need to keep a global handle to // it to support the Win 3.1 TrueType-specific calls. // if (fl & FNT_TT_DRV ) { gppdevTrueType = (PPDEV) po.hdev(); } if (fl & FNT_OT_DRV) { gppdevATMFD = (PPDEV) po.hdev(); gufiLocalType1Rasterizer.CheckSum = TYPE1_RASTERIZER; gufiLocalType1Rasterizer.Index = 0x1; } FntCacheHDEV((PPDEV) po.hdev(), fl); po.ppdev->fl |= PDEV_FONTDRIVER; return(TRUE); } } WARNING("bLoadFontDriver failed\n"); return(FALSE); } /******************************Public*Routine******************************\ * bDoubleDpi * * Read the registry to determine if we should implement our double-the-DPI * hack. This functionality was intended as a simple mechanism for the * release of Windows 2000 for applications developers to test their * applications for conformance with upcoming high-DPI (200 DPI) displays. * The problem is that currently only 75 to 100 DPI displays are available, * but we know the high DPI displays are coming soon. * * So we implement this little hack that doubles the effective resolution * of the monitor, and down-samples to the display. So if your monitor does * 1024x768, we make the system think it's really 2048x1536. * * Hopefully, this hacky functionality can be removed for the release after * Windows 2000, as it's fairly unusable for anything other than simple * test purposes. * \**************************************************************************/ BOOL bDoubleDpi(BOOL fConsole) { HANDLE hkRegistry; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; NTSTATUS status; DWORD Length; PKEY_VALUE_FULL_INFORMATION Information; DWORD dwDoubleDpi; dwDoubleDpi = 0; ///For this to success, it must be console session(session 0) ///Connected locally to physical console. if (fConsole && (gProtocolType == PROTOCOL_CONSOLE)) { RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\System\\CurrentControlSet\\" L"Control\\GraphicsDrivers"); InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwOpenKey(&hkRegistry, GENERIC_READ, &ObjectAttributes); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&UnicodeString, L"DoubleDpi"); Length = sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(L"DoubleDpi") + sizeof(DWORD); Information = (PKEY_VALUE_FULL_INFORMATION) PALLOCMEM(Length, ' ddG'); if (Information) { status = ZwQueryValueKey(hkRegistry, &UnicodeString, KeyValueFullInformation, Information, Length, &Length); if (NT_SUCCESS(status)) { dwDoubleDpi = *(LPDWORD) ((((PUCHAR)Information) + Information->DataOffset)); } VFREEMEM(Information); } ZwCloseKey(hkRegistry); } } return(dwDoubleDpi == 1); } void vCheckTimeZoneBias() { HANDLE hkRegistry; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; NTSTATUS status; DWORD Length; PKEY_VALUE_FULL_INFORMATION Information; RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\System\\CurrentControlSet\\" L"Control\\TimeZoneInformation"); InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwOpenKey(&hkRegistry, GENERIC_READ, &ObjectAttributes); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&UnicodeString, L"ActiveTimeBias"); Length = sizeof(KEY_VALUE_FULL_INFORMATION) + sizeof(L"ActiveTimeBias") + sizeof(DWORD); Information = (PKEY_VALUE_FULL_INFORMATION) PALLOCMEM(Length, 'pmtG'); if (Information) { status = ZwQueryValueKey(hkRegistry, &UnicodeString, KeyValueFullInformation, Information, Length, &Length); if (!NT_SUCCESS(status)) { gbGUISetup = TRUE; } VFREEMEM(Information); } ZwCloseKey(hkRegistry); } else { gbGUISetup = TRUE; } } /******************************Public*Routine******************************\ * InitializeGreCSRSS * * Initialize the client-server subsystem portion of GDI. * \**************************************************************************/ extern "C" BOOL InitializeGreCSRSS() { // Init DirectX graphics driver if (!NT_SUCCESS(DxDdStartupDxGraphics(0,NULL,0,NULL,NULL,gpepCSRSS))) { WARNING("GRE: could not enable DirectDraw\n"); return(FALSE); } RTL_QUERY_REGISTRY_TABLE QueryTable[2]; USHORT AnsiCodePage, OemCodePage; // Init the font drivers gppdevTrueType = NULL; gppdevATMFD = NULL; gcTrueTypeFonts = 0; gulFontInformation = 0; gusLanguageID = GetLanguageID(); RtlGetDefaultCodePage(&AnsiCodePage,&OemCodePage); vConvertCodePageToCharSet( AnsiCodePage, &gfsCurSignature, &gjCurCharset); gbDBCSCodePage = (IS_ANY_DBCS_CODEPAGE(AnsiCodePage)) ? TRUE : FALSE; InitFNTCache(); vCheckTimeZoneBias(); // // NOTE: we are disabling ATM and vector font drivers for _GDIPLUS_ work // #ifndef _GDIPLUS_ QueryTable[0].QueryRoutine = FontDriverQueryRoutine; QueryTable[0].Flags = 0; // RTL_QUERY_REGISTRY_REQUIRED; QueryTable[0].Name = (PWSTR)NULL; QueryTable[0].EntryContext = NULL; QueryTable[0].DefaultType = REG_NONE; QueryTable[0].DefaultData = NULL; QueryTable[0].DefaultLength = 0; QueryTable[1].QueryRoutine = NULL; QueryTable[1].Flags = 0; QueryTable[1].Name = NULL; // Enumerate and initialize all the font drivers. RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT | RTL_REGISTRY_OPTIONAL, (PWSTR)L"Font Drivers", &QueryTable[0], NULL, NULL); if (!bEnableFontDriver((PFN) atmfdEnableDriver, FNT_OT_DRV)) { WARNING("GDISRV.DLL could not enable ATMFD stub\n"); return(FALSE); } // also creates ghsemVTFD semaphore if (!bEnableFontDriver((PFN) vtfdEnableDriver, FNT_VT_DRV)) { WARNING("GDISRV.DLL could not enable VTFD\n"); return(FALSE); } #endif // !_GDIPLUS_ // We need to get the fix pitch registry first // This is only JPN platform vGetJpn98FixPitch(); // also creates ghsemBMFD semaphore if (!bEnableFontDriver((PFN) BmfdEnableDriver, FNT_BMP_DRV)) { WARNING("GDISRV failed to enable BMFD\n"); return(FALSE); } if (!bEnableFontDriver((PFN) ttfdEnableDriver, FNT_TT_DRV)) { WARNING("GDISRV.DLL could not enable TTFD\n"); return(FALSE); } // // Init global public PFT // if (!bInitFontTables()) { WARNING("Could not start the global font tables\n"); return(FALSE); } // // Initialize LFONT // TRACE_FONT(("GRE: Initializing Stock Fonts\n")); if (!bInitStockFonts()) { WARNING("Stock font initialization failed\n"); return(FALSE); } TRACE_FONT(("GRE: Initializing Font Substitution\n")); // Init font substitution table vInitFontSubTable(); // Load default face names for the mapper from the registry vInitMapper(); if (!bInitializeEUDC()) { WARNING("EUDC initialization failed\n"); return(FALSE); } return(TRUE); } /******************************Public*Routine******************************\ * InitializeGre * * Initialize the Graphics Engine. This call is made once by USER. * * History: * Thu 29-Oct-1992 -by- Patrick Haluptzok [patrickh] * Remove wrappers, unnecesary semaphore use, bogus variables, cleanup. * * 10-Aug-1990 -by- Donald Sidoroff [donalds] * Wrote it. \**************************************************************************/ LONG CountInit = 1; extern "C" BOOL gbRemoteSession; // as in ntuser\kernel\globals.c extern "C" BOOLEAN InitializeGre( VOID) { #ifdef LANGPACK RTL_QUERY_REGISTRY_TABLE QueryTable[2]; #endif G_fConsole = (BOOL)!gbRemoteSession; G_fDoubleDpi = bDoubleDpi(G_fConsole); // // We only want to initialize once. We can detect transition to 0. // if (InterlockedDecrement(&CountInit) != 0) { return(TRUE); } #if defined(_GDIPLUS_) gIsTerminalServer = FALSE; #else gIsTerminalServer = !!(SharedUserData->SuiteMask & (1 << TerminalServer)); #endif if (!MultiUserGreCleanupInit()) { WARNING("InitializeGre: failed to initialize cleanup support\n"); return(FALSE); } // // Initialize the GRE DriverVerifier support (see verifier.cxx). // VerifierInitialization(); // // Note that GreEngLoadModuleTrackInit must be called AFTER gIsTerminalServer is set // (though it's called regardless of its value), so that the memory allocations will // be placed on the hydra tracking list if necessary. if (!GreEngLoadModuleTrackInit()) { WARNING("InitializeGre: failed to initialize EngLoadModule tracking\n"); return(FALSE); } #if TRACE_SURFACE_ALLOCS // // Initialize SURFACE tracing if requested in registry // TRACED_SURFACE::vInit(); #endif // // load registry process quota information // bLoadProcessHandleQuota(); // // Initialize lots of random stuff including the handle manager. // if (!HmgCreate()) { WARNING("HMGR failed to initialize\n"); return(FALSE); } // // Initialize REGION time stamp // REGION::ulUniqueREGION = 1; #if DBG_CORE if ((ghsemDEBUG = GreCreateSemaphore())==NULL) { WARNING("win32k: unable to initialize ghsemDEBUG\n"); return(FALSE); } #endif #if defined(USE_NINEGRID_STATIC) if ((gNineGridSem = GreCreateSemaphore())==NULL) { WARNING("Win32k: unable to initialize gNineGridSem\n"); return(FALSE); } #endif // // Create the LDEV\PDEV semaphore. // if ((ghsemDriverMgmt = GreCreateSemaphore()) == NULL) { WARNING("win32k: unable to create driver mgmt semaphore\n"); return(FALSE); } // // Init the font drivers // if (!bInitPathAlloc()) { WARNING("Pathalloc Initialization failed\n"); return(FALSE); } // Create the RFONT list semaphore. ghsemRFONTList = GreCreateSemaphore(); if (ghsemRFONTList == NULL) { WARNING("win32k: unable to create ghsemRFONTList\n"); return FALSE; } ghsemCLISERV = GreCreateSemaphore(); if (ghsemCLISERV == NULL) { WARNING("win32k: unabel to create ghsemCLISERV\n"); return( FALSE ); } if ((ghsemAtmfdInit = GreCreateSemaphore()) == NULL) { WARNING("win32k: unable to create driver mgmt semaphore\n"); return(FALSE); } // Create the WNDOBJ semaphore. ghsemWndobj = GreCreateSemaphore(); if (ghsemWndobj == NULL) { WARNING("win32k: unable to create ghsemWndobj\n"); return FALSE; } // Create the RFONT list semaphore. ghsemGdiSpool = GreCreateSemaphore(); if(ghsemGdiSpool == NULL) { WARNING("win32k: unable to create ghsemGdiSpool\n"); return FALSE; } // Create the mode change semaphore. if ((ghsemShareDevLock = GreCreateSemaphore()) == NULL) { WARNING("win32k: unable to create mode change semaphore\n"); return(FALSE); } // Create the association list mutex. if ((gAssociationListMutex = GreCreateFastMutex()) == NULL) { WARNING("win32k: unable to create association list mutex\n"); return(FALSE); } // Create a null region as the default region hrgnDefault = GreCreateRectRgn(0, 0, 0, 0); if (hrgnDefault == (HRGN) 0) { WARNING("hrgnDefault failed to initialize\n"); return(FALSE); } { RGNOBJAPI ro(hrgnDefault,TRUE); if(!ro.bValid()) { WARNING("invalid hrgnDefault\n"); return FALSE; } prgnDefault = ro.prgnGet(); } // Create a monochrome 1x1 bitmap as the default bitmap if (!bInitPALOBJ()) { WARNING("bInitPALOBJ failed !\n"); return(FALSE); } vInitXLATE(); if (!bInitBMOBJ()) { WARNING("bInitBMOBJ failed !\n"); return(FALSE); } // initialize the script names if(!InitializeScripts()) { WARNING("Could not initialize the script names\n"); return(FALSE); } // // Start up the brush component // if (!bInitBRUSHOBJ()) { WARNING("Could not init the brushes\n"); return(FALSE); } if (!bInitICM()) { WARNING("Could not init ICM\n"); return(FALSE); } // // Enable statically linked halftone library // if (!EnableHalftone()) { WARNING("GRE: could not enable halftone\n"); return(FALSE); } // // determine if processor supports MMX // #if defined (_X86_) gbMMXProcessor = bIsMMXProcessor(); #endif TRACE_INIT(("GRE: Completed Initialization\n")); #ifdef _GDIPLUS_ gpepCSRSS = PsGetCurrentProcess(); InitializeGreCSRSS(); #endif #ifdef LANGPACK QueryTable[0].QueryRoutine = LpkShapeQueryRoutine; QueryTable[0].Flags = 0; QueryTable[0].Name = (PWSTR)NULL; QueryTable[0].EntryContext = NULL; QueryTable[0].DefaultType = REG_NONE; QueryTable[0].DefaultData = NULL; QueryTable[0].DefaultLength = 0; QueryTable[1].QueryRoutine = NULL; QueryTable[1].Flags = 0; QueryTable[1].Name = NULL; gpGdiSharedMemory->dwLpkShapingDLLs = 0; RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT | RTL_REGISTRY_OPTIONAL, (PWSTR)L"LanguagePack", &QueryTable[0], NULL, NULL); #endif gpGdiSharedMemory->timeStamp = 1; return(TRUE); } extern "C" BOOL TellGdiToGetReady() { ASSERTGDI(gpepCSRSS, "gpepCSRSS\n"); return InitializeGreCSRSS(); } #ifdef LANGPACK extern "C" NTSTATUS LpkShapeQueryRoutine ( IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext ) { if( ValueType == REG_DWORD ) { gpGdiSharedMemory->dwLpkShapingDLLs |= (1<<(*((DWORD*)ValueData))); } return( STATUS_SUCCESS ); } #endif extern "C" NTSTATUS FontDriverQueryRoutine ( IN PWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Context, IN PVOID EntryContext ) { PLDEV pldev; WCHAR FontDriverPath[MAX_PATH+1]; wcscpy(FontDriverPath, L"\\SystemRoot\\System32\\"); // guard against some malicious person putting a huge value in here to hose us if((ValueLength / sizeof(WCHAR) < MAX_PATH - (sizeof(L"\\SystemRoot\\System32\\") / sizeof(WCHAR))) && (ValueType == REG_SZ)) { wcscat(FontDriverPath, (PWSTR) ValueData); if (_wcsicmp(L"\\SystemRoot\\System32\\atmdrvr.dll", FontDriverPath) == 0 || _wcsicmp(L"\\SystemRoot\\System32\\atmfd.dll", FontDriverPath) == 0) { //skip old atm font driver (4.0) or (5.0) because it is loaded through stub //WARNING("FontDriverQueryRoutine: system has a old version of ATM driver\n"); } else { pldev = ldevLoadDriver(FontDriverPath, LDEV_FONT); if (pldev) { // Create the PDEV for this (the PDEV won't have anything in it // except the dispatch table. PDEVOBJ po(pldev, NULL, NULL, NULL, NULL, NULL, NULL); if (po.bValid()) { po.ppdev->fl |= PDEV_FONTDRIVER; FntCacheHDEV((PPDEV) po.hdev(), FNT_DUMMY_DRV); return(TRUE); } else { WARNING("win32k.sys could not initialize installable driver\n"); } } else { WARNING("win32k.sys could not initialize installable driver\n"); } } } return( STATUS_SUCCESS ); } /******************************Public*Routine******************************\ * Read process handle quota * * Arguments: * * None * * Return Value: * * Status * * History: * * 3-May-1996 -by- Mark Enstrom [marke] * \**************************************************************************/ BOOL bLoadProcessHandleQuota() { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING UnicodeString; NTSTATUS NtStatus; HANDLE hKey; BOOL bRet = FALSE; RtlInitUnicodeString(&UnicodeString, L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows"); // // Open a registry key // InitializeObjectAttributes(&ObjectAttributes, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL); NtStatus = ZwOpenKey(&hKey, KEY_ALL_ACCESS, &ObjectAttributes); if (NT_SUCCESS(NtStatus)) { UNICODE_STRING UnicodeValue; ULONG ReturnedLength; UCHAR DataArray[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)]; PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)DataArray; RtlInitUnicodeString(&UnicodeValue, L"GDIProcessHandleQuota"); NtStatus = ZwQueryValueKey(hKey, &UnicodeValue, KeyValuePartialInformation, pKeyInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD), &ReturnedLength); if (NT_SUCCESS(NtStatus)) { gProcessHandleQuota = *(PLONG)(&pKeyInfo->Data[0]); } else { gProcessHandleQuota = DEFAULT_HANDLE_QUOTA; } bRet = TRUE; ZwCloseKey(hKey); } return(bRet); }