mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
382 lines
7.9 KiB
382 lines
7.9 KiB
|
|
/*++
|
|
|
|
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);
|
|
|
|
}
|
|
|