windows-nt/Source/XPSP1/NT/base/win32/client/sessdev.c
2020-09-26 16:20:57 +08:00

383 lines
7.9 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
sessdev.c
Abstract:
Per Session Dos Device access routines
Author:
Revision History:
--*/
#include "basedll.h"
#define SESSION0_ROOT L"GLOBALROOT"
#define SESSIONX_ROOT L"GLOBALROOT\\Sessions\\"
BOOL
WINAPI
DosPathToSessionPathA(
IN DWORD SessionId,
IN LPCSTR pInPath,
OUT LPSTR *ppOutPath
)
/*++
Routine Description:
Converts a DOS path relative to the current session to a DOS path
that allows access to a specific session.
Arguments:
SessionId - SessionId to access.
pInPath - WIN32 DOS path. Could be of the form "C:", "LPT1:",
"C:\file\path", etc.
ppOutPath - Output path that accesses the specified session.
If pIniPath is "C:" and SessionId is 6, the output would be
"GLOBALROOT\Sessions\6\DosDevices\C:".
Return Value:
TRUE - Path returned in *ppOutPath in newly allocated memory from
LocalAlloc.
FALSE - Call failed. Error code returned via GetLastError()
--*/
{
BOOL rc;
DWORD Len;
PCHAR Buf;
NTSTATUS Status;
PWCHAR pOutPath;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
// if the input path is null or the pointer is a bad pointer, return
// an error.
if( (pInPath == 0) ||
(IsBadReadPtr( pInPath, sizeof( CHAR ))) ||
(IsBadWritePtr( ppOutPath, sizeof(LPSTR) )) ) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
try {
RtlInitAnsiString( &AnsiString, pInPath );
Status = RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, TRUE );
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
return FALSE;
}
rc = DosPathToSessionPathW(
SessionId,
UnicodeString.Buffer,
&pOutPath
);
RtlFreeUnicodeString( &UnicodeString );
if( !rc ) {
return( rc );
}
RtlInitUnicodeString( &UnicodeString, pOutPath );
Status = RtlUnicodeStringToAnsiString( &AnsiString, &UnicodeString, TRUE );
if (!NT_SUCCESS( Status )) {
BaseSetLastNTError( Status );
LocalFree( pOutPath );
return FALSE;
}
Len = strlen( AnsiString.Buffer ) + 1;
Buf = LocalAlloc(LMEM_FIXED, Len);
if( Buf == NULL ) {
LocalFree( pOutPath );
RtlFreeAnsiString( &AnsiString );
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
strcpy( Buf, AnsiString.Buffer );
*ppOutPath = Buf;
LocalFree( pOutPath );
RtlFreeAnsiString( &AnsiString );
return(TRUE);
}
BOOL
WINAPI
DosPathToSessionPathW(
IN DWORD SessionId,
IN LPCWSTR pInPath,
OUT LPWSTR *ppOutPath
)
/*++
Routine Description:
Converts a DOS path relative to the current session to a DOS path
that allows access to a specific session.
Arguments:
SessionId - SessionId to access.
pInPath - WIN32 DOS path. Could be of the form "C:", "LPT1:",
"C:\file\path", etc.
ppOutPath - Output path that accesses the specified session.
If pIniPath is "C:" and SessionId is 6, the output would be
"GLOBALROOT\Sessions\6\DosDevices\C:".
Return Value:
TRUE - Path returned in *ppOutPath in newly allocated memory from
LocalAlloc.
FALSE - Call failed. Error code returned via GetLastError()
--*/
{
PWCHAR Buf;
ULONG Len;
//
// SessionId 0 has no per session object directories.
//
if (BaseStaticServerData->LUIDDeviceMapsEnabled == TRUE) {
Len = 0;
} else {
if( SessionId == 0 ) {
Len = wcslen(SESSION0_ROOT);
}
else {
Len = wcslen(SESSIONX_ROOT);
Len += 10; // Max DWORD width
}
}
Len += 13; // \DosDevices\ ... <NULL>
// if the input path is null or the pointer is a bad pointer, return
// an error.
if( (pInPath == 0) ||
(IsBadReadPtr( pInPath, sizeof( WCHAR ))) ||
(IsBadWritePtr( ppOutPath, sizeof(LPWSTR) )) ) {
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
Len += wcslen(pInPath);
Buf = LocalAlloc(LMEM_FIXED, Len * sizeof(WCHAR));
if( Buf == NULL ) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(FALSE);
}
try {
if (BaseStaticServerData->LUIDDeviceMapsEnabled == TRUE) {
// C: -> C:
swprintf(
Buf,
L"%ws",
pInPath
);
} else {
if( SessionId == 0 ) {
// C: -> GLOBALROOT\DosDevices\C:
swprintf(
Buf,
L"%ws\\DosDevices\\%ws",
SESSION0_ROOT,
pInPath
);
}
else {
// C: -> GLOBALROOT\Sessions\6\DosDevices\C:
swprintf(
Buf,
L"%ws%u\\DosDevices\\%ws",
SESSIONX_ROOT,
SessionId,
pInPath
);
}
}
*ppOutPath = Buf;
} except (EXCEPTION_EXECUTE_HANDLER) {
BaseSetLastNTError(GetExceptionCode());
return(FALSE);
}
return(TRUE);
}
BOOL
WINAPI
ProcessIdToSessionId(
IN DWORD dwProcessId,
OUT DWORD *pSessionId
)
/*++
Routine Description:
Given a ProcessId, return the SessionId.
This is useful for services that impersonate a caller, and
redefine a drive letter for the caller. An example is the
workstation service. Transport specific routines allow the
ProcessId of the caller to be retrieved.
Arguments:
Process - Process identifies process to
return the SessionId for.
pSessionId - returned SessionId.
Return Value:
TRUE - SessionId returned in *pSessionId
FALSE - Call failed. Error code returned via GetLastError()
--*/
{
HANDLE Handle;
NTSTATUS Status;
CLIENT_ID ClientId;
OBJECT_ATTRIBUTES Obja;
PROCESS_SESSION_INFORMATION Info;
if( IsBadWritePtr( pSessionId, sizeof(DWORD) ) ) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
InitializeObjectAttributes(
&Obja,
NULL,
0,
NULL,
NULL
);
ClientId.UniqueProcess = (HANDLE) LongToHandle(dwProcessId);
ClientId.UniqueThread = (HANDLE)NULL;
Status = NtOpenProcess(
&Handle,
(ACCESS_MASK)PROCESS_QUERY_INFORMATION,
&Obja,
&ClientId
);
if( !NT_SUCCESS(Status) ) {
SetLastError(RtlNtStatusToDosError(Status));
return(FALSE);
}
Status = NtQueryInformationProcess(
Handle,
ProcessSessionInformation,
&Info,
sizeof(Info),
NULL
);
if( !NT_SUCCESS(Status) ) {
NtClose( Handle );
SetLastError(RtlNtStatusToDosError(Status));
return(FALSE);
}
*pSessionId = Info.SessionId;
NtClose( Handle );
return(TRUE);
}
DWORD
WINAPI
WTSGetActiveConsoleSessionId ()
/*++
Routine Description:
returns the Session ID for the session, attached to Console.
Arguments:
none
Return Value:
SessionID for the console (session attached to console not necessarily session 0 ) session.
return 0xFFFFFFFF if there is no session attached to console.
This could happen if session disconnect / connect is taking place
This is a session id for the session currently connected to console, it changes when
new session is connected at console. to keep track of the current console sesion, use
WTSRegisterSessionNotification
--*/
{
return (USER_SHARED_DATA->ActiveConsoleId);
}