Windows2003-3790/termsrv/newclient/clshell/tscapp.cpp
2020-09-30 16:53:55 +02:00

553 lines
15 KiB
C++

//
// tscapp.cpp
//
// Implementation of CTscApp
// Ts Client Shell app logic
//
// Copyright(C) Microsoft Corporation 2000
// Author: Nadim Abdo (nadima)
//
//
#include "stdafx.h"
#define TRC_GROUP TRC_GROUP_UI
#define TRC_FILE "tscapp.cpp"
#include <atrcapi.h>
#include "tscapp.h"
#include "tscsetting.h"
#include "rdpfstore.h"
#include "rmigrate.h"
#include "sh.h"
CTscApp::CTscApp()
{
DC_BEGIN_FN("CTscApp");
_pWnd = NULL;
_pShellUtil = NULL;
_pTscSet = NULL;
_fAutoSaveSettings = FALSE;
DC_END_FN();
}
CTscApp::~CTscApp()
{
DC_BEGIN_FN("~CTscApp");
delete _pWnd;
delete _pShellUtil;
delete _pTscSet;
DC_END_FN();
}
//
// StartShell called to startup the app
//
//
BOOL CTscApp::StartShell(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpszCmdLine)
{
DWORD dwErr;
DC_BEGIN_FN("StartShell");
_hInst = hInstance;
TRC_ASSERT(!_pWnd,
(TB,_T("Calling StartShell while container wnd is up")));
//
// Create the container window
//
_pShellUtil = new CSH();
if(_pShellUtil)
{
if(!_pShellUtil->SH_Init( hInstance))
{
TRC_ERR((TB,_T("SH_Init failed")));
return FALSE;
}
dwErr = _pShellUtil->SH_ParseCmdParam( lpszCmdLine);
if (SH_PARSECMD_OK != dwErr) {
TRC_ERR((TB,_T("SH_ParseCmdParam failed on: %s code: 0x%x"),lpszCmdLine, dwErr));
//
// Invalid connection file specified
//
if (SH_PARSECMD_ERR_INVALID_CONNECTION_PARAM == dwErr) {
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_INVALID_CONNECTION_FILE,
_pShellUtil->GetRegSession()
);
}
//
// Parse failure is fatal
//
return FALSE;
}
#ifndef OS_WINCE
if(_pShellUtil->SH_GetCmdMigrate())
{
//Only do a migrate and then quit
CTscRegMigrate mig;
TCHAR szPath[MAX_PATH];
if(_pShellUtil->SH_GetRemoteDesktopFolderPath(szPath,
SIZECHAR(szPath)))
{
if(!mig.MigrateAll(szPath))
{
TRC_ERR((TB,_T("MigrateAll failed to dir:%s"),szPath));
}
//Want to quit the app
return FALSE;
}
else
{
TRC_ERR((TB,_T("SH_GetRemoteDesktopFolderPath failed")));
return FALSE;
}
}
#endif
if(!InitSettings(hInstance))
{
TRC_ERR((TB,_T("InitSettings returned FALSE")));
return FALSE;
}
_pWnd = new CContainerWnd();
if(_pWnd)
{
if (_pWnd->Init( hInstance, _pTscSet, _pShellUtil))
{
return TRUE;
}
else
{
TRC_ERR((TB,_T("Error: pWnd->Init returned FALSE. Exiting\n")));
return FALSE;
}
}
else
{
TRC_ERR((TB,_T("Could not new CContainerWnd")));
return FALSE;
}
}
else
{
TRC_ERR((TB,_T("Could not new CSH")));
return FALSE;
}
DC_END_FN();
}
HWND CTscApp::GetTscDialogHandle()
{
DC_BEGIN_FN("GetTscDialogHandle");
HWND hwndDlg = NULL;
if(_pWnd)
{
hwndDlg = _pWnd->GetConnectDialogHandle();
}
DC_END_FN();
return hwndDlg;
}
//
// Setup the settings structures
// Based on command line options
//
// This involves figuring out where to load settings from
// and then doing it. E.g
// Load from file
// Load from registry
// Load from internal defaults
//
BOOL CTscApp::InitSettings(HINSTANCE hInstance)
{
CRdpFileStore rdpf;
LPTSTR szFileName = NULL;
TCHAR szDefaultFile[MAX_PATH];
BOOL fLoadedSettings = FALSE;
DC_BEGIN_FN("InitSettings");
_pTscSet = new CTscSettings();
if(!_pTscSet)
{
TRC_ERR((TB,_T("Could not new CTscSettings")));
return FALSE;
}
if(_pShellUtil->SH_GetCmdFileForEdit() ||
_pShellUtil->SH_GetCmdFileForConnect())
{
szFileName = _pShellUtil->SH_GetCmdLnFileName();
if(!_pShellUtil->SH_FileExists(szFileName))
{
TCHAR errFileNotFound[MAX_PATH];
TCHAR szAppName[MAX_PATH];
if(LoadString(hInstance,
UI_IDS_APP_NAME,
szAppName,
SIZECHAR(szAppName)))
{
if (LoadString(hInstance,
UI_IDS_ERR_FILEDOESNOTEXIST,
errFileNotFound,
SIZECHAR(errFileNotFound)) != 0)
{
TCHAR errFormatedFileNotFound[MAX_PATH*3];
_stprintf(errFormatedFileNotFound, errFileNotFound,
szFileName);
MessageBox(NULL, errFormatedFileNotFound, szAppName,
MB_ICONERROR | MB_OK);
return FALSE;
}
}
return FALSE;
}
}
else if(_pShellUtil->GetRegSessionSpecified())
{
// Automigrate the specified registry
// session directly to an in-memory settings store
_fAutoSaveSettings = FALSE;
rdpf.SetToNullStore();
CTscRegMigrate mig;
TRC_NRM((TB,_T("Automigrating session %s"),
_pShellUtil->GetRegSession()));
if(mig.MigrateSession( _pShellUtil->GetRegSession(),
&rdpf))
{
TRC_NRM((TB,_T("Success automigrating reg setting")));
HRESULT hr = _pTscSet->LoadFromStore(&rdpf);
if(FAILED(hr))
{
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_INITDEFAULT,
szFileName);
return FALSE;
}
_pShellUtil->SetAutoConnect( TRUE );
fLoadedSettings = TRUE;
}
else
{
//Something bad happened
//could not automigrate..indicate failure
//and use NULL store
fLoadedSettings = FALSE;
}
}
else
{
//No files specified or registry sessions specified
//Try to use the default.rdp file (create if necessary)
if(!_pShellUtil->SH_GetPathToDefaultFile(
szDefaultFile,
SIZECHAR(szDefaultFile)))
{
TRC_ERR((TB,_T("SH_GetPathToDefaultFile failed")));
//
// Display error message to user
//
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_GETPATH_TO_DEFAULT_FILE);
return FALSE;
}
szFileName = szDefaultFile;
if(!_pShellUtil->SH_FileExists(szFileName))
{
//
// File doesn't exist so create the Remote Desktops
// directory to ensure the file can be created
//
if(!CreateRDdir())
{
TRC_ERR((TB,_T("Couldn't create RD dir. Not using %s"),
szFileName));
szFileName = NULL;
}
//
// Now create a hidden default file
//
if (szFileName)
{
if (!CSH::SH_CreateHiddenFile(szFileName))
{
TRC_ERR((TB,_T("Unable to create and hide file %s"),
szFileName));
szFileName = NULL;
}
}
}
//
// Auto Save on exit if we're using the default
// connection file (Default.rdp)
//
_fAutoSaveSettings = szFileName ? TRUE : FALSE;
}
if(szFileName)
{
//
//We're loading the settings from a file
//this is the common case.
//
if(rdpf.OpenStore(szFileName))
{
HRESULT hr = _pTscSet->LoadFromStore(&rdpf);
if(SUCCEEDED(hr))
{
fLoadedSettings = TRUE;
}
else
{
TRC_ERR((TB,_T("LoadFromStore failed")));
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_LOAD,
szFileName);
// We can load NULL file even if you can't load the file
}
rdpf.CloseStore();
}
else
{
TRC_ERR((TB,_T("OpenStore (%s) failed"),szFileName));
_pShellUtil->SH_DisplayErrorBox(NULL,UI_IDS_ERR_OPEN_FILE,
szFileName);
// We can load NULL file even if you can't open the file
}
}
if(!fLoadedSettings)
{
TRC_ERR((TB,_T("Couldn't load settings, using NULL STORE")));
//Some bad thing happened and we can't get a file to load
//from (not even the default file). So load from an empty
//store, this will initialize everything to defaults
if(rdpf.SetToNullStore())
{
HRESULT hr = _pTscSet->LoadFromStore(&rdpf);
if(FAILED(hr))
{
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_INITDEFAULT,
szFileName);
return FALSE;
}
}
else
{
TRC_ERR((TB,_T("SetToNullStore Failed")));
return FALSE;
}
}
//Keep track of the filename
if(szFileName)
{
_pTscSet->SetFileName(szFileName);
}
//
// Override loaded settings with cmd line settings
//
_pShellUtil->SH_ApplyCmdLineSettings(_pTscSet, NULL);
DC_END_FN();
return TRUE;
}
BOOL CTscApp::EndShell()
{
DC_BEGIN_FN("EndShell");
BOOL fRet = FALSE;
if(!_pTscSet || !_pShellUtil)
{
return FALSE;
}
#ifndef OS_WINCE
_pShellUtil->SH_Cleanup();
#endif
//
// Only autosave if
// the last connection was successful
//
if(_fAutoSaveSettings &&
_pWnd &&
_pWnd->GetConnectionSuccessFlag())
{
//
// AutoSave the tscsettings
// (only if the current file is still Default.rdp)
//
TCHAR szDefaultFile[MAX_PATH];
if(!_pShellUtil->SH_GetPathToDefaultFile(
szDefaultFile,
SIZECHAR(szDefaultFile)))
{
TRC_ERR((TB,_T("SH_GetPathToDefaultFile failed")));
return FALSE;
}
if(!_tcscmp(szDefaultFile, _pTscSet->GetFileName()))
{
CRdpFileStore rdpf;
if(rdpf.OpenStore(szDefaultFile))
{
HRESULT hr = E_FAIL;
hr = _pTscSet->SaveToStore(&rdpf);
if(SUCCEEDED(hr))
{
if(rdpf.CommitStore())
{
//Save last filename
_pTscSet->SetFileName(szDefaultFile);
fRet = TRUE;
}
else
{
TRC_ERR((TB,_T("Unable to CommitStore settings")));
}
}
else
{
TRC_ERR((TB,_T("Unable to save settings to store %d, %s"),
hr, szDefaultFile));
}
rdpf.CloseStore();
if(!fRet)
{
_pShellUtil->SH_DisplayErrorBox(NULL,
UI_IDS_ERR_SAVE,
szDefaultFile);
}
return fRet;
}
else
{
TRC_ERR((TB,_T("Unable to OpenStore for save %s"), szDefaultFile));
_pShellUtil->SH_DisplayErrorBox(NULL,UI_IDS_ERR_OPEN_FILE,
szDefaultFile);
return FALSE;
}
}
else
{
//Not a failure, but nothing to do
TRC_NRM((TB,_T("Current file is no longer default, don't autosave")));
return TRUE;
}
}
else
{
return TRUE;
}
DC_END_FN();
}
//
// Creates the Remote Desktops dir (if needed)
// pops UI on failure
//
// Returns:
// TRUE on success
//
//
BOOL CTscApp::CreateRDdir()
{
DC_BEGIN_FN("CreateRDdir");
//
// Make sure the directory exists so that the file
// can be created by the OpenStore
//
TCHAR szDir[MAX_PATH];
if(_pShellUtil->SH_GetRemoteDesktopFolderPath(szDir,
SIZECHAR(szDir)))
{
if(_pShellUtil->SH_CreateDirectory(szDir))
{
return TRUE;
}
else
{
TRC_ERR((TB,_T("SH_CreateDirectory failed %s:%d"),
szDir, GetLastError()));
//
// Display error message to user
//
#ifndef OS_WINCE
TCHAR szMyDocsFolderName[MAX_PATH];
if(_pShellUtil->SH_GetMyDocumentsDisplayName(
szMyDocsFolderName,
SIZECHAR(szMyDocsFolderName)))
{
TCHAR errCantCreateRDFolder[MAX_PATH];
TCHAR szAppName[MAX_PATH];
if(LoadString(_hInst,
UI_IDS_APP_NAME,
szAppName,
SIZECHAR(szAppName)))
{
if (LoadString(_hInst,
UI_IDS_ERR_CREATE_REMDESKS_FOLDER,
errCantCreateRDFolder,
SIZECHAR(errCantCreateRDFolder)))
{
TCHAR errFmtCantCreateRDFolder[MAX_PATH*3];
_stprintf(errFmtCantCreateRDFolder,
errCantCreateRDFolder,
szMyDocsFolderName,
szDir);
MessageBox(NULL, errFmtCantCreateRDFolder,
szAppName,
MB_ICONERROR | MB_OK);
}
}
}
#endif
//
// This is an error but we'll handle it anyway
// by loading defaults from a null store
//
return FALSE;
}
}
else
{
//Guess we can't load from a file after all
return FALSE;
}
DC_END_FN();
}