/*++ 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\ ... // 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); }