3 #include <ndk/cmfuncs.h>
5 #include <wine/debug.h>
6 WINE_DEFAULT_DEBUG_CHANNEL(user32
);
8 #define KEY_LENGTH 1024
10 static ULONG User32TlsIndex
;
11 HINSTANCE User32Instance
;
13 PPROCESSINFO g_ppi
= NULL
;
14 PUSER_HANDLE_TABLE gHandleTable
= NULL
;
15 PUSER_HANDLE_ENTRY gHandleEntries
= NULL
;
16 PSERVERINFO gpsi
= NULL
;
17 ULONG_PTR g_ulSharedDelta
;
18 BOOLEAN gfLogonProcess
= FALSE
;
19 BOOLEAN gfServerProcess
= FALSE
;
20 HICON hIconSmWindows
= NULL
, hIconWindows
= NULL
;
22 WCHAR szAppInit
[KEY_LENGTH
];
28 OBJECT_ATTRIBUTES Attributes
;
33 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo
= NULL
;
35 UNICODE_STRING szKeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
36 UNICODE_STRING szLoadName
= RTL_CONSTANT_STRING(L
"LoadAppInit_DLLs");
37 UNICODE_STRING szDllsName
= RTL_CONSTANT_STRING(L
"AppInit_DLLs");
39 InitializeObjectAttributes(&Attributes
, &szKeyName
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
40 Status
= NtOpenKey(&hKey
, KEY_READ
, &Attributes
);
41 if (NT_SUCCESS(Status
))
43 dwSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
);
44 kvpInfo
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
48 Status
= NtQueryValueKey(hKey
,
50 KeyValuePartialInformation
,
54 if (!NT_SUCCESS(Status
))
61 HeapFree(GetProcessHeap(), 0, kvpInfo
);
66 Status
= NtQueryValueKey(hKey
,
68 KeyValuePartialInformation
,
72 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
75 kvpInfo
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
79 Status
= NtQueryValueKey(hKey
,
81 KeyValuePartialInformation
,
85 if (NT_SUCCESS(Status
))
87 LPWSTR lpBuffer
= (LPWSTR
)kvpInfo
->Data
;
88 if (*lpBuffer
!= UNICODE_NULL
)
90 INT bytesToCopy
, nullPos
;
92 bytesToCopy
= min(kvpInfo
->DataLength
, KEY_LENGTH
* sizeof(WCHAR
));
96 RtlMoveMemory(szAppInit
,
100 nullPos
= (bytesToCopy
/ sizeof(WCHAR
)) - 1;
102 /* ensure string is terminated */
103 szAppInit
[nullPos
] = UNICODE_NULL
;
117 HeapFree(GetProcessHeap(), 0, kvpInfo
);
126 szAppInit
[0] = UNICODE_NULL
;
130 WCHAR buffer
[KEY_LENGTH
];
134 RtlCopyMemory(buffer
, szAppInit
, KEY_LENGTH
* sizeof(WCHAR
) );
136 for (i
= 0; i
< KEY_LENGTH
; ++ i
)
138 if(buffer
[i
] == L
' ' || buffer
[i
] == L
',')
142 for (i
= 0; i
< KEY_LENGTH
; )
159 if (szAppInit
[0] != UNICODE_NULL
)
161 WCHAR buffer
[KEY_LENGTH
];
166 RtlCopyMemory(buffer
, szAppInit
, KEY_LENGTH
* sizeof(WCHAR
));
168 for (i
= 0; i
< KEY_LENGTH
; ++ i
)
170 if(buffer
[i
] == L
' ' || buffer
[i
] == L
',')
174 for (i
= 0; i
< KEY_LENGTH
; )
182 hModule
= GetModuleHandleW(ptr
);
183 FreeLibrary(hModule
);
200 PVOID apfnDispatch
[USER32_CALLBACK_MAXIMUM
+ 1] =
202 User32CallWindowProcFromKernel
,
203 User32CallSendAsyncProcForKernel
,
204 User32LoadSysMenuTemplateForKernel
,
205 User32SetupDefaultCursors
,
206 User32CallHookProcFromKernel
,
207 User32CallEventProcFromKernel
,
208 User32CallLoadMenuFromKernel
,
209 User32CallClientThreadSetupFromKernel
,
210 User32CallClientLoadLibraryFromKernel
,
211 User32CallGetCharsetInfo
,
212 User32CallCopyImageFromKernel
,
213 User32CallSetWndIconsFromKernel
,
221 ClientThreadSetup(VOID
)
224 // This routine, in Windows, does a lot of what Init does, but in a radically
227 // In Windows, because CSRSS's threads have TIF_CSRSSTHREAD set (we have this
228 // flag in ROS but not sure if we use it), the xxxClientThreadSetup callback
229 // isn't made when CSRSS first loads WINSRV.DLL (which loads USER32.DLL).
231 // However, all the other calls are made as normal, and WINSRV.DLL loads
232 // USER32.dll, the DllMain runs, and eventually the first NtUser system call is
233 // made which initializes Win32k (and initializes the thread, but as mentioned
234 // above, the thread is marked as TIF_CSRSSTHREAD.
236 // In the DllMain of User32, there is also a CsrClientConnectToServer call to
237 // server 2 (winsrv). When this is done from CSRSS, the "InServer" flag is set,
238 // so user32 will remember that it's running inside of CSRSS. Also, another
239 // flag, called "FirstThread" is manually set by DllMain.
241 // Then, WINSRV finishes loading, and CSRSRV starts the API thread/loop. This
242 // code then calls CsrConnectToUser, which calls... ClientThreadStartup. Now
243 // this routine detects that it's in the server process, which means it's CSRSS
244 // and that the callback never happened. It does some first-time-Win32k connection
245 // initialization and caches a bunch of things -- if it's the first thread. It also
246 // acquires a critical section to initialize GDI -- and then resets the first thread
249 // For now, we'll do none of this, but to support Windows' CSRSRV.DLL which calls
250 // CsrConnectToUser, we'll pretend we "did something" here. Then the rest will
251 // continue as normal.
263 NtCurrentPeb()->KernelCallbackTable
= apfnDispatch
;
264 NtCurrentPeb()->PostProcessInitRoutine
= NULL
;
266 NtUserProcessConnect( NtCurrentProcess(),
268 sizeof(USERCONNECT
));
270 g_ppi
= GetWin32ClientInfo()->ppi
; // Snapshot PI, used as pointer only!
271 g_ulSharedDelta
= UserCon
.siClient
.ulSharedDelta
;
272 gpsi
= SharedPtrToUser(UserCon
.siClient
.psi
);
273 gHandleTable
= SharedPtrToUser(UserCon
.siClient
.aheList
);
274 gHandleEntries
= SharedPtrToUser(gHandleTable
->handles
);
276 RtlInitializeCriticalSection(&gcsUserApiHook
);
277 gfServerProcess
= FALSE
; // FIXME HAX! Used in CsrClientConnectToServer(,,,,&gfServerProcess);
279 //CsrClientConnectToServer(L"\\Windows", 0, NULL, 0, &gfServerProcess);
280 //ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", UserCon.siClient.psi, UserCon.siClient.aheList, g_ulSharedDelta);
282 /* Allocate an index for user32 thread local data. */
283 User32TlsIndex
= TlsAlloc();
284 if (User32TlsIndex
!= TLS_OUT_OF_INDEXES
)
290 InitializeCriticalSection(&U32AccelCacheLock
);
291 GdiDllInitialize(NULL
, DLL_PROCESS_ATTACH
, NULL
);
298 TlsFree(User32TlsIndex
);
307 DeleteCriticalSection(&U32AccelCacheLock
);
310 DeleteFrameBrushes();
312 GdiDllInitialize(NULL
, DLL_PROCESS_DETACH
, NULL
);
313 TlsFree(User32TlsIndex
);
318 IN PVOID hInstanceDll
,
324 case DLL_PROCESS_ATTACH
:
325 User32Instance
= hInstanceDll
;
326 if (!RegisterClientPFN())
340 case DLL_THREAD_ATTACH
:
345 case DLL_THREAD_DETACH
:
349 case DLL_PROCESS_DETACH
:
350 if (hImmInstance
) FreeLibrary(hImmInstance
);
365 // ERR("GetConnected\n");
367 if ((PTHREADINFO
)NtCurrentTeb()->Win32ThreadInfo
== NULL
)
368 NtUserGetThreadState(THREADSTATE_GETTHREADINFO
);
370 if (gpsi
&& g_ppi
) return;
371 // FIXME HAX: Due to the "Dll Initialization Bug" we have to call this too.
372 GdiDllInitialize(NULL
, DLL_PROCESS_ATTACH
, NULL
);
374 NtUserProcessConnect( NtCurrentProcess(),
376 sizeof(USERCONNECT
));
378 g_ppi
= GetWin32ClientInfo()->ppi
;
379 g_ulSharedDelta
= UserCon
.siClient
.ulSharedDelta
;
380 gpsi
= SharedPtrToUser(UserCon
.siClient
.psi
);
381 gHandleTable
= SharedPtrToUser(UserCon
.siClient
.aheList
);
382 gHandleEntries
= SharedPtrToUser(gHandleTable
->handles
);
388 User32CallClientThreadSetupFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
390 ERR("ClientThreadSetup\n");
392 return ZwCallbackReturn(NULL
, 0, STATUS_SUCCESS
);
397 User32CallGetCharsetInfo(PVOID Arguments
, ULONG ArgumentLength
)
400 PGET_CHARSET_INFO pgci
= (PGET_CHARSET_INFO
)Arguments
;
402 TRACE("GetCharsetInfo\n");
404 Ret
= TranslateCharsetInfo((DWORD
*)pgci
->Locale
, &pgci
->Cs
, TCI_SRCLOCALE
);
406 return ZwCallbackReturn(Arguments
, ArgumentLength
, Ret
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
411 User32CallSetWndIconsFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
413 PSETWNDICONS_CALLBACK_ARGUMENTS Common
= Arguments
;
417 hIconSmWindows
= LoadImageW(0, IDI_WINLOGO
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTCOLOR
);
418 hIconWindows
= LoadImageW(0, IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
420 Common
->hIconSmWindows
= hIconSmWindows
;
421 Common
->hIconWindows
= hIconWindows
;
422 ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows
,hIconWindows
);
423 return ZwCallbackReturn(Arguments
, ArgumentLength
, STATUS_SUCCESS
);