Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2507 lines
65 KiB

/*++
* File name:
* tclient.c
* Contents:
* Initialization code. Global feedback thread
*
* Copyright (C) 1998-1999 Microsoft Corp.
*
--*/
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <malloc.h>
#include <process.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <direct.h>
#include <winsock.h>
#include <tchar.h>
#define WIDE2ANSI(_p_, _s_) \
if ( NULL != _s_ ) \
{ \
size_t len = wcslen( _s_ ) + 1; \
size_t wlen = sizeof(wchar_t) * len; \
char *wc = (char *)_alloca( wlen ); \
\
WideCharToMultiByte( \
CP_UTF8, 0, _s_, -1, wc, (int)wlen, NULL, NULL \
); \
_p_ = wc; \
} else { \
_p_ = NULL; \
}
#include "tclient.h"
#define PROTOCOLAPI __declspec(dllexport)
#include "protocol.h"
#include "queues.h"
#include "bmpcache.h"
#include "extraexp.h"
#include "scfuncs.h"
//
// COM support.
//
#include "resource.h"
#include "initguid.h"
#include "tclientax.h"
#include "tclientaxobj.h"
#include <atlwin.cpp>
#include <atlctl.cpp>
#define IID_DEFINED
#include "tclientax_i.c"
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_CTClient, CTClientApi)
END_OBJECT_MAP()
//
// Use C linkage for global data.
//
extern "C" {
/*
* stolen from tssec.h
*/
VOID
_stdcall
TSRNG_Initialize(
VOID
);
BOOL
_stdcall
TSRNG_GenerateRandomBits(
LPBYTE pbRandomKey,
DWORD dwRandomKeyLen
);
BOOL
_stdcall
EncryptDecryptLocalData50(
LPBYTE pbData,
DWORD dwDataLen,
LPBYTE pbSalt,
DWORD dwSaltLen
);
/*
* Internal functions definitions
*/
BOOL _RegisterWindow(VOID);
LRESULT CALLBACK _FeedbackWndProc( HWND , UINT, WPARAM, LPARAM);
BOOL _CreateFeedbackThread(VOID);
VOID _DestroyFeedbackThread(VOID);
VOID _CleanStuff(VOID);
/*
* Global data
*/
OSVERSIONINFOEXW g_OsInfo;
HWND g_hWindow = NULL; // Window handle for the feedback thread
HINSTANCE g_hInstance = NULL; // Dll instance
PWAIT4STRING g_pWaitQHead = NULL; // Linked list for waited events
PFNPRINTMESSAGE g_pfnPrintMessage= NULL;// Trace function (from smclient)
PCONNECTINFO g_pClientQHead = NULL; // LL of all threads
HANDLE g_hThread = NULL; // Feedback Thread handle
LPCRITICAL_SECTION g_lpcsGuardWaitQueue = NULL;
// Guards the access to all
// global variables
// Some strings we are expecting and response actions
// Those are used in SCConnect, _Logon and SCStart
CHAR g_strConsoleExtension[ MAX_STRING_LENGTH ];
// Ferit's extension for the
// console
// Low Speed option
// Cache Bitmaps on disc option
// by default, client will not run
// in full screen
INT g_ConnectionFlags = TSFLAG_COMPRESSION|TSFLAG_BITMAPCACHE|TSFLAG_DRIVES|TSFLAG_PORTS;
// Apply translation so the english strings are human readable
// when language packs are installed
//
INT g_bTranslateStrings = 0;
/*++
* Function:
* InitDone
*
* Description:
* Initialize/delete global data. Create/destroy
* feedback thread
*
* Arguments:
* hDllInst - Instance to the DLL
* bInit - TRUE if initialize
*
* Return value:
* TRUE if succeeds
*
--*/
int InitDone(HINSTANCE hDllInst, int bInit)
{
int rv = TRUE;
if (bInit)
{
WCHAR szMyLibName[_MAX_PATH];
//
// Initialize the COM module.
//
_Module.Init(ObjectMap, hDllInst);
g_lpcsGuardWaitQueue = (LPCRITICAL_SECTION) malloc(sizeof(*g_lpcsGuardWaitQueue));
if (!g_lpcsGuardWaitQueue)
{
rv = FALSE;
goto exitpt;
}
// Overreference the library
// The reason for that is beacuse an internal thread is created.
// When the library trys to unload it can't kill that thread
// and wait for its handle to get signaled, because
// the thread itself wants to go to DllEntry and this
// causes a deadlock. The best solution is to overreference the
// handle so the library is unload at the end of the process
if (!GetModuleFileNameW(hDllInst,
szMyLibName,
sizeof(szMyLibName) / sizeof(*szMyLibName)))
{
TRACE((ERROR_MESSAGE, "Can't overref the dll. Exit.\n"));
free(g_lpcsGuardWaitQueue);
rv = FALSE;
goto exitpt;
}
else {
szMyLibName[SIZEOF_ARRAY(szMyLibName) - 1] = 0;
}
if (!LoadLibraryW(szMyLibName))
{
TRACE((ERROR_MESSAGE, "Can't overref the dll. Exit.\n"));
free(g_lpcsGuardWaitQueue);
rv = FALSE;
goto exitpt;
}
// get the OS info
ZeroMemory(&g_OsInfo, sizeof(g_OsInfo));
g_OsInfo.dwOSVersionInfoSize = sizeof(g_OsInfo);
if (!GetVersionExW((LPOSVERSIONINFOW)&g_OsInfo))
{
//
// Windows 9x does not support OSVERSIONINFOEX, so retry with
// OSVERSIONINFO.
//
ZeroMemory(&g_OsInfo, sizeof(g_OsInfo));
g_OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
if (!GetVersionExW((LPOSVERSIONINFOW)&g_OsInfo))
{
TRACE((ERROR_MESSAGE, "GetVersionEx failed.Exit\n"));
free(g_lpcsGuardWaitQueue);
rv = FALSE;
goto exitpt;
}
}
g_hInstance = hDllInst;
InitializeCriticalSection(g_lpcsGuardWaitQueue);
InitCache();
if (_RegisterWindow()) // If failed to register the window,
_CreateFeedbackThread(); // means the feedback thread will
// not work
} else
{
if (g_pWaitQHead || g_pClientQHead)
{
TRACE((ERROR_MESSAGE,
"The Library unload is unclean. Will try to fix this\n"));
_CleanStuff();
}
_DestroyFeedbackThread();
DeleteCache();
if (g_lpcsGuardWaitQueue)
{
DeleteCriticalSection(g_lpcsGuardWaitQueue);
free(g_lpcsGuardWaitQueue);
}
g_lpcsGuardWaitQueue = NULL;
g_hInstance = NULL;
g_pfnPrintMessage = NULL;
//
// Terminate the COM module.
//
_Module.Term();
}
exitpt:
return rv;
}
#if 0
VOID
_ConvertAnsiToUnicode( LPWSTR wszDst, LPWSTR wszSrc )
{
#define _TOHEX(_d_) ((_d_ <= '9' && _d_ >= '0')?_d_ - '0': \
(_d_ <= 'f' && _d_ >= 'a')?_d_ - 'a' + 10: \
(_d_ <= 'F' && _d_ >= 'F')?_d_ - 'A' + 10:0)
while( wszSrc[0] && wszSrc[1] && wszSrc[2] && wszSrc[3] )
{
*wszDst = (WCHAR)((_TOHEX(wszSrc[0]) << 4) + _TOHEX(wszSrc[1]) +
(((_TOHEX(wszSrc[2]) << 4) + _TOHEX(wszSrc[3])) << 8));
wszDst ++;
wszSrc += 4;
}
*wszDst = 0;
#undef _TOHEX
}
/*
*
* Wrappers for GetPrivateProfileW, on Win95 there's no UNICODE veriosn
* of this function
*
*/
DWORD
_WrpGetPrivateProfileStringW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName)
{
DWORD rv = 0;
CHAR szAppName[MAX_STRING_LENGTH];
CHAR szKeyName[MAX_STRING_LENGTH];
CHAR szDefault[MAX_STRING_LENGTH];
CHAR szReturnedString[MAX_STRING_LENGTH];
CHAR szReturnedStringNonExp[MAX_STRING_LENGTH];
CHAR szFileName[MAX_STRING_LENGTH];
LPWSTR szwReturnedString = NULL;
ASSERT( 0 != nSize );
if ( nSize < wcslen( lpDefault ))
wcsncpy( lpReturnedString, lpDefault, nSize - 1 );
else
wcscpy( lpReturnedString, lpDefault );
__try {
szwReturnedString = (LPWSTR) alloca(( nSize + 1 ) * sizeof( WCHAR ));
} __except( EXCEPTION_EXECUTE_HANDLER ) {
szwReturnedString = NULL;
}
if ( !szwReturnedString )
goto exitpt;
if (ISNT())
{
rv = GetPrivateProfileStringW(
lpAppName,
lpKeyName,
lpDefault,
szwReturnedString,
nSize,
lpFileName);
if (rv)
{
goto exitpt;
}
}
// Call the ANSI version
_snprintf(szAppName, MAX_STRING_LENGTH, "%S", lpAppName);
_snprintf(szKeyName, MAX_STRING_LENGTH, "%S", lpKeyName);
_snprintf(szFileName, MAX_STRING_LENGTH, "%S", lpFileName);
_snprintf(szDefault, MAX_STRING_LENGTH, "%S", lpDefault);
rv = GetPrivateProfileStringA(
szAppName,
szKeyName,
szDefault,
szReturnedStringNonExp,
sizeof(szReturnedString),
szFileName);
ExpandEnvironmentStringsA(
szReturnedStringNonExp,
szReturnedString,
sizeof(szReturnedString)
);
_snwprintf(lpReturnedString, nSize, L"%S", szReturnedString);
lpReturnedStrig[ nSize - 1 ] = 0;
exitpt:
if ( NULL != szwReturnedString )
{
// expand the string
//
ExpandEnvironmentStringsW(
szwReturnedString,
lpReturnedString,
nSize
);
}
if ( L'\\' == lpReturnedString[0] &&
L'U' == towupper(lpReturnedString[1]))
_ConvertAnsiToUnicode( lpReturnedString, lpReturnedString + 2 );
return rv;
}
UINT
_WrpGetPrivateProfileIntW(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
INT nDefault,
LPCWSTR lpFileName)
{
UINT rv = (UINT)-1;
CHAR szAppName[MAX_STRING_LENGTH];
CHAR szKeyName[MAX_STRING_LENGTH];
CHAR szFileName[MAX_STRING_LENGTH];
rv = GetPrivateProfileIntW(
lpAppName,
lpKeyName,
nDefault,
lpFileName);
if (rv != (UINT)-1 && rv)
goto exitpt;
// Call the ANSI version
_snprintf(szAppName, MAX_STRING_LENGTH, "%S", lpAppName);
_snprintf(szKeyName, MAX_STRING_LENGTH, "%S", lpKeyName);
_snprintf(szFileName, MAX_STRING_LENGTH, "%S", lpFileName);
rv = GetPrivateProfileIntA(
szAppName,
szKeyName,
nDefault,
szFileName);
exitpt:
return rv;
}
LONG RegCreateKeyExWrp(
HKEY hkey,
LPCWSTR lpSubKey,
DWORD Reserved,
LPWSTR lpClass,
DWORD dwOptions,
REGSAM samDesired,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
PHKEY phkResult,
PDWORD lpdwDisposition
)
{
LONG rv;
if (!ISWIN9X())
{
return RegCreateKeyExW( hkey, lpSubKey, Reserved,
lpClass, dwOptions, samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition );
}
__try {
CHAR *lpSubKeyA;
CHAR *lpClassA;
WIDE2ANSI( lpSubKeyA, lpSubKey );
WIDE2ANSI( lpClassA, lpClass );
rv = RegCreateKeyExA( hkey, lpSubKeyA, Reserved,
lpClassA, dwOptions, samDesired,
lpSecurityAttributes,
phkResult,
lpdwDisposition );
} __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW)?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
rv = ERROR_STACK_OVERFLOW;
}
return rv;
}
LONG
RegSetValueExWrp(
HKEY hkey,
LPCWSTR lpValueName,
DWORD reserved,
DWORD dwType,
CONST BYTE *lpData,
DWORD cbData
)
{
LONG rv;
if (!ISWIN9X())
{
return RegSetValueEx(
hkey, lpValueName, reserved, dwType, lpData, cbData );
}
__try {
CHAR *lpValueNameA;
CHAR *lpDataA;
WIDE2ANSI( lpValueNameA, lpValueName );
if ( REG_SZ == dwType )
{
WIDE2ANSI( lpDataA, ((LPCWSTR)lpData) );
lpData = (CONST BYTE *)lpDataA;
cbData = (DWORD)strlen( lpDataA );
}
rv = RegSetValueExA( hkey, lpValueNameA, reserved, dwType, lpData, cbData );
} __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
rv = ERROR_STACK_OVERFLOW;
}
return rv;
}
LONG RegQueryValueExWrp(
HKEY hKey, // handle to key
LPCWSTR lpValueName, // value name
PDWORD lpReserved, // reserved
PDWORD lpType, // type buffer
PBYTE lpData, // data buffer
PDWORD lpcbData // size of data buffer
)
{
LONG rv;
if (!ISWIN9X())
{
return RegQueryValueEx( hKey, lpValueName, lpReserved, lpType, lpData, lpcbData );
}
__try {
CHAR *lpValueNameA;
WIDE2ANSI( lpValueNameA, lpValueName );
rv = RegQueryValueExA( hKey, lpValueNameA, lpReserved, lpType, lpData, lpcbData );
} __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
rv = ERROR_STACK_OVERFLOW;
}
return rv;
}
LONG
RegDeleteKeyWrp(
HKEY hkey,
LPCWSTR lpSubKey
)
{
LONG rv;
if ( !ISWIN9X() )
{
return RegDeleteKeyW( hkey, lpSubKey );
}
__try {
CHAR *lpSubKeyA;
WIDE2ANSI( lpSubKeyA, lpSubKey );
rv = RegDeleteKeyA( hkey, lpSubKeyA );
} __except( (GetExceptionCode() == STATUS_STACK_OVERFLOW) ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH )
{
rv = ERROR_STACK_OVERFLOW;
}
return rv;
}
INT
GetClassNameWrp(
HWND hwnd,
LPWSTR szName,
INT max
)
{
LPSTR szNameA;
INT maxA;
INT rv;
if ( !ISWIN9X() )
{
return GetClassNameW( hwnd, szName,max );
}
maxA = max / sizeof( WCHAR );
__try {
szNameA = (LPSTR)_alloca( maxA );
} __except( EXCEPTION_EXECUTE_HANDLER )
{
SetLastError( ERROR_STACK_OVERFLOW );
rv = 0;
goto exitpt;
}
rv = GetClassNameA( hwnd, szNameA, maxA );
MultiByteToWideChar( CP_UTF8, 0, szNameA, maxA, szName, max );
exitpt:
return rv;
}
INT
GetWindowTextWrp(
HWND hwnd,
LPWSTR szText,
INT max
)
{
LPSTR szTextA;
INT maxA;
INT rv;
if ( !ISWIN9X() )
{
return GetWindowTextW( hwnd, szText ,max );
}
maxA = max / sizeof( WCHAR );
__try {
szTextA = (LPSTR)_alloca( maxA );
} __except( EXCEPTION_EXECUTE_HANDLER )
{
SetLastError( ERROR_STACK_OVERFLOW );
rv = 0;
goto exitpt;
}
rv = GetClassNameA( hwnd, szTextA, maxA );
MultiByteToWideChar( CP_UTF8, 0, szTextA, maxA, szText, max );
exitpt:
return rv;
}
#endif // 0
/*++
* Function:
* ConstructLogonString
*
* Description:
* Constructs the client command line. The format is taken from
* the INI file, supports the following parameters:
* %srv% - destination server
* %usr% - username
* %psw% - password
* %dom% - domain
*
* Arguments:
*
* Return value:
* none
*
--*/
VOID
ConstructLogonString(
LPCWSTR lpszServerName,
LPCWSTR lpszUserName,
LPCWSTR lpszPassword,
LPCWSTR lpszDomain,
LPWSTR szLine,
DWORD dwSize,
PCONFIGINFO pConfig
)
{
DWORD_PTR dwFmtSize;
LPWSTR szFmt;
//
// fix the parameters
//
if ( NULL == lpszServerName )
lpszServerName = L"";
if ( NULL == lpszUserName )
lpszUserName = L"";
if ( NULL == lpszPassword )
lpszPassword = L"";
if ( NULL == lpszDomain )
lpszDomain = L"";
if ( dwSize < 1 )
return;
if ( NULL == pConfig )
return;
szFmt = pConfig->strLogonFmt;
dwFmtSize = wcslen( szFmt );
for( ; 0 != dwFmtSize && dwSize > 1 ; )
{
//
// optimize the code path
//
if ( L'%' != *szFmt )
goto copy_char;
if ( dwFmtSize >= 5 )
{
INT iNewLen;
if ( !_wcsnicmp( szFmt, L"%srv%", 5 ))
{
iNewLen = _snwprintf( szLine, dwSize,
L"%s", lpszServerName );
if ( iNewLen < 0 )
{
break;
}
szLine += iNewLen;
dwSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%usr%", 5 ))
{
iNewLen = _snwprintf( szLine, dwSize,
L"%s", lpszUserName );
if ( iNewLen < 0 )
{
break;
}
szLine += iNewLen;
dwSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%psw%", 5 ))
{
iNewLen = _snwprintf( szLine, dwSize,
L"%s", lpszPassword );
if ( iNewLen < 0 )
{
break;
}
szLine += iNewLen;
dwSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%dom%", 5 ))
{
iNewLen = _snwprintf( szLine, dwSize,
L"%s", lpszDomain );
if ( iNewLen < 0 )
{
break;
}
szLine += iNewLen;
dwSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else {
goto copy_char;
}
continue;
}
copy_char:
*szLine = *szFmt;
szLine ++;
szFmt ++;
dwSize --;
dwFmtSize --;
}
*szLine = 0;
}
/*++
* Function:
* ConstructCmdLine
*
* Description:
* Constructs the client command line. The format is taken from
* the INI file, supports the following parameters:
* %img% - the client's image
* %srv% - destination server
* %usr% - username
* %psw% - password
* %dom% - domain
* %hrs% - horizontal resolution
* %vrs% - vertical resolution
* %wnd% - tclient's window handle, for accepting feedback
* %reg% - registry referrence
* %app% - starting app
* %cwd% - (UNSUPPORTED) working directory for the app
* %con% - /console if TSFLAG_RCONSOLE is defined
*
* Arguments:
*
* Return value:
* none
*
--*/
VOID
ConstructCmdLine(
LPCWSTR lpszServerName,
LPCWSTR lpszUserName,
LPCWSTR lpszPassword,
LPCWSTR lpszDomain,
LPCWSTR lpszShell,
IN const int xRes,
IN const int yRes,
IN const int ConnectionFlags,
LPWSTR szCommandLine,
DWORD dwCmdLineSize,
PCONFIGINFO pConfig
)
{
DWORD_PTR dwFmtSize;
LPWSTR szFmt;
//
// fix the parameters
//
if ( NULL == lpszServerName )
lpszServerName = L"";
if ( NULL == lpszUserName )
lpszUserName = L"";
if ( NULL == lpszPassword )
lpszPassword = L"";
if ( NULL == lpszDomain )
lpszDomain = L"";
if ( NULL == lpszShell )
lpszShell = L"";
if ( dwCmdLineSize < 1 )
return;
if ( NULL == pConfig )
return;
szFmt = pConfig->strCmdLineFmt;
dwFmtSize = wcslen( szFmt );
for( ; 0 != dwFmtSize && dwCmdLineSize > 1 ; )
{
//
// optimize the code path
//
if ( L'%' != *szFmt )
goto copy_char;
if ( dwFmtSize >= 5 )
{
INT iNewLen;
if ( !_wcsnicmp( szFmt, L"%img%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", pConfig->strClientImg );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%srv%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", lpszServerName );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%usr%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", lpszUserName );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%psw%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", lpszPassword );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%dom%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", lpszDomain );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%hrs%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%d", xRes );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%vrs%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%d", yRes );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%con%", 5 ))
{
if (ConnectionFlags & TSFLAG_RCONSOLE)
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"-console" );
if ( iNewLen < 0 )
{
break;
}
} else
{
iNewLen = 0;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%wnd%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
#ifdef _WIN64
L"%I64d",
#else // !_WIN64
L"%d",
#endif // !_WIN64
(LONG_PTR)g_hWindow );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%reg%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
REG_FORMAT,
GetCurrentProcessId(), GetCurrentThreadId());
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else if ( !_wcsnicmp( szFmt, L"%app%", 5 ))
{
iNewLen = _snwprintf( szCommandLine, dwCmdLineSize,
L"%s", lpszShell );
if ( iNewLen < 0 )
{
break;
}
szCommandLine += iNewLen;
dwCmdLineSize -= iNewLen;
szFmt += 5;
dwFmtSize -= 5;
} else {
goto copy_char;
}
continue;
}
copy_char:
*szCommandLine = *szFmt;
szCommandLine ++;
szFmt ++;
dwCmdLineSize --;
dwFmtSize --;
}
*szCommandLine = 0;
}
/*++
* Function:
* _FeedbackWndProc
* Description:
* Window proc wich dispatches messages containing feedback
* The messages are usualy sent by RDP clients
*
--*/
LRESULT CALLBACK _FeedbackWndProc( HWND hwnd,
UINT uiMessage,
WPARAM wParam,
LPARAM lParam)
{
// HANDLE hMapF = NULL;
switch (uiMessage)
{
case WM_FB_TEXTOUT:
_TextOutReceived((DWORD)wParam, (HANDLE)lParam);
break;
case WM_FB_GLYPHOUT:
_GlyphReceived((DWORD)wParam, (HANDLE)lParam);
break;
case WM_FB_DISCONNECT:
_SetClientDead(lParam);
_CheckForWorkerWaitingDisconnect(lParam);
_CancelWaitingWorker(lParam);
break;
case WM_FB_CONNECT:
_CheckForWorkerWaitingConnect((HWND)wParam, lParam);
break;
case WM_FB_LOGON:
TRACE((INFO_MESSAGE, "LOGON event, session ID=%d\n",
wParam));
_SetSessionID(lParam, (UINT)wParam);
break;
break;
case WM_FB_ACCEPTME:
return (_CheckIsAcceptable(lParam, FALSE) != NULL);
case WM_FB_REPLACEPID:
return (_ReplaceProcessId( wParam, lParam ));
#ifdef _RCLX
case WM_WSOCK: // Windows socket messages
RClx_DispatchWSockEvent((SOCKET)wParam, lParam);
break;
#endif // _RCLX
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProcA(hwnd, uiMessage, wParam, lParam);
}
return 0;
}
/*++
* Function:
* _RegisterWindow
* Description:
* Resgisters window class for the feedback dispatcher
* Arguments:
* none
* Return value:
* TRUE on success
*
--*/
BOOL _RegisterWindow(VOID)
{
WNDCLASSA wc;
BOOL rv = FALSE;
// DWORD dwLastErr;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = _FeedbackWndProc;
wc.hInstance = g_hInstance;
wc.lpszClassName = _TSTNAMEOFCLAS;
if (!RegisterClassA (&wc) &&
GetLastError() &&
GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
{
TRACE((ERROR_MESSAGE,
"Can't register class. GetLastError=%d\n",
GetLastError()));
goto exitpt;
}
rv = TRUE;
exitpt:
return rv;
}
/*++
* Function:
* _GoFeedback
* Description:
* Main function for the feedback thread. The thread is created for the
* lifetime of the DLL
* Arguments:
* lpParam is unused
* Return value:
* Thread exit code
--*/
DWORD WINAPI _GoFeedback(LPVOID lpParam)
{
MSG msg;
UNREFERENCED_PARAMETER(lpParam);
g_hWindow = CreateWindowA(
_TSTNAMEOFCLAS,
NULL, // Window name
0, // dwStyle
0, // x
0, // y
0, // nWidth
0, // nHeight
NULL, // hWndParent
NULL, // hMenu
g_hInstance,
NULL); // lpParam
if (!g_hWindow)
{
TRACE((ERROR_MESSAGE, "No feedback window handle"));
goto exitpt;
} else {
#ifdef _RCLX
if (!RClx_Init())
TRACE((ERROR_MESSAGE, "Can't initialize RCLX\n"));
#endif // _RCLX
while (GetMessageA (&msg, NULL, 0, 0) && msg.message != WM_FB_END)
{
DispatchMessageA (&msg);
}
#ifdef _RCLX
RClx_Done();
#endif // _RCLX
}
TRACE((INFO_MESSAGE, "Window/Thread destroyed\n"));
FreeLibraryAndExitThread(g_hInstance, 0);
exitpt:
return 1;
}
VOID
SetAllowBackgroundInput(
VOID
)
{
DWORD ResId;
LONG sysrc;
HKEY key;
DWORD disposition;
ResId = 1;
// sysrc = RegCreateKeyExWrp(HKEY_CURRENT_USER,
sysrc = RegCreateKeyExW(HKEY_CURRENT_USER,
REG_BASE,
0, /* reserved */
NULL, /* class */
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, /* security attributes */
&key,
&disposition);
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegCreateKeyEx failed, sysrc = %d\n", sysrc));
goto exitpt;
}
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
ALLOW_BACKGROUND_INPUT,
0,
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
RegCloseKey(key);
exitpt:
;
}
/*
* Disables prompting the user for redirected drives and ports (may be even more stuff)
*
*/
BOOL
_DisablePrompting(
LPCWSTR szServerName,
INT ConnectionFlags
)
{
BOOL rv = FALSE;
LONG rc;
HKEY hKey = NULL;
DWORD dwType, dwSize, dwData, dwDisp;
DWORD dwPromptFlags = 0;
if ( ConnectionFlags & TSFLAG_DRIVES )
{
dwPromptFlags |= 1;
}
if ( ConnectionFlags & TSFLAG_PORTS )
{
dwPromptFlags |= 2;
}
if ( 0 == dwPromptFlags )
{
rv = TRUE;
goto exitpt;
}
// rc = RegCreateKeyExWrp(
rc = RegCreateKeyExW(
HKEY_CURRENT_USER,
REG_BASE L"\\LocalDevices",
0, // options
NULL, // class
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, // security
&hKey,
&dwDisp
);
if ( ERROR_SUCCESS != rc )
{
TRACE(( WARNING_MESSAGE, "RegOpenKeyEx failed (%d).Can't disable user prompt\n", rc ));
goto exitpt;
}
dwSize = sizeof( dwData );
// rc = RegQueryValueExWrp(
rc = RegQueryValueExW(
hKey,
szServerName,
NULL, // reserved
&dwType,
(LPBYTE)&dwData,
&dwSize
);
if ( ERROR_SUCCESS != rc ||
REG_DWORD != dwType )
{
dwData = 0;
}
dwData |= dwPromptFlags;
// rc = RegSetValueExWrp(
rc = RegSetValueExW(
hKey,
szServerName,
0,
REG_DWORD,
(LPBYTE)&dwData,
sizeof( dwData )
);
if ( ERROR_SUCCESS != rc )
{
TRACE(( WARNING_MESSAGE, "RegSetValueEx failed (%d). Can't disable user prompt\n", rc ));
}
rv = TRUE;
exitpt:
if ( NULL != hKey )
{
RegCloseKey( hKey );
}
return rv;
}
/*++
* Function:
* _SetClientRegistry
* Description:
* Sets the registry prior running RDP client
* The format of the key is: smclient_PID_TID
* PID is the process ID and TID is the thread ID
* This key is deleated after the client disconnects
* Arguments:
* lpszServerName - server to which the client will connect
* xRes, yRes - clients resolution
* bLowSpeed - low speed (compression) option
* bCacheBitmaps - cache the bitmaps to the disc option
* bFullScreen - the client will be in full screen mode
* ... - ...
* KeyboardHook - keyboard hook mode
* Called by:
* SCConnect
--*/
VOID
_SetClientRegistry(
LPCWSTR lpszServerName,
LPCWSTR lpszShell,
LPCWSTR lpszUsername,
LPCWSTR lpszPassword,
LPCWSTR lpszDomain,
INT xRes,
INT yRes,
INT Bpp,
INT AudioOpts,
PCONNECTINFO *ppCI,
INT ConnectionFlags,
INT KeyboardHook)
{
// const CHAR *pData;
// CHAR szServer[MAX_STRING_LENGTH];
// register int i;
LONG sysrc;
HKEY key;
DWORD disposition;
DWORD_PTR dataSize;
DWORD ResId;
WCHAR lpszRegistryEntry[4*MAX_STRING_LENGTH];
// RECT rcDesktop = {0, 0, 0, 0};
// INT desktopX, desktopY;
_snwprintf(lpszRegistryEntry, sizeof(lpszRegistryEntry)/sizeof( lpszRegistryEntry[0] ),
L"%s\\" REG_FORMAT,
REG_BASE, GetCurrentProcessId(), GetCurrentThreadId());
lpszRegistryEntry[ sizeof(lpszRegistryEntry)/sizeof( lpszRegistryEntry[0] ) - 1 ] = 0;
#if 0
// Get desktop size
GetWindowRect(GetDesktopWindow(), &rcDesktop);
desktopX = rcDesktop.right;
desktopY = rcDesktop.bottom;
// Adjust the resolution
if (desktopX < xRes || desktopY < yRes)
{
xRes = desktopX;
yRes = desktopY;
}
#endif
dataSize = ( wcslen(lpszServerName) + 1 ) * sizeof( WCHAR );
// Before starting ducati client set registry with server name
// sysrc = RegCreateKeyExWrp(HKEY_CURRENT_USER,
sysrc = RegCreateKeyExW(HKEY_CURRENT_USER,
lpszRegistryEntry,
0, /* reserved */
NULL, /* class */
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, /* security attributes */
&key,
&disposition);
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegCreateKeyEx failed, sysrc = %d\n", sysrc));
goto exitpt;
}
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"MRU0",
0, // reserved
REG_SZ,
(LPBYTE)lpszServerName,
(DWORD)dataSize);
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
// Set alternative shell (if specified
if (lpszShell)
{
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
TEXT("Alternate Shell 50"),
0, // reserved
REG_BINARY,
(LPBYTE)lpszShell,
(DWORD)(wcslen(lpszShell) * sizeof(*lpszShell)));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
}
// set user name
//
if (lpszUsername)
{
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
TEXT("UserName 50"),
0, // reserved
REG_BINARY,
(LPBYTE)lpszUsername,
(DWORD)(wcslen(lpszUsername) * sizeof(*lpszUsername)));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
}
// domain
//
if (lpszDomain)
{
WCHAR szBuff[MAX_STRING_LENGTH];
//
// convert lpszDomain to lower case only
// to force UpdateSessionPDU to be send from the server
//
wcsncpy( szBuff, lpszDomain, MAX_STRING_LENGTH - 1 );
_wcslwr( szBuff );
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
TEXT("Domain 50"),
0, // reserved
REG_BINARY,
(LPBYTE)szBuff,
(DWORD)(wcslen(lpszDomain) * sizeof(*lpszDomain)));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
}
// Set the resolution
if (xRes >= 1600 && yRes >= 1200) ResId = 4;
else if (xRes >= 1280 && yRes >= 1024) ResId = 3;
else if (xRes >= 1024 && yRes >= 768) ResId = 2;
else if (xRes >= 800 && yRes >= 600) ResId = 1;
else ResId = 0; // 640x480
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Desktop Size ID",
0,
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
ResId = 1;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Auto Connect",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
if ( (*ppCI)->pConfigInfo->Autologon )
{
WCHAR szEncPwd[127];
UINT cb;
BYTE Salt[20];
// password
//
if ( NULL == lpszPassword )
goto skip_pwd;
TSRNG_Initialize();
TSRNG_GenerateRandomBits( Salt, sizeof( Salt ));
wcsncpy( szEncPwd, lpszPassword, sizeof( szEncPwd ) / sizeof( szEncPwd[0]) - 1 ); // BUGBUG: AV?
szEncPwd[ sizeof( szEncPwd ) / sizeof( szEncPwd[0] ) - 1 ] = 0;
cb = sizeof(szEncPwd);
EncryptDecryptLocalData50( (LPBYTE)szEncPwd, cb,
Salt, sizeof( Salt ));
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Salt 50",
0, // reserved
REG_BINARY,
(LPBYTE)Salt,
sizeof( Salt ));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n",
sysrc));
}
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Password 50",
0, // reserved
REG_BINARY,
(LPBYTE)szEncPwd,
cb);
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n",
sysrc));
}
skip_pwd:
ResId = 1;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"AutoLogon 50",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
}
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
ResId = (ConnectionFlags & TSFLAG_BITMAPCACHE)?1:0;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"BitmapCachePersistEnable",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
ResId = (ConnectionFlags & TSFLAG_COMPRESSION)?1:0;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Compression",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegSetValue failed, status = %d\n", sysrc));
}
if (ConnectionFlags & TSFLAG_FULLSCREEN)
{
ResId = 2;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"Screen Mode ID",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
}
if (ConnectionFlags & TSFLAG_DRIVES)
{
ResId = 1;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"RedirectDrives",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
}
if (ConnectionFlags & TSFLAG_PORTS)
{
ResId = 1;
// sysrc = RegSetValueExWrp(key,
sysrc = RegSetValueExW(key,
L"RedirectComPorts",
0, // reserved
REG_DWORD,
(LPBYTE)&ResId,
sizeof(ResId));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
}
_DisablePrompting( lpszServerName, ConnectionFlags );
if ( 0 != Bpp )
{
DWORD dw = Bpp;
// sysrc = RegSetValueExWrp(
sysrc = RegSetValueExW(
key,
L"Session Bpp",
0,
REG_DWORD,
(LPBYTE)&dw,
sizeof( dw ));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
}
if ( 0 != AudioOpts )
{
DWORD dw = AudioOpts;
// sysrc = RegSetValueExWrp(
sysrc = RegSetValueExW(
key,
L"AudioMode",
0,
REG_DWORD,
(LPBYTE)&dw,
sizeof( dw ));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
}
//
// Set the keyboard-hook mode.
//
// sysrc = RegSetValueExWrp(
sysrc = RegSetValueExW(
key,
L"KeyboardHook",
0,
REG_DWORD,
(LPBYTE)&KeyboardHook,
sizeof(KeyboardHook));
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE,
"RegSetValue failed, status = %d\n", sysrc));
}
RegCloseKey(key);
exitpt:
;
}
/*++
* Function:
* _DeleteClientRegistry
* Description:
* Deletes the key set by _SetClientRegistry
* Called by:
* SCDisconnect
--*/
VOID _DeleteClientRegistry(PCONNECTINFO pCI)
{
WCHAR lpszRegistryEntry[4*MAX_STRING_LENGTH];
LONG sysrc;
_snwprintf(lpszRegistryEntry, sizeof(lpszRegistryEntry)/sizeof(lpszRegistryEntry[0]),
L"%s\\" REG_FORMAT,
REG_BASE, GetCurrentProcessId(), pCI->OwnerThreadId);
lpszRegistryEntry[ sizeof(lpszRegistryEntry)/sizeof(lpszRegistryEntry[0]) -1 ] = 0;
// sysrc = RegDeleteKeyWrp(HKEY_CURRENT_USER, lpszRegistryEntry);
sysrc = RegDeleteKeyW(HKEY_CURRENT_USER, lpszRegistryEntry);
if (sysrc != ERROR_SUCCESS)
{
TRACE((WARNING_MESSAGE, "RegDeleteKey failed, status = %d\n", sysrc));
}
}
/*++
* Function:
* _CreateFeedbackThread
* Description:
* Creates the feedback thread
* Called by:
* InitDone
--*/
BOOL _CreateFeedbackThread(VOID)
{
BOOL rv = TRUE;
// Register feedback window class
// WNDCLASS wc;
UINT dwThreadId;
// UINT dwLastErr;
g_hThread = (HANDLE)
_beginthreadex
(NULL,
0,
(unsigned (__stdcall *)(void*))_GoFeedback,
NULL,
0,
&dwThreadId);
if (!g_hThread) {
TRACE((ERROR_MESSAGE, "Couldn't create thread\n"));
rv = FALSE;
}
return rv;
}
/*++
* Function:
* _DestroyFeedbackThread
* Description:
* Destroys the thread created by _CreateFeedbackThread
* Called by:
* InitDone
--*/
VOID _DestroyFeedbackThread(VOID)
{
if (g_hThread)
{
// DWORD dwWait;
// CHAR szMyLibName[_MAX_PATH];
// Closing feedback thread
PostMessageA(g_hWindow, WM_FB_END, 0, 0);
TRACE((INFO_MESSAGE, "Closing DLL thread\n"));
// Dedstroy the window
DestroyWindow(g_hWindow);
// CloseHandle(g_hThread);
g_hThread = NULL;
}
}
/*++
* Function:
* _CleanStuff
* Description:
* Cleans the global queues. Closes any resources
* Called by:
* InitDone
--*/
VOID _CleanStuff(VOID)
{
// Thread safe, bacause is executed from DllEntry
while (g_pClientQHead)
{
TRACE((WARNING_MESSAGE, "Cleaning connection info: 0x%x\n",
g_pClientQHead));
SCDisconnect(g_pClientQHead);
}
#if 0
if (g_pClientQHead)
{
PCONNECTINFO pNext, pIter = g_pClientQHead;
while (pIter)
{
int nEv;
DWORD wres;
TRACE((WARNING_MESSAGE, "Cleaning connection info: 0x%x\n", pIter));
// Clear Events
if (pIter->evWait4Str)
{
CloseHandle(pIter->evWait4Str);
pIter->evWait4Str = NULL;
}
for (nEv = 0; nEv < pIter->nChatNum; nEv ++)
CloseHandle(pIter->aevChatSeq[nEv]);
pIter->nChatNum = 0;
// Clear Processes
do {
SendMessageA(pIter->hClient, WM_CLOSE, 0, 0);
} while((wres = WaitForSingleObject(pIter->hProcess, pCI->pConfigInfo->WAIT4STR_TIMEOUT/4) == WAIT_TIMEOUT));
if (wres == WAIT_TIMEOUT)
{
TRACE((WARNING_MESSAGE,
"Can't close process. WaitForSingleObject timeouts\n"));
TRACE((WARNING_MESSAGE,
"Process #%d will be killed\n",
pIter->dwProcessId ));
if (!TerminateProcess(pIter->hProcess, 1))
{
TRACE((WARNING_MESSAGE,
"Can't kill process #%d. GetLastError=%d\n",
pIter->dwProcessId, GetLastError()));
}
}
TRACE((WARNING_MESSAGE, "Closing process\n"));
if (pIter->hProcess)
CloseHandle(pIter->hProcess);
if (pIter->hThread)
CloseHandle(pIter->hThread);
pIter->hProcess = pIter->hThread = NULL;
// Free the structures
pNext = pIter->pNext;
free(pNext);
pIter = pNext;
}
}
#endif // 0
}
VOID _TClientAssert(BOOL bCond,
LPCSTR filename,
INT line,
LPCSTR expression,
BOOL bBreak)
{
if (!bCond)
{
TRACE((ERROR_MESSAGE,
"ASSERT (%s) %s line: %d\n",
expression,
filename,
line));
if (bBreak)
{
DebugBreak();
}
}
}
/*++
* Function:
* LoadSmClientFile
* Description:
* Loads the appropriate SMCLIENT.INI
* Called by:
* _FillConfigInfo
--*/
VOID LoadSmClientFile(WCHAR *szIniFileName, DWORD dwIniFileNameLen, LPSTR szLang)
{
WCHAR wszLang[4];
// Construct INI path
*szIniFileName = 0;
if(!_wgetcwd (
szIniFileName,
(int)(dwIniFileNameLen - wcslen(SMCLIENT_INI) - 8))
)
{
TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
}
if ( 0 == *szIniFileName )
{
CHAR szaIniFileName[_MAX_PATH];
TRACE((WARNING_MESSAGE, "Reading ASCII working dir\n"));
DWORD_PTR dwINILen = wcslen(SMCLIENT_INI);
if (!_getcwd (
szaIniFileName,
(int)(sizeof(szaIniFileName) - dwINILen - 8))
)
{
TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
}
else
{
_snwprintf(szIniFileName, dwIniFileNameLen, L"%S", szaIniFileName );
szIniFileName[ dwIniFileNameLen - 1 ] = 0;
}
if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - strlen(szLang) - 2 )
{
TRACE(( ERROR_MESSAGE, "Current directory length too long.\n"));
szIniFileName[0] = 0;
return;
}
}
// add '\' at the end if there isn't one
if (szIniFileName[wcslen(szIniFileName)-1]!=L'\\')
{
wcscat(szIniFileName, L"\\");
}
printf("Loading the smclient file \n");
wcscat(szIniFileName, SMCLIENT_INI);
if( strcmp( szLang, "0409") )
{
wcscat(szIniFileName, L".");
MultiByteToWideChar( CP_ACP, 0, szLang, -1, wszLang, sizeof(wszLang)/sizeof(wszLang[0]) );
wcscat(szIniFileName, wszLang);
}
; //return VOID
}
/*++
* Function:
* _FillConfigInfo
*
* Description:
* Reads smclient.ini, section [tclient], variable "timeout"
* Also read some other values
* Arguments:
* PCONFIGINFO
* Return value:
* none
*
--*/
VOID _FillConfigInfo(PCONFIGINFO pConfigInfo) // LPSTR szLang)
{
UINT nNew;
WCHAR szIniFileName[_MAX_PATH];
// WCHAR szBuff[ 4 * MAX_STRING_LENGTH ];
WCHAR szBuffDef[MAX_STRING_LENGTH];
BOOL bFlag;
DWORD dwIniFileNameLen = _MAX_PATH;
/* Initializing variables here */
pConfigInfo->CONNECT_TIMEOUT = 35000;
pConfigInfo->ConnectionFlags = TSFLAG_COMPRESSION|TSFLAG_BITMAPCACHE;
pConfigInfo->Autologon = 0;
pConfigInfo->UseRegistry = 1;
pConfigInfo->LoginWait = 1;
pConfigInfo->bTranslateStrings = 0;
pConfigInfo->bUnicode = 0;
pConfigInfo->KeyboardHook = TCLIENT_KEYBOARD_HOOK_FULLSCREEN;
//
// Clear the configuration info and the INI-file name.
//
ZeroMemory(pConfigInfo, sizeof(*pConfigInfo));
ZeroMemory(szIniFileName, sizeof(szIniFileName));
// LoadSmClientFile(szIniFileName, _MAX_PATH, szLang);
if(!_wgetcwd (
szIniFileName,
(int)(dwIniFileNameLen - wcslen(SMCLIENT_INI) - 1))
)
{
TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
}
if ( 0 == *szIniFileName )
{
CHAR szaIniFileName[_MAX_PATH];
TRACE((WARNING_MESSAGE, "Reading ASCII working dir\n"));
DWORD_PTR dwINILen = wcslen(SMCLIENT_INI);
if (!_getcwd (
szaIniFileName,
(int)(sizeof(szaIniFileName) - dwINILen - 1))
)
{
TRACE((ERROR_MESSAGE, "Current directory length too long.\n"));
}
else
{
_snwprintf(szIniFileName, dwIniFileNameLen, L"%S", szaIniFileName );
szIniFileName[ dwIniFileNameLen - 1 ] = 0;
}
//if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - strlen(szLang) - 2 )
if ( wcslen( szIniFileName ) > dwIniFileNameLen - wcslen(SMCLIENT_INI) - 2 )
{
TRACE(( ERROR_MESSAGE, "Current directory length too long.\n"));
szIniFileName[0] = 0;
return;
}
}
// add '\' at the end if there isn't one
if (szIniFileName[wcslen(szIniFileName)-1]!=L'\\')
{
wcscat(szIniFileName, L"\\");
}
wcscat(szIniFileName, SMCLIENT_INI);
// nNew = _WrpGetPrivateProfileIntW(
nNew = GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"timeout",
600,
szIniFileName);
if (nNew)
{
pConfigInfo->WAIT4STR_TIMEOUT = nNew * 1000;
TRACE((INFO_MESSAGE, "New timeout: %d seconds\n", nNew));
}
// nNew = _WrpGetPrivateProfileIntW(
nNew = GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"contimeout",
35,
szIniFileName);
if (nNew)
{
pConfigInfo->CONNECT_TIMEOUT = nNew * 1000;
TRACE((INFO_MESSAGE, "New timeout: %d seconds\n", nNew));
}
pConfigInfo->Autologon =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"Autologon",
0,
szIniFileName);
pConfigInfo->UseRegistry =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"UseRegistry",
1,
szIniFileName);
pConfigInfo->LoginWait =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"LoginWait",
1,
szIniFileName);
pConfigInfo->bTranslateStrings =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"TranslateStrings",
0,
szIniFileName);
pConfigInfo->bUnicode =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"Unicode",
0,
szIniFileName);
pConfigInfo->KeyboardHook =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"KeyboardHook",
0,
szIniFileName);
pConfigInfo->ConnectionFlags = 0;
bFlag =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"LowSpeed",
0,
szIniFileName);
if (bFlag)
pConfigInfo->ConnectionFlags |=TSFLAG_COMPRESSION;
bFlag =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"PersistentCache",
0,
szIniFileName);
if (bFlag)
pConfigInfo->ConnectionFlags |=TSFLAG_BITMAPCACHE;
bFlag =
// _WrpGetPrivateProfileIntW(
GetPrivateProfileIntW(
TCLIENT_INI_SECTION,
L"FullScreen",
0,
szIniFileName);
if (bFlag)
pConfigInfo->ConnectionFlags |=TSFLAG_FULLSCREEN;
// read the strings
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"StartRun",
RUN_MENU,
pConfigInfo->strStartRun,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"StartLogoff",
START_LOGOFF,
pConfigInfo->strStartLogoff,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"StartRunAct",
RUN_ACT,
pConfigInfo->strStartRun_Act,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"RunBox",
RUN_BOX,
pConfigInfo->strRunBox,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"WinLogon",
WINLOGON_USERNAME,
pConfigInfo->strWinlogon,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"WinLogonAct",
WINLOGON_ACT,
pConfigInfo->strWinlogon_Act,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"PriorWinLogon",
PRIOR_WINLOGON,
pConfigInfo->strPriorWinlogon,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"PriorWinLogonAct",
PRIOR_WINLOGON_ACT,
pConfigInfo->strPriorWinlogon_Act,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"NoSmartcard",
NO_SMARTCARD_UI,
pConfigInfo->strNoSmartcard,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"Smartcard",
SMARTCARD_UI,
pConfigInfo->strSmartcard,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"SmartcardAct",
SMARTCARD_UI_ACT,
pConfigInfo->strSmartcard_Act,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"LoginString",
L"",
pConfigInfo->strLogonFmt,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"NTSecurity",
WINDOWS_NT_SECURITY,
pConfigInfo->strNTSecurity,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"NTSecurityAct",
WINDOWS_NT_SECURITY_ACT,
pConfigInfo->strNTSecurity_Act,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"SureLogoff",
ARE_YOU_SURE,
pConfigInfo->strSureLogoff,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"SureLogoffAct",
SURE_LOGOFF_ACT,
pConfigInfo->strSureLogoffAct,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"LogonErrorMessage",
LOGON_ERROR_MESSAGE,
pConfigInfo->strLogonErrorMessage,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"LogonDisabled",
LOGON_DISABLED_MESSAGE,
pConfigInfo->strLogonDisabled,
MAX_STRING_LENGTH,
szIniFileName);
_snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ) , L"%S", CLIENT_CAPTION);
szBuffDef[MAX_STRING_LENGTH - 1] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"UIClientCaption",
szBuffDef,
pConfigInfo->strClientCaption,
MAX_STRING_LENGTH,
szIniFileName);
_snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", DISCONNECT_DIALOG_BOX);
szBuffDef[MAX_STRING_LENGTH - 1] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"UIDisconnectDialogBox",
szBuffDef,
pConfigInfo->strDisconnectDialogBox,
MAX_STRING_LENGTH,
szIniFileName);
_snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", YES_NO_SHUTDOWN);
szBuffDef[MAX_STRING_LENGTH - 1] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"UIYesNoDisconnect",
szBuffDef,
pConfigInfo->strYesNoShutdown,
MAX_STRING_LENGTH,
szIniFileName);
_snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%S", CLIENT_EXE);
szBuffDef[MAX_STRING_LENGTH - 1] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"ClientImage",
szBuffDef,
pConfigInfo->strClientImg,
MAX_STRING_LENGTH,
szIniFileName);
szBuffDef[0] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"ClientDebugger",
szBuffDef,
pConfigInfo->strDebugger,
MAX_STRING_LENGTH,
szIniFileName);
_snwprintf(szBuffDef, sizeof(szBuffDef) / sizeof( WCHAR ), L"%s", NAME_MAINCLASS);
szBuffDef[MAX_STRING_LENGTH - 1] = 0;
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"UIMainWindowClass",
szBuffDef,
pConfigInfo->strMainWindowClass,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"ClientCmdLine",
L"",
pConfigInfo->strCmdLineFmt,
4 * MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"ConsoleExtension",
L"",
pConfigInfo->strConsoleExtension,
MAX_STRING_LENGTH,
szIniFileName);
// _WrpGetPrivateProfileStringW(
GetPrivateProfileStringW(
TCLIENT_INI_SECTION,
L"sessionlist",
L"",
pConfigInfo->strSessionListDlg,
MAX_STRING_LENGTH,
szIniFileName);
}
/*++
* Function:
* DllCanUnloadNow
*
* Description:
* Used to determine whether the DLL can be unloaded by OLE
* Arguments:
* None.
* Return value:
* ...
*
--*/
STDAPI
DllCanUnloadNow(
VOID
)
{
return _Module.GetLockCount() == 0 ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
/*++
* Function:
* DllGetClassObject
*
* Description:
* Returns a class factory to create an object of the requested type.
* Arguments:
* rclsid - ...
* riid - ...
* ppv - ...
* Return value:
* ...
*
--*/
STDAPI
DllGetClassObject(
IN REFCLSID rclsid,
IN REFIID riid,
OUT LPVOID* ppv
)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
/*++
* Function:
* DllRegisterServer
*
* Description:
* DllRegisterServer - Adds entries to the system registry
* Arguments:
* None.
* Return value:
* ...
*
--*/
STDAPI
DllRegisterServer(
VOID
)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/*++
* Function:
* DllUnregisterServer
*
* Description:
* DllUnregisterServer - Removes entries from the system registry
* Arguments:
* None.
* Return value:
* ...
*
--*/
STDAPI
DllUnregisterServer(
VOID
)
{
_Module.UnregisterServer();
return S_OK;
}
} // extern "C"
#ifdef _M_IA64
//$WIN64: Don't know why _WndProcThunkProc isn't defined
extern "C" LRESULT CALLBACK _WndProcThunkProc(HWND, UINT, WPARAM, LPARAM)
{
return 0;
}
#endif