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.
 
 
 
 
 
 

961 lines
26 KiB

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