// // 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 #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(); }