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
);
189 PVOID apfnDispatch
[USER32_CALLBACK_MAXIMUM
+ 1] =
191 User32CallWindowProcFromKernel
,
192 User32CallSendAsyncProcForKernel
,
193 User32LoadSysMenuTemplateForKernel
,
194 User32SetupDefaultCursors
,
195 User32CallHookProcFromKernel
,
196 User32CallEventProcFromKernel
,
197 User32CallLoadMenuFromKernel
,
198 User32CallClientThreadSetupFromKernel
,
199 User32CallClientLoadLibraryFromKernel
,
200 User32CallGetCharsetInfo
,
201 User32CallCopyImageFromKernel
,
202 User32CallSetWndIconsFromKernel
,
203 User32DeliverUserAPC
,
211 ClientThreadSetup(VOID
)
214 // This routine, in Windows, does a lot of what Init does, but in a radically
217 // In Windows, because CSRSS's threads have TIF_CSRSSTHREAD set (we have this
218 // flag in ROS but not sure if we use it), the xxxClientThreadSetup callback
219 // isn't made when CSRSS first loads WINSRV.DLL (which loads USER32.DLL).
221 // However, all the other calls are made as normal, and WINSRV.DLL loads
222 // USER32.dll, the DllMain runs, and eventually the first NtUser system call is
223 // made which initializes Win32k (and initializes the thread, but as mentioned
224 // above, the thread is marked as TIF_CSRSSTHREAD.
226 // In the DllMain of User32, there is also a CsrClientConnectToServer call to
227 // server 2 (winsrv). When this is done from CSRSS, the "InServer" flag is set,
228 // so user32 will remember that it's running inside of CSRSS. Also, another
229 // flag, called "FirstThread" is manually set by DllMain.
231 // Then, WINSRV finishes loading, and CSRSRV starts the API thread/loop. This
232 // code then calls CsrConnectToUser, which calls... ClientThreadStartup. Now
233 // this routine detects that it's in the server process, which means it's CSRSS
234 // and that the callback never happened. It does some first-time-Win32k connection
235 // initialization and caches a bunch of things -- if it's the first thread. It also
236 // acquires a critical section to initialize GDI -- and then resets the first thread
239 // For now, we'll do none of this, but to support Windows' CSRSRV.DLL which calls
240 // CsrConnectToUser, we'll pretend we "did something" here. Then the rest will
241 // continue as normal.
256 TRACE("user32::Init()\n");
259 NtCurrentPeb()->KernelCallbackTable
= apfnDispatch
;
260 NtCurrentPeb()->PostProcessInitRoutine
= NULL
;
262 /* Minimal setup of the connect info structure */
263 UserCon
.ulVersion
= USER_VERSION
;
265 /* Connect to win32k */
266 Status
= NtUserProcessConnect(NtCurrentProcess(),
269 if (!NT_SUCCESS(Status
)) return FALSE
;
272 g_ppi
= GetWin32ClientInfo()->ppi
; // Snapshot PI, used as pointer only!
273 g_ulSharedDelta
= UserCon
.siClient
.ulSharedDelta
;
274 gpsi
= SharedPtrToUser(UserCon
.siClient
.psi
);
275 gHandleTable
= SharedPtrToUser(UserCon
.siClient
.aheList
);
276 gHandleEntries
= SharedPtrToUser(gHandleTable
->handles
);
278 RtlInitializeCriticalSection(&gcsUserApiHook
);
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
)
291 InitializeCriticalSection(&U32AccelCacheLock
);
298 TlsFree(User32TlsIndex
);
305 DeleteCriticalSection(&U32AccelCacheLock
);
308 DeleteFrameBrushes();
310 TlsFree(User32TlsIndex
);
315 IN PVOID hInstanceDll
,
321 case DLL_PROCESS_ATTACH
:
326 #define WIN_OBJ_DIR L"\\Windows"
327 #define SESSION_DIR L"\\Sessions"
330 USERSRV_API_CONNECTINFO ConnectInfo
; // USERCONNECT
331 ULONG ConnectInfoSize
= sizeof(ConnectInfo
);
332 WCHAR SessionDir
[256];
334 /* Cache the PEB and Session ID */
335 PPEB Peb
= NtCurrentPeb();
336 ULONG SessionId
= Peb
->SessionId
; // gSessionId
338 /* Don't bother us for each thread */
339 DisableThreadLibraryCalls(hInstanceDll
);
341 /* Minimal setup of the connect info structure */
342 ConnectInfo
.ulVersion
= USER_VERSION
;
344 /* Setup the Object Directory path */
347 /* Use the raw path */
348 wcscpy(SessionDir
, WIN_OBJ_DIR
);
352 /* Use the session path */
360 /* Connect to the USER Server */
361 Status
= CsrClientConnectToServer(SessionDir
,
362 USERSRV_SERVERDLL_INDEX
,
366 if (!NT_SUCCESS(Status
))
368 ERR("Failed to connect to CSR (Status %lx)\n", Status
);
373 gfServerProcess
= FALSE
;
376 User32Instance
= hInstanceDll
;
378 if (!RegisterClientPFN())
387 case DLL_PROCESS_DETACH
:
390 FreeLibrary(hImmInstance
);
397 /* Finally, initialize GDI */
398 return GdiDllInitialize(hInstanceDll
, dwReason
, reserved
);
401 // FIXME: This function IS A BIIG HACK!!
409 TRACE("user32::GetConnected()\n");
411 if ((PTHREADINFO
)NtCurrentTeb()->Win32ThreadInfo
== NULL
)
412 NtUserGetThreadState(THREADSTATE_GETTHREADINFO
);
414 if (gpsi
&& g_ppi
) return;
416 /* Minimal setup of the connect info structure */
417 UserCon
.ulVersion
= USER_VERSION
;
419 /* Connect to win32k */
420 Status
= NtUserProcessConnect(NtCurrentProcess(),
423 if (!NT_SUCCESS(Status
)) return;
426 g_ppi
= GetWin32ClientInfo()->ppi
; // Snapshot PI, used as pointer only!
427 g_ulSharedDelta
= UserCon
.siClient
.ulSharedDelta
;
428 gpsi
= SharedPtrToUser(UserCon
.siClient
.psi
);
429 gHandleTable
= SharedPtrToUser(UserCon
.siClient
.aheList
);
430 gHandleEntries
= SharedPtrToUser(gHandleTable
->handles
);
435 User32CallClientThreadSetupFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
437 TRACE("ClientThreadSetup\n");
439 return ZwCallbackReturn(NULL
, 0, STATUS_SUCCESS
);
444 User32CallGetCharsetInfo(PVOID Arguments
, ULONG ArgumentLength
)
447 PGET_CHARSET_INFO pgci
= (PGET_CHARSET_INFO
)Arguments
;
449 TRACE("GetCharsetInfo\n");
451 Ret
= TranslateCharsetInfo((DWORD
*)pgci
->Locale
, &pgci
->Cs
, TCI_SRCLOCALE
);
453 return ZwCallbackReturn(Arguments
, ArgumentLength
, Ret
? STATUS_SUCCESS
: STATUS_UNSUCCESSFUL
);
458 User32CallSetWndIconsFromKernel(PVOID Arguments
, ULONG ArgumentLength
)
460 PSETWNDICONS_CALLBACK_ARGUMENTS Common
= Arguments
;
464 hIconSmWindows
= LoadImageW(0, IDI_WINLOGO
, IMAGE_ICON
, GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_DEFAULTCOLOR
);
465 hIconWindows
= LoadImageW(0, IDI_WINLOGO
, IMAGE_ICON
, 0, 0, LR_DEFAULTCOLOR
);
467 Common
->hIconSmWindows
= hIconSmWindows
;
468 Common
->hIconWindows
= hIconWindows
;
469 ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows
,hIconWindows
);
470 return ZwCallbackReturn(Arguments
, ArgumentLength
, STATUS_SUCCESS
);
475 User32DeliverUserAPC(PVOID Arguments
, ULONG ArgumentLength
)
477 return ZwCallbackReturn(0, 0, STATUS_SUCCESS
);