354 lines
9.7 KiB
C
354 lines
9.7 KiB
C
/** Module Header **\
|
|
* Module Name: csrstubs.c
|
|
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
|
|
* Routines to call CSR
|
|
|
|
* 02-27-95 JimA Created.
|
|
|
|
* Note: This file has been partitioned with #if defines so that the LPC
|
|
* marsheling code can be inside 64bit code when running under wow64(32bit on 64bit NT).
|
|
* In wow64, the system DLLs for 32bit processes are 32bit.
|
|
|
|
* The marsheling code can only be depedent on functions NTDLL.
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "csrmsg.h"
|
|
#include "dbt.h"
|
|
#include "csrhlpr.h"
|
|
|
|
#if defined(BUILD_CSRWOW64)
|
|
#undef RIPERR0
|
|
#undef RIPNTERR0
|
|
#undef RIPMSG0
|
|
#define RIPNTERR0(status, flags, szFmt) {if (NtCurrentTeb()) NtCurrentTeb()->LastErrorValue = RtlNtStatusToDosError(status);}
|
|
#define RIPERR0(idErr, flags, szFmt) {if (NtCurrentTeb()) NtCurrentTeb()->LastErrorValue = (idErr);}
|
|
#define RIPMSG0(flags, szFmt)
|
|
#endif
|
|
|
|
|
|
#define SET_LAST_ERROR_RETURNED() if (a->dwLastError) RIPERR0(a->dwLastError, RIP_VERBOSE, "")
|
|
|
|
|
|
#if !defined(BUILD_WOW6432)
|
|
NTSTATUS APIENTRY CallUserpExitWindowsEx(IN UINT uFlags, IN DWORD dwReserved, OUT PBOOL pfSuccess)
|
|
{
|
|
USER_API_MSG m;
|
|
PEXITWINDOWSEXMSG a = &m.u.ExitWindowsEx;
|
|
|
|
a->uFlags = uFlags;
|
|
a->dwReserved = dwReserved;
|
|
CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpExitWindowsEx), sizeof( *a ));
|
|
if (NT_SUCCESS( m.ReturnValue ) || m.ReturnValue == STATUS_CANT_WAIT) {
|
|
SET_LAST_ERROR_RETURNED();
|
|
*pfSuccess = a->fSuccess;
|
|
} else {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "");
|
|
*pfSuccess = FALSE;
|
|
}
|
|
|
|
return m.ReturnValue;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !defined(BUILD_CSRWOW64)
|
|
|
|
typedef struct _EXITWINDOWSDATA {
|
|
UINT uFlags;
|
|
DWORD dwReserved;
|
|
} EXITWINDOWSDATA, *PEXITWINDOWSDATA;
|
|
|
|
DWORD ExitWindowsThread(PVOID pvParam);
|
|
|
|
|
|
BOOL WINAPI ExitWindowsWorker(UINT uFlags, DWORD dwReserved, BOOL fSecondThread)
|
|
{
|
|
EXITWINDOWSDATA ewd;
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
DWORD dwExitCode;
|
|
DWORD idWait;
|
|
MSG msg;
|
|
BOOL fSuccess;
|
|
NTSTATUS Status;
|
|
|
|
/*
|
|
* Force a connection so apps will have a windowstation
|
|
* to log off of.
|
|
*/
|
|
if (PtiCurrent() == NULL)
|
|
return FALSE;
|
|
|
|
/*
|
|
* Check for UI restrictions
|
|
*/
|
|
if (!NtUserCallOneParam((ULONG_PTR)uFlags, SFI_PREPAREFORLOGOFF)) {
|
|
RIPMSG0(RIP_WARNING, "ExitWindows called by a restricted thread\n");
|
|
return FALSE;
|
|
}
|
|
|
|
Status = CallUserpExitWindowsEx(uFlags, dwReserved, &fSuccess);
|
|
if (NT_SUCCESS( Status )) {
|
|
return fSuccess;
|
|
} else if (Status == STATUS_CANT_WAIT && !fSecondThread) {
|
|
ewd.uFlags = uFlags;
|
|
ewd.dwReserved = dwReserved;
|
|
hThread = CreateThread(NULL, 0, ExitWindowsThread, &ewd, 0, &dwThreadId);
|
|
if (hThread == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
while (1) {
|
|
idWait = MsgWaitForMultipleObjectsEx(1, &hThread, INFINITE, QS_ALLINPUT, 0);
|
|
|
|
/*
|
|
* If the thread was signaled, we're done.
|
|
*/
|
|
if (idWait == WAIT_OBJECT_0)
|
|
break;
|
|
|
|
/*
|
|
* Process any waiting messages
|
|
*/
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
DispatchMessage(&msg);
|
|
}
|
|
GetExitCodeThread(hThread, &dwExitCode);
|
|
NtClose(hThread);
|
|
if (dwExitCode == ERROR_SUCCESS)
|
|
return TRUE;
|
|
else {
|
|
RIPERR0(dwExitCode, RIP_VERBOSE, "");
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
RIPNTERR0(Status, RIP_VERBOSE, "");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD ExitWindowsThread(PVOID pvParam)
|
|
{
|
|
PEXITWINDOWSDATA pewd = pvParam;
|
|
DWORD dwExitCode;
|
|
|
|
if (ExitWindowsWorker(pewd->uFlags, pewd->dwReserved, TRUE))
|
|
dwExitCode = 0;
|
|
else
|
|
dwExitCode = GetLastError();
|
|
|
|
ExitThread(dwExitCode);
|
|
return 0;
|
|
}
|
|
|
|
|
|
BOOL WINAPI ExitWindowsEx(UINT uFlags, DWORD dwReserved)
|
|
{
|
|
return ExitWindowsWorker(uFlags, dwReserved, FALSE);
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !defined(BUILD_WOW6432)
|
|
BOOL WINAPI EndTask(HWND hwnd, BOOL fShutdown, BOOL fForce)
|
|
{
|
|
USER_API_MSG m;
|
|
PENDTASKMSG a = &m.u.EndTask;
|
|
|
|
a->hwnd = hwnd;
|
|
a->fShutdown = fShutdown;
|
|
a->fForce = fForce;
|
|
CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpEndTask), sizeof( *a ));
|
|
if (NT_SUCCESS( m.ReturnValue )) {
|
|
SET_LAST_ERROR_RETURNED();
|
|
return a->fSuccess;
|
|
} else {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
VOID APIENTRY Logon(BOOL fLogon)
|
|
{
|
|
USER_API_MSG m;
|
|
PLOGONMSG a = &m.u.Logon;
|
|
|
|
a->fLogon = fLogon;
|
|
CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpLogon), sizeof(*a));
|
|
}
|
|
|
|
|
|
NTSTATUS APIENTRY CallUserpRegisterLogonProcess(IN DWORD dwProcessId)
|
|
{
|
|
USER_API_MSG m;
|
|
PLOGONMSG a = &m.u.Logon;
|
|
NTSTATUS Status;
|
|
|
|
m.u.IdLogon = dwProcessId;
|
|
Status = CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpRegisterLogonProcess), sizeof(*a));
|
|
return Status;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !defined(BUILD_CSRWOW64)
|
|
extern BOOL gfLogonProcess;
|
|
BOOL RegisterLogonProcess(DWORD dwProcessId, BOOL fSecure)
|
|
{
|
|
gfLogonProcess = (BOOL)NtUserCallTwoParam(dwProcessId, fSecure, SFI__REGISTERLOGONPROCESS);
|
|
|
|
/*
|
|
* Now, register the logon process into winsrv.
|
|
*/
|
|
if (gfLogonProcess) {
|
|
CallUserpRegisterLogonProcess(dwProcessId);
|
|
}
|
|
|
|
return gfLogonProcess;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !defined(BUILD_WOW6432)
|
|
BOOL WINAPI RegisterServicesProcess(DWORD dwProcessId)
|
|
{
|
|
USER_API_MSG m;
|
|
PREGISTERSERVICESPROCESSMSG a = &m.u.RegisterServicesProcess;
|
|
|
|
a->dwProcessId = dwProcessId;
|
|
CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpRegisterServicesProcess), sizeof( *a ));
|
|
if (NT_SUCCESS( m.ReturnValue )) {
|
|
SET_LAST_ERROR_RETURNED();
|
|
return a->fSuccess;
|
|
} else {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
HDESK WINAPI GetThreadDesktop(DWORD dwThreadId)
|
|
{
|
|
USER_API_MSG m;
|
|
PGETTHREADCONSOLEDESKTOPMSG a = &m.u.GetThreadConsoleDesktop;
|
|
|
|
a->dwThreadId = dwThreadId;
|
|
CsrClientCallServer( (PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER( USERSRV_SERVERDLL_INDEX, UserpGetThreadConsoleDesktop), sizeof( *a ));
|
|
if (NT_SUCCESS( m.ReturnValue )) {
|
|
return NtUserGetThreadDesktop(dwThreadId, a->hdeskConsole);
|
|
} else {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* DeviceEventWorker
|
|
|
|
* This is a private (not publicly exported) interface that the user-mode
|
|
* pnp manager calls when it needs to send a WM_DEVICECHANGE message to a
|
|
* specific window handle. The user-mode pnp manager is a service within
|
|
* services.exe and as such is not on the interactive window station and
|
|
* active desktop, so it can't directly call SendMessage. For broadcasted
|
|
* messages (messages that go to all top-level windows), the user-mode pnp
|
|
* manager calls BroadcastSystemMessage directly.
|
|
|
|
* PaulaT 06/04/97
|
|
|
|
*/
|
|
ULONG WINAPI DeviceEventWorker(IN HWND hWnd, IN WPARAM wParam, IN LPARAM lParam, IN DWORD dwFlags, OUT PDWORD pdwResult)
|
|
{
|
|
USER_API_MSG m;
|
|
PDEVICEEVENTMSG a = &m.u.DeviceEvent;
|
|
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
|
|
int cb = 0;
|
|
|
|
a->hWnd = hWnd;
|
|
a->wParam = wParam;
|
|
a->lParam = lParam;
|
|
a->dwFlags = dwFlags;
|
|
a->dwResult = 0;
|
|
|
|
// If lParam is specified, it must be marshalled (see the defines for this structure in dbt.h - the structure always starts with DEV_BROADCAST_HDR structure).
|
|
if (lParam) {
|
|
cb = ((PDEV_BROADCAST_HDR)lParam)->dbch_size;
|
|
|
|
CaptureBuffer = CsrAllocateCaptureBuffer(1, cb);
|
|
if (CaptureBuffer == NULL) {
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
CsrCaptureMessageBuffer(CaptureBuffer, (PCHAR)lParam, cb, (PVOID *)&a->lParam);
|
|
|
|
// This ends up calling SrvDeviceEvent routine in the server.
|
|
CsrClientCallServer((PCSR_API_MSG)&m, CaptureBuffer, CSR_MAKE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpDeviceEvent), sizeof(*a));
|
|
CsrFreeCaptureBuffer(CaptureBuffer);
|
|
} else {
|
|
// This ends up calling SrvDeviceEvent routine in the server.
|
|
CsrClientCallServer((PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpDeviceEvent), sizeof(*a));
|
|
}
|
|
|
|
if (NT_SUCCESS(m.ReturnValue)) {
|
|
*pdwResult = (DWORD)a->dwResult;
|
|
} else {
|
|
RIPMSG0(RIP_WARNING, "DeviceEventWorker failed.");
|
|
}
|
|
|
|
return m.ReturnValue;
|
|
} // DeviceEventWorker
|
|
|
|
|
|
#if DBG
|
|
VOID APIENTRY CsrWin32HeapFail(IN DWORD dwFlags, IN BOOL bFail)
|
|
{
|
|
USER_API_MSG m;
|
|
PWIN32HEAPFAILMSG a = &m.u.Win32HeapFail;
|
|
|
|
a->dwFlags = dwFlags;
|
|
a->bFail = bFail;
|
|
|
|
CsrClientCallServer((PCSR_API_MSG)&m, NULL, CSR_MAKE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpWin32HeapFail), sizeof(*a));
|
|
if (!NT_SUCCESS(m.ReturnValue)) {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "UserpWin32HeapFail failed");
|
|
}
|
|
}
|
|
|
|
|
|
UINT APIENTRY CsrWin32HeapStat(PDBGHEAPSTAT phs, DWORD dwLen)
|
|
{
|
|
USER_API_MSG m;
|
|
PWIN32HEAPSTATMSG a = &m.u.Win32HeapStat;
|
|
PCSR_CAPTURE_HEADER CaptureBuffer = NULL;
|
|
|
|
a->dwLen = dwLen;
|
|
|
|
CaptureBuffer = CsrAllocateCaptureBuffer(1, dwLen);
|
|
if (CaptureBuffer == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
CsrCaptureMessageBuffer(CaptureBuffer, (PCHAR)phs, dwLen, (PVOID *)&a->phs);
|
|
CsrClientCallServer((PCSR_API_MSG)&m, CaptureBuffer, CSR_MAKE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpWin32HeapStat), sizeof(*a));
|
|
if (!NT_SUCCESS(m.ReturnValue)) {
|
|
RIPNTERR0(m.ReturnValue, RIP_VERBOSE, "UserpWin32HeapStat failed");
|
|
a->dwMaxTag = 0;
|
|
goto ErrExit;
|
|
}
|
|
RtlMoveMemory(phs, a->phs, dwLen);
|
|
|
|
ErrExit:
|
|
CsrFreeCaptureBuffer(CaptureBuffer);
|
|
return a->dwMaxTag;
|
|
}
|
|
#endif // DBG
|
|
|
|
|
|
#endif |