mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-01 19:26:16 +00:00
425 lines
11 KiB
C
425 lines
11 KiB
C
#include <user32.h>
|
|
|
|
#include <ndk/cmfuncs.h>
|
|
|
|
#include <wine/debug.h>
|
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
|
|
#define KEY_LENGTH 1024
|
|
|
|
static ULONG User32TlsIndex;
|
|
HINSTANCE User32Instance;
|
|
|
|
PPROCESSINFO g_ppi = NULL;
|
|
PUSER_HANDLE_TABLE gHandleTable = NULL;
|
|
PUSER_HANDLE_ENTRY gHandleEntries = NULL;
|
|
PSERVERINFO gpsi = NULL;
|
|
ULONG_PTR g_ulSharedDelta;
|
|
BOOLEAN gfLogonProcess = FALSE;
|
|
BOOLEAN gfServerProcess = FALSE;
|
|
HICON hIconSmWindows = NULL, hIconWindows = NULL;
|
|
|
|
WCHAR szAppInit[KEY_LENGTH];
|
|
|
|
BOOL
|
|
GetDllList()
|
|
{
|
|
NTSTATUS Status;
|
|
OBJECT_ATTRIBUTES Attributes;
|
|
BOOL bRet = FALSE;
|
|
BOOL bLoad;
|
|
HANDLE hKey = NULL;
|
|
DWORD dwSize;
|
|
PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = NULL;
|
|
|
|
UNICODE_STRING szKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows");
|
|
UNICODE_STRING szLoadName = RTL_CONSTANT_STRING(L"LoadAppInit_DLLs");
|
|
UNICODE_STRING szDllsName = RTL_CONSTANT_STRING(L"AppInit_DLLs");
|
|
|
|
InitializeObjectAttributes(&Attributes, &szKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
Status = NtOpenKey(&hKey, KEY_READ, &Attributes);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD);
|
|
kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
if (!kvpInfo)
|
|
goto end;
|
|
|
|
Status = NtQueryValueKey(hKey,
|
|
&szLoadName,
|
|
KeyValuePartialInformation,
|
|
kvpInfo,
|
|
dwSize,
|
|
&dwSize);
|
|
if (!NT_SUCCESS(Status))
|
|
goto end;
|
|
|
|
RtlMoveMemory(&bLoad,
|
|
kvpInfo->Data,
|
|
kvpInfo->DataLength);
|
|
|
|
HeapFree(GetProcessHeap(), 0, kvpInfo);
|
|
kvpInfo = NULL;
|
|
|
|
if (bLoad)
|
|
{
|
|
Status = NtQueryValueKey(hKey,
|
|
&szDllsName,
|
|
KeyValuePartialInformation,
|
|
NULL,
|
|
0,
|
|
&dwSize);
|
|
if (Status != STATUS_BUFFER_TOO_SMALL)
|
|
goto end;
|
|
|
|
kvpInfo = HeapAlloc(GetProcessHeap(), 0, dwSize);
|
|
if (!kvpInfo)
|
|
goto end;
|
|
|
|
Status = NtQueryValueKey(hKey,
|
|
&szDllsName,
|
|
KeyValuePartialInformation,
|
|
kvpInfo,
|
|
dwSize,
|
|
&dwSize);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
LPWSTR lpBuffer = (LPWSTR)kvpInfo->Data;
|
|
if (*lpBuffer != UNICODE_NULL)
|
|
{
|
|
INT bytesToCopy, nullPos;
|
|
|
|
bytesToCopy = min(kvpInfo->DataLength, KEY_LENGTH * sizeof(WCHAR));
|
|
|
|
if (bytesToCopy != 0)
|
|
{
|
|
RtlMoveMemory(szAppInit,
|
|
kvpInfo->Data,
|
|
bytesToCopy);
|
|
|
|
nullPos = (bytesToCopy / sizeof(WCHAR)) - 1;
|
|
|
|
/* ensure string is terminated */
|
|
szAppInit[nullPos] = UNICODE_NULL;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
end:
|
|
if (hKey)
|
|
NtClose(hKey);
|
|
|
|
if (kvpInfo)
|
|
HeapFree(GetProcessHeap(), 0, kvpInfo);
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
VOID
|
|
LoadAppInitDlls()
|
|
{
|
|
szAppInit[0] = UNICODE_NULL;
|
|
|
|
if (GetDllList())
|
|
{
|
|
WCHAR buffer[KEY_LENGTH];
|
|
LPWSTR ptr;
|
|
size_t i;
|
|
|
|
RtlCopyMemory(buffer, szAppInit, KEY_LENGTH);
|
|
|
|
for (i = 0; i < KEY_LENGTH; ++ i)
|
|
{
|
|
if(buffer[i] == L' ' || buffer[i] == L',')
|
|
buffer[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < KEY_LENGTH; )
|
|
{
|
|
if(buffer[i] == 0)
|
|
++ i;
|
|
else
|
|
{
|
|
ptr = buffer + i;
|
|
i += wcslen(ptr);
|
|
LoadLibraryW(ptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
UnloadAppInitDlls()
|
|
{
|
|
if (szAppInit[0] != UNICODE_NULL)
|
|
{
|
|
WCHAR buffer[KEY_LENGTH];
|
|
HMODULE hModule;
|
|
LPWSTR ptr;
|
|
size_t i;
|
|
|
|
RtlCopyMemory(buffer, szAppInit, KEY_LENGTH * sizeof(WCHAR));
|
|
|
|
for (i = 0; i < KEY_LENGTH; ++ i)
|
|
{
|
|
if(buffer[i] == L' ' || buffer[i] == L',')
|
|
buffer[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < KEY_LENGTH; )
|
|
{
|
|
if(buffer[i] == 0)
|
|
++ i;
|
|
else
|
|
{
|
|
ptr = buffer + i;
|
|
i += wcslen(ptr);
|
|
hModule = GetModuleHandleW(ptr);
|
|
FreeLibrary(hModule);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
InitThread(VOID)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
VOID
|
|
CleanupThread(VOID)
|
|
{
|
|
}
|
|
|
|
PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
|
|
{
|
|
User32CallWindowProcFromKernel,
|
|
User32CallSendAsyncProcForKernel,
|
|
User32LoadSysMenuTemplateForKernel,
|
|
User32SetupDefaultCursors,
|
|
User32CallHookProcFromKernel,
|
|
User32CallEventProcFromKernel,
|
|
User32CallLoadMenuFromKernel,
|
|
User32CallClientThreadSetupFromKernel,
|
|
User32CallClientLoadLibraryFromKernel,
|
|
User32CallGetCharsetInfo,
|
|
User32CallCopyImageFromKernel,
|
|
User32CallSetWndIconsFromKernel,
|
|
};
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
ClientThreadSetup(VOID)
|
|
{
|
|
//
|
|
// This routine, in Windows, does a lot of what Init does, but in a radically
|
|
// different way.
|
|
//
|
|
// In Windows, because CSRSS's threads have TIF_CSRSSTHREAD set (we have this
|
|
// flag in ROS but not sure if we use it), the xxxClientThreadSetup callback
|
|
// isn't made when CSRSS first loads WINSRV.DLL (which loads USER32.DLL).
|
|
//
|
|
// However, all the other calls are made as normal, and WINSRV.DLL loads
|
|
// USER32.dll, the DllMain runs, and eventually the first NtUser system call is
|
|
// made which initializes Win32k (and initializes the thread, but as mentioned
|
|
// above, the thread is marked as TIF_CSRSSTHREAD.
|
|
//
|
|
// In the DllMain of User32, there is also a CsrClientConnectToServer call to
|
|
// server 2 (winsrv). When this is done from CSRSS, the "InServer" flag is set,
|
|
// so user32 will remember that it's running inside of CSRSS. Also, another
|
|
// flag, called "FirstThread" is manually set by DllMain.
|
|
//
|
|
// Then, WINSRV finishes loading, and CSRSRV starts the API thread/loop. This
|
|
// code then calls CsrConnectToUser, which calls... ClientThreadStartup. Now
|
|
// this routine detects that it's in the server process, which means it's CSRSS
|
|
// and that the callback never happened. It does some first-time-Win32k connection
|
|
// initialization and caches a bunch of things -- if it's the first thread. It also
|
|
// acquires a critical section to initialize GDI -- and then resets the first thread
|
|
// flag.
|
|
//
|
|
// For now, we'll do none of this, but to support Windows' CSRSRV.DLL which calls
|
|
// CsrConnectToUser, we'll pretend we "did something" here. Then the rest will
|
|
// continue as normal.
|
|
//
|
|
UNIMPLEMENTED;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
Init(VOID)
|
|
{
|
|
USERCONNECT UserCon;
|
|
|
|
/* Set PEB data */
|
|
NtCurrentPeb()->KernelCallbackTable = apfnDispatch;
|
|
NtCurrentPeb()->PostProcessInitRoutine = NULL;
|
|
|
|
NtUserProcessConnect( NtCurrentProcess(),
|
|
&UserCon,
|
|
sizeof(USERCONNECT));
|
|
|
|
g_ppi = GetWin32ClientInfo()->ppi; // Snapshot PI, used as pointer only!
|
|
g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
|
|
gpsi = SharedPtrToUser(UserCon.siClient.psi);
|
|
gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
|
|
gHandleEntries = SharedPtrToUser(gHandleTable->handles);
|
|
|
|
RtlInitializeCriticalSection(&gcsUserApiHook);
|
|
gfServerProcess = FALSE; // FIXME HAX! Used in CsrClientConnectToServer(,,,,&gfServerProcess);
|
|
|
|
//CsrClientConnectToServer(L"\\Windows", 0, NULL, 0, &gfServerProcess);
|
|
//ERR("1 SI 0x%x : HT 0x%x : D 0x%x\n", UserCon.siClient.psi, UserCon.siClient.aheList, g_ulSharedDelta);
|
|
|
|
/* Allocate an index for user32 thread local data. */
|
|
User32TlsIndex = TlsAlloc();
|
|
if (User32TlsIndex != TLS_OUT_OF_INDEXES)
|
|
{
|
|
if (MessageInit())
|
|
{
|
|
if (MenuInit())
|
|
{
|
|
InitializeCriticalSection(&U32AccelCacheLock);
|
|
GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
|
|
LoadAppInitDlls();
|
|
|
|
return TRUE;
|
|
}
|
|
MessageCleanup();
|
|
}
|
|
TlsFree(User32TlsIndex);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
Cleanup(VOID)
|
|
{
|
|
DeleteCriticalSection(&U32AccelCacheLock);
|
|
MenuCleanup();
|
|
MessageCleanup();
|
|
DeleteFrameBrushes();
|
|
UnloadAppInitDlls();
|
|
GdiDllInitialize(NULL, DLL_PROCESS_DETACH, NULL);
|
|
TlsFree(User32TlsIndex);
|
|
}
|
|
|
|
INT WINAPI
|
|
DllMain(
|
|
IN PVOID hInstanceDll,
|
|
IN ULONG dwReason,
|
|
IN PVOID reserved)
|
|
{
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
User32Instance = hInstanceDll;
|
|
if (!RegisterClientPFN())
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (!Init())
|
|
return FALSE;
|
|
if (!InitThread())
|
|
{
|
|
Cleanup();
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
if (!InitThread())
|
|
return FALSE;
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
CleanupThread();
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
if (hImmInstance) FreeLibrary(hImmInstance);
|
|
CleanupThread();
|
|
Cleanup();
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
FASTCALL
|
|
GetConnected(VOID)
|
|
{
|
|
USERCONNECT UserCon;
|
|
// ERR("GetConnected\n");
|
|
|
|
if ((PTHREADINFO)NtCurrentTeb()->Win32ThreadInfo == NULL)
|
|
NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
|
|
|
|
if (gpsi && g_ppi) return;
|
|
// FIXME HAX: Due to the "Dll Initialization Bug" we have to call this too.
|
|
GdiDllInitialize(NULL, DLL_PROCESS_ATTACH, NULL);
|
|
|
|
NtUserProcessConnect( NtCurrentProcess(),
|
|
&UserCon,
|
|
sizeof(USERCONNECT));
|
|
|
|
g_ppi = GetWin32ClientInfo()->ppi;
|
|
g_ulSharedDelta = UserCon.siClient.ulSharedDelta;
|
|
gpsi = SharedPtrToUser(UserCon.siClient.psi);
|
|
gHandleTable = SharedPtrToUser(UserCon.siClient.aheList);
|
|
gHandleEntries = SharedPtrToUser(gHandleTable->handles);
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
WINAPI
|
|
User32CallClientThreadSetupFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
|
{
|
|
ERR("ClientThreadSetup\n");
|
|
ClientThreadSetup();
|
|
return ZwCallbackReturn(NULL, 0, STATUS_SUCCESS);
|
|
}
|
|
|
|
NTSTATUS
|
|
WINAPI
|
|
User32CallGetCharsetInfo(PVOID Arguments, ULONG ArgumentLength)
|
|
{
|
|
BOOL Ret;
|
|
PGET_CHARSET_INFO pgci = (PGET_CHARSET_INFO)Arguments;
|
|
|
|
TRACE("GetCharsetInfo\n");
|
|
|
|
Ret = TranslateCharsetInfo((DWORD *)pgci->Locale, &pgci->Cs, TCI_SRCLOCALE);
|
|
|
|
return ZwCallbackReturn(Arguments, ArgumentLength, Ret ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
NTSTATUS
|
|
WINAPI
|
|
User32CallSetWndIconsFromKernel(PVOID Arguments, ULONG ArgumentLength)
|
|
{
|
|
PSETWNDICONS_CALLBACK_ARGUMENTS Common = Arguments;
|
|
|
|
if (!hIconSmWindows)
|
|
{
|
|
hIconSmWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
|
|
hIconWindows = LoadImageW(0, IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
|
|
}
|
|
Common->hIconSmWindows = hIconSmWindows;
|
|
Common->hIconWindows = hIconWindows;
|
|
ERR("hIconSmWindows %p hIconWindows %p \n",hIconSmWindows,hIconWindows);
|
|
return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
|
|
}
|