1 /* 2 * dllmain.c 3 */ 4 5 #include <precomp.h> 6 7 static BOOL gbInitialized = FALSE; 8 extern HGDIOBJ stock_objects[]; 9 BOOL SetStockObjects = FALSE; 10 PDEVCAPS GdiDevCaps = NULL; 11 PGDIHANDLECACHE GdiHandleCache = NULL; 12 BOOL gbLpk = FALSE; 13 RTL_CRITICAL_SECTION semLocal; 14 extern CRITICAL_SECTION gcsClientObjLinks; 15 16 /* 17 * GDI32.DLL does have an entry point for DisableThreadLibraryCalls(). 18 * The initialization is done by a call to GdiDllInitialize(). This 19 * call is done from the entry point of USER32.DLL. 20 */ 21 BOOL 22 WINAPI 23 DllMain( 24 _In_ HANDLE hDll, 25 _In_ ULONG dwReason, 26 _In_opt_ PVOID pReserved) 27 { 28 UNREFERENCED_PARAMETER(pReserved); 29 30 switch (dwReason) 31 { 32 case DLL_PROCESS_ATTACH : 33 DisableThreadLibraryCalls(hDll); 34 break; 35 36 default: 37 break; 38 } 39 return TRUE; 40 } 41 42 43 VOID 44 WINAPI 45 GdiProcessSetup(VOID) 46 { 47 if (!gbInitialized) 48 { 49 gbInitialized = TRUE; 50 hProcessHeap = GetProcessHeap(); 51 52 /* map the gdi handle table to user space */ 53 GdiHandleTable = NtCurrentTeb()->ProcessEnvironmentBlock->GdiSharedHandleTable; 54 GdiSharedHandleTable = NtCurrentTeb()->ProcessEnvironmentBlock->GdiSharedHandleTable; 55 GdiDevCaps = &GdiSharedHandleTable->DevCaps; 56 CurrentProcessId = NtCurrentTeb()->ClientId.UniqueProcess; 57 GDI_BatchLimit = (DWORD) NtCurrentTeb()->ProcessEnvironmentBlock->GdiDCAttributeList; 58 GdiHandleCache = (PGDIHANDLECACHE)NtCurrentTeb()->ProcessEnvironmentBlock->GdiHandleBuffer; 59 RtlInitializeCriticalSection(&semLocal); 60 InitializeCriticalSection(&gcsClientObjLinks); 61 GdiInitializeLanguagePack(0); 62 } 63 } 64 65 VOID 66 WINAPI 67 GdiProcessShutdown(VOID) 68 { 69 DeleteCriticalSection(&gcsClientObjLinks); 70 RtlDeleteCriticalSection(&semLocal); 71 } 72 73 74 /* 75 * @implemented 76 */ 77 BOOL 78 WINAPI 79 GdiDllInitialize( 80 _In_ HANDLE hDll, 81 _In_ ULONG dwReason, 82 _In_opt_ PVOID pReserved) 83 { 84 UNREFERENCED_PARAMETER(pReserved); 85 86 switch (dwReason) 87 { 88 case DLL_PROCESS_ATTACH: 89 { 90 /* Don't bother us for each thread */ 91 // DisableThreadLibraryCalls(hDll); 92 93 /* Initialize the kernel part of GDI first */ 94 if (!NtGdiInit()) return FALSE; 95 96 /* Now initialize ourselves */ 97 GdiProcessSetup(); 98 break; 99 } 100 101 case DLL_THREAD_ATTACH: 102 { 103 NtCurrentTeb()->GdiTebBatch.Offset = 0; 104 NtCurrentTeb()->GdiBatchCount = 0; 105 break; 106 } 107 108 case DLL_PROCESS_DETACH: 109 { 110 /* Cleanup */ 111 GdiProcessShutdown(); 112 return TRUE; 113 } 114 115 default: 116 return FALSE; 117 } 118 119 /* Very simple, the list will fill itself as it is needed */ 120 if (!SetStockObjects) 121 { 122 RtlZeroMemory(&stock_objects, NB_STOCK_OBJECTS); // Assume ROS is dirty 123 SetStockObjects = TRUE; 124 } 125 126 return TRUE; 127 } 128 129 /* EOF */ 130