// // Copyright (C) 2000 Microsoft Corporation. All Rights Reserved. // // // //==============================================================; #include "RemotePage.h" #include #include #include #include #include "resource.h" #include #include "RAssistance.h" #include "RAssistance_i.c" #include #include "cfgbkend.h" #include "cfgbkend_i.c" extern ULONG g_uObjects; IRASettingProperty* g_praSetting = NULL; // Used for Remote assistance setting #define NO_HELP ((DWORD) -1) // Disables Help for a control //Table of help IDs for each control DWORD aHelpIds[] = { IDC_REMOTE_ENABLE, HIDC_REMOTE_ENABLE, IDC_REMOTE_USR_LIST, HIDC_REMOTE_USR_LIST, IDC_REMOTE_USR_ADD, HIDC_REMOTE_USR_ADD, IDC_REMOTE_USR_REMOVE, HIDC_REMOTE_USR_REMOVE, IDC_REMOTE_ASSISTANCE_ADVANCED, HIDC_RA_ADVANCED, IDC_ENABLERA, HIDC_RA_ENABLE, IDC_REMOTE_UPLINK, NO_HELP, IDC_REMOTE_GPLINK_APPSERVER, NO_HELP, IDC_REMOTE_SCLINK_APPSERVER, NO_HELP, IDC_OFFLINE_FILES, NO_HELP, IDC_REMOTE_COMPNAME, NO_HELP, IDC_REMOTE_HELP, NO_HELP, IDC_REMOTE_SELECT_USERS, NO_HELP, IDC_DEFAULT1, NO_HELP, IDC_DEFAULT2, NO_HELP, IDC_DEFAULT3, NO_HELP, IDC_DEFAULT4, NO_HELP, IDC_DEFAULT5, NO_HELP, 0, 0 }; //************************************************************* // // CRemotePage::CRemotePage() // // Purpose: Initializes data members of the object // // Parameters: HINSTANCE hinst // // Return: NONE // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* CRemotePage::CRemotePage( IN HINSTANCE hinst) : m_RemoteUsersDialog(hinst) { m_cref = 1; // m_bProfessional = FALSE; m_dwPageType = PAGE_TYPE_UNKNOWN; m_hInst = hinst; m_bDisableChkBox = FALSE; m_bDisableButtons = FALSE; m_bShowAccessDeniedWarning = FALSE; m_dwInitialState = 0; m_hDlg = NULL; m_TemplateId = 0; g_uObjects++; } //************************************************************* // // CRemotePage::~CRemotePage() // // Purpose: decreases the object counter // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* CRemotePage::~CRemotePage() { g_uObjects--; } /////////////////////////////// // Interface IUnknown /////////////////////////////// STDMETHODIMP CRemotePage::QueryInterface( IN REFIID riid, OUT LPVOID *ppv) { if (!ppv) return E_FAIL; *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown)) *ppv = static_cast(this); else if (IsEqualIID(riid, IID_IShellExtInit)) *ppv = static_cast(this); else if (IsEqualIID(riid, IID_IShellPropSheetExt)) *ppv = static_cast(this); if (*ppv) { AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CRemotePage::AddRef() { return ++m_cref; } STDMETHODIMP_(ULONG) CRemotePage::Release() { m_cref--; if (!m_cref) { delete this; return 0; } return m_cref; } /////////////////////////////// // Interface IShellExtInit /////////////////////////////// STDMETHODIMP CRemotePage::Initialize( IN LPCITEMIDLIST pidlFolder, IN LPDATAOBJECT lpdobj, IN HKEY hkeyProgID ) { return S_OK; } /////////////////////////////// // Interface IShellPropSheetExt /////////////////////////////// //************************************************************* // // AddPages() // // Purpose: Adds "Remote" tab to a property sheet // // Parameters: lpfnAddPage - function to call to add a page // lParam - Parameter to pass to the function specified by the lpfnAddPage // // Return: TRUE if message was processed // FALSE if not // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* STDMETHODIMP CRemotePage::AddPages( IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam ) { if(CanShowRemotePage()) { PROPSHEETPAGE psp; psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = 0; psp.hInstance = m_hInst; psp.pszTemplate = MAKEINTRESOURCE(m_TemplateId); psp.pfnDlgProc = RemoteDlgProc; psp.pszTitle = NULL; psp.lParam = (LPARAM)this; HPROPSHEETPAGE hPage = CreatePropertySheetPage(&psp); if(hPage && lpfnAddPage(hPage,lParam)) { return S_OK; } } return E_FAIL; } STDMETHODIMP CRemotePage::ReplacePage( IN UINT uPageID, IN LPFNADDPROPSHEETPAGE lpfnReplacePage, IN LPARAM lParam ) { return E_FAIL; } //************************************************************* // // RemoteDlgProc() // // Purpose: Dialog box procedure for Remote tab // // Parameters: hDlg - handle to the dialog box // uMsg - window message // wParam - wParam // lParam - lParam // // Return: TRUE if message was processed // FALSE if not // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* INT_PTR APIENTRY RemoteDlgProc ( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CRemotePage *pPage = (CRemotePage *) GetWindowLongPtr(hDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { PROPSHEETPAGE *ppsp=(PROPSHEETPAGE *)lParam; pPage = (CRemotePage *)ppsp->lParam; SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)pPage); if(pPage) { pPage->AddRef(); pPage->OnInitDialog(hDlg); } } break; case WM_NOTIFY: switch (((NMHDR FAR*)lParam)->code) { case NM_CLICK: case NM_RETURN: // Is for RA's help? if (wParam == IDC_REMOTERA_HELP) { #if 1 #define HELP_PATH TEXT("\\PCHEALTH\\HelpCtr\\Binaries\\HelpCtr.exe -FromStartHelp -Mode \"hcp://CN=Microsoft Corporation,L=Redmond,S=Washington,C=US/Remote Assistance/RAIMLayout.xml\" -Url \"hcp://CN=Microsoft Corporation,L=Redmond,S=Washington,C=US/Remote%20Assistance/Common/RCMoreInfo.htm\"") TCHAR szCommandLine[2000]; PROCESS_INFORMATION ProcessInfo; STARTUPINFO StartUpInfo; TCHAR szWinDir[2048]; GetWindowsDirectory(szWinDir, 2048); ZeroMemory((LPVOID)&StartUpInfo, sizeof(STARTUPINFO)); StartUpInfo.cb = sizeof(STARTUPINFO); wsprintf(szCommandLine, TEXT("%s%s"), szWinDir,HELP_PATH); CreateProcess(NULL, szCommandLine,NULL,NULL,TRUE,CREATE_NEW_PROCESS_GROUP,NULL,&szWinDir[0],&StartUpInfo,&ProcessInfo); #else HtmlHelp(NULL, TEXT("rassist.chm"), HH_HELP_FINDER, 0); #endif } else if(pPage) { pPage->OnLink(wParam); } break; case PSN_APPLY: if(pPage) { if(pPage->OnApply()) { SetWindowLongPtr(hDlg,DWLP_MSGRESULT,PSNRET_NOERROR); } else { SetWindowLongPtr(hDlg,DWLP_MSGRESULT,PSNRET_INVALID); } } return TRUE; case PSN_SETACTIVE: if(pPage) { pPage->OnSetActive(); } return TRUE; default: return FALSE; } break; case WM_COMMAND: { switch(LOWORD(wParam)) { case IDC_REMOTE_ENABLE: if(pPage && pPage->OnRemoteEnable()) { pPage->RemoteEnableWarning(); PropSheet_Changed(GetParent(hDlg), hDlg); } break; case IDC_REMOTE_SELECT_USERS: if(pPage) { pPage->OnRemoteSelectUsers(); } break; // Remote Assistance Dialog button. case IDC_REMOTE_ASSISTANCE_ADVANCED: { BOOL bIsChanged = FALSE; if (!g_praSetting) { CoCreateInstance(CLSID_RASettingProperty, NULL, CLSCTX_INPROC_SERVER, IID_IRASettingProperty, reinterpret_cast(&g_praSetting)); // Need to init it at the first time. if (g_praSetting) { g_praSetting->Init(); } else { // Not enough memory, too bad. return TRUE; } } g_praSetting->ShowDialogBox(hDlg); if (SUCCEEDED(g_praSetting->get_IsChanged(&bIsChanged)) && bIsChanged) { PropSheet_Changed(GetParent(hDlg), hDlg); } } break; case IDC_ENABLERA: { PropSheet_Changed(GetParent(hDlg), hDlg); EnableWindow(GetDlgItem(hDlg,IDC_REMOTE_ASSISTANCE_ADVANCED), IsDlgButtonChecked(hDlg, IDC_ENABLERA)); } break; default: break; } } return FALSE; case WM_DESTROY: if(pPage) { pPage->Release(); } if (g_praSetting) { g_praSetting->Release(); g_praSetting = NULL; } return FALSE; //If an application processes this message, it should return zero. case WM_HELP: { LPHELPINFO phi=(LPHELPINFO)lParam; if(phi && phi->dwContextId) { WinHelp(hDlg,TEXT("SYSDM.HLP"),HELP_CONTEXTPOPUP,phi->dwContextId); } } break; case WM_CONTEXTMENU: // right mouse click WinHelp((HWND) wParam, TEXT("SYSDM.HLP"), HELP_CONTEXTMENU, (DWORD_PTR)aHelpIds); break; default: return FALSE; } return TRUE; } //************************************************************* // // CRemotePage::CanShowRemotePage() // // Purpose: Checks Windows version; // searches for "FDenyTSConnections" value first // in HKLM\\Software\\Policies\\Microsoft\\Windows NT\\Terminal Services // if not found than in // SYSTEM\\CurrentControlSet\\Control\\Terminal Server; // creates "Remote Desktop Users" SID, // gets "Remote Desktop Users" group name from the SID // // Parameters: hInst - hInstance // dwPageType - can be PAGE_TYPE_PTS or PAGE_TYPE_APPSERVER // // Return: TRUE if can show remote page // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* BOOL CRemotePage::CanShowRemotePage() { BOOL fCreatePage = FALSE; //Check Windows version OSVERSIONINFOEX ov; ov.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if(!GetVersionEx((LPOSVERSIONINFO)&ov)) { return FALSE; } if(ov.wProductType == VER_NT_WORKSTATION && (ov.wSuiteMask & VER_SUITE_SINGLEUSERTS )) { fCreatePage = TRUE; if(ov.wSuiteMask & VER_SUITE_PERSONAL) { #ifdef _WIN64 // No Remote Assistance on IA64 fCreatePage = FALSE; #else m_dwPageType = PAGE_TYPE_PERSONAL; m_TemplateId = IDD_REMOTE_PERSONAL; #endif } else { m_bProfessional = TRUE; m_dwPageType = PAGE_TYPE_PTS; m_TemplateId = IDD_REMOTE_PTS; } } else { if((ov.wProductType == VER_NT_DOMAIN_CONTROLLER || ov.wProductType == VER_NT_SERVER) && (ov.wSuiteMask & VER_SUITE_TERMINAL) && TestUserForAdmin()) { fCreatePage = TRUE; if(ov.wSuiteMask & VER_SUITE_SINGLEUSERTS) { m_dwPageType = PAGE_TYPE_PTS; m_TemplateId = IDD_REMOTE_PTS; } else { m_dwPageType = PAGE_TYPE_APPSERVER; m_TemplateId = IDD_REMOTE_APPSERVER; } } } if( !fCreatePage) { return FALSE; } DWORD dwType; DWORD cbDisable; LONG Err; HKEY hKey; Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Policies\\Microsoft\\Windows NT\\Terminal Services"), 0, KEY_QUERY_VALUE, &hKey); if(Err == ERROR_SUCCESS) { cbDisable = sizeof(DWORD); Err = RegQueryValueEx(hKey, TEXT("fDenyTSConnections"), NULL, &dwType, (LPBYTE)&m_dwInitialState, &cbDisable); if(Err == ERROR_SUCCESS) { m_bDisableChkBox = TRUE; if(m_dwInitialState != 0) { m_bDisableButtons = TRUE; } } RegCloseKey(hKey); } if(Err != ERROR_SUCCESS) { if(Err != ERROR_FILE_NOT_FOUND) { return FALSE; } Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), 0, KEY_QUERY_VALUE, &hKey); if(Err == ERROR_SUCCESS) { cbDisable = sizeof(DWORD); Err = RegQueryValueEx(hKey, TEXT("fDenyTSConnections"), NULL, &dwType, (LPBYTE)&m_dwInitialState, &cbDisable); RegCloseKey(hKey); } if(Err != ERROR_SUCCESS && Err != ERROR_FILE_NOT_FOUND ) { return FALSE; } } //Check permissions //on the registry if( !m_bDisableChkBox ) { Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), 0, KEY_SET_VALUE, &hKey); if( Err == ERROR_SUCCESS ) { RegCloseKey(hKey); } else { if( Err == ERROR_ACCESS_DENIED ) { m_bDisableChkBox = TRUE; m_bShowAccessDeniedWarning = TRUE; } } } if(m_dwPageType == PAGE_TYPE_PTS) { if(!m_bDisableButtons) { if(!m_RemoteUsersDialog.CanShowDialog(&m_bDisableButtons)) { return FALSE; } if(m_bDisableButtons) { m_bShowAccessDeniedWarning = TRUE; } } } return TRUE; } //************************************************************* // // CRemotePage::OnInitDialog() // // Purpose: initializes check box state // creates list of "Remote Desktop Users" members // // Parameters: hDlg - the page handle // // Return: NONE // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* void CRemotePage::OnInitDialog( IN HWND hDlg) { m_hDlg = hDlg; /* Get Remote Assistance button value */ BOOL bRAEnable = FALSE; int iErr; HKEY hKey = NULL; IRARegSetting* pRA = NULL; CoCreateInstance(CLSID_RARegSetting, NULL, CLSCTX_INPROC_SERVER, IID_IRARegSetting, reinterpret_cast(&pRA)); if (pRA) { pRA->get_AllowGetHelpCPL(&bRAEnable); pRA->Release(); } CheckDlgButton(m_hDlg, IDC_ENABLERA, bRAEnable?BST_CHECKED:BST_UNCHECKED); // check if users have permission to change this setting. iErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Terminal Server"), 0, KEY_SET_VALUE, &hKey); if (iErr == ERROR_SUCCESS) { RegCloseKey(hKey); } else if (iErr == ERROR_ACCESS_DENIED) { bRAEnable = FALSE; EnableWindow(GetDlgItem(m_hDlg,IDC_ENABLERA), FALSE); } EnableWindow(GetDlgItem(m_hDlg,IDC_REMOTE_ASSISTANCE_ADVANCED), bRAEnable); /***** RA done *******/ if(m_bDisableChkBox) { EnableWindow(GetDlgItem(m_hDlg,IDC_REMOTE_ENABLE),FALSE); } CheckDlgButton(m_hDlg,IDC_REMOTE_ENABLE,m_dwInitialState?BST_UNCHECKED:BST_CHECKED); if(m_dwPageType == PAGE_TYPE_PTS) { if(m_bDisableButtons) { EnableWindow(GetDlgItem(m_hDlg,IDC_REMOTE_SELECT_USERS),FALSE); } //Get computer name LPTSTR szCompName = (LPTSTR)LocalAlloc (LPTR, (MAX_PATH+1) * sizeof(TCHAR) ); DWORD dwNameSize = MAX_PATH; if(szCompName) { BOOL bResult = GetComputerNameEx( ComputerNameDnsFullyQualified, szCompName, &dwNameSize ); if(!bResult && GetLastError() == ERROR_MORE_DATA) { LocalFree(szCompName); szCompName = (LPTSTR) LocalAlloc (LPTR, (dwNameSize+1) * sizeof(TCHAR) ); if ( szCompName ) { bResult = GetComputerNameEx( ComputerNameDnsFullyQualified, szCompName, &dwNameSize ); } } if(bResult) { SetDlgItemText(hDlg,IDC_REMOTE_COMPNAME,szCompName); } if(szCompName) { LocalFree(szCompName); } } } } //************************************************************* // // CRemotePage::OnSetActive() // // Purpose: When the page gets active and user does not have // permissions to change some settings it shows // a warning message. // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* void CRemotePage::OnSetActive() { TCHAR szMsg[MAX_PATH+1]; TCHAR szTitle[MAX_PATH+1]; if( m_bShowAccessDeniedWarning ) { if(LoadString(m_hInst,IDS_REMOTE_SESSIONS,szTitle,MAX_PATH) && LoadString(m_hInst,IDS_WRN_NO_PERMISSIONS,szMsg,MAX_PATH)) { MessageBox(m_hDlg,szMsg,szTitle,MB_OK|MB_ICONINFORMATION); } m_bShowAccessDeniedWarning = FALSE; } } //************************************************************* // // CRemotePage::OnApply() // // Purpose: saves settings in the Registry // saves "Remote Desktop Users" membership changes // // Parameters: NONE // // Return: TRUE - if changes can be applied // FALSE - otherwise. // // Comments: in case of error shows message box // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* BOOL CRemotePage::OnApply() { CWaitCursor wait; CMutex mutex; DWORD dwType = REG_DWORD; DWORD dwDisable = 0; DWORD cbDisable = sizeof(DWORD); LONG Err; // Update RA setting first IRARegSetting* pRA = NULL; CoCreateInstance(CLSID_RARegSetting, NULL, CLSCTX_INPROC_SERVER, IID_IRARegSetting, reinterpret_cast(&pRA)); if (pRA) { pRA->put_AllowGetHelp(IsDlgButtonChecked(m_hDlg, IDC_ENABLERA)==BST_CHECKED); pRA->Release(); } BOOL bIsChanged = FALSE; if (g_praSetting && SUCCEEDED(g_praSetting->get_IsChanged(&bIsChanged)) && bIsChanged) { g_praSetting->SetRegSetting(); } // RA done. if(!OnRemoteEnable()) { return FALSE; } if(IsWindowEnabled(GetDlgItem(m_hDlg,IDC_REMOTE_ENABLE))) { if(IsDlgButtonChecked(m_hDlg,IDC_REMOTE_ENABLE) == BST_UNCHECKED) { dwDisable = 1; } if(dwDisable != m_dwInitialState) { HRESULT hr; hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); if (SUCCEEDED(hr)) { ILocalMachine *pLocalMachine; hr = CoCreateInstance(CLSID_ShellLocalMachine, NULL, CLSCTX_INPROC_SERVER, IID_ILocalMachine, reinterpret_cast(&pLocalMachine)); if (SUCCEEDED(hr) && (pLocalMachine != NULL)) { hr = pLocalMachine->put_isRemoteConnectionsEnabled(dwDisable == 0); pLocalMachine->Release(); } CoUninitialize(); } Err = HRESULT_CODE(hr); if (ERROR_SUCCESS == Err) { m_dwInitialState = dwDisable; } else { if (ERROR_NOT_SUPPORTED == Err) { TCHAR szContent[256], szTitle[256]; (int)LoadString(m_hInst, IDS_OTHER_USERS, szContent, sizeof(szContent) / sizeof(szContent[0])); (int)LoadString(m_hInst, IDS_REMOTE_SESSIONS, szTitle, sizeof(szTitle) / sizeof(szTitle[0])); MessageBox(m_hDlg, szContent, szTitle, MB_OK | MB_ICONSTOP); } else { DisplayError(m_hInst, m_hDlg, Err, IDS_ERR_SAVE_REGISTRY, IDS_REMOTE_SESSIONS); } CheckDlgButton(m_hDlg, IDC_REMOTE_ENABLE, m_dwInitialState ? BST_UNCHECKED : BST_CHECKED); } } } return TRUE; } //************************************************************* // // CRemotePage::OnLink() // // Purpose: runs application which link points to. // // Parameters: WPARAM wParam - link ID // // Return: NONE // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* void CRemotePage::OnLink( WPARAM wParam) { switch(wParam) { case IDC_REMOTE_GPLINK_APPSERVER: ShellExecute(NULL,TEXT("open"),TEXT("gpedit.msc"),NULL,NULL,SW_SHOW); break; case IDC_REMOTE_SCLINK_APPSERVER: ShellExecute(NULL,TEXT("open"),TEXT("tscc.msc"),NULL,NULL,SW_SHOW); break; case IDC_REMOTE_UPLINK: ShellExecute(NULL,TEXT("open"),TEXT("control"),TEXT("userpasswords"),NULL,SW_SHOW); break; /* case IDC_REMOTE_HELP: HtmlHelp(NULL, TEXT("rdesktop.chm"), HH_HELP_FINDER, 0); break;*/ case IDC_REMOTE_HELP: if(m_bProfessional) { ShellExecute(NULL,TEXT("open"), TEXT("hcp://services/subsite?node=TopLevelBucket_2/Working_Remotely/") TEXT("Remote_Desktop&topic=MS-ITS:rdesktop.chm::/rdesktop_overview.htm"),NULL,NULL,SW_SHOW); } else { ShellExecute(NULL,TEXT("open"), TEXT("hcp://services/subsite?node=Management_and_Administration_Tools/") TEXT("Remote_Desktop_for_Administration&topic=MS-ITS:rdesktop.chm::/sag_rdesktop_topnode.htm"),NULL,NULL,SW_SHOW); } break; case IDC_REMOTE_HELP_APPSERVER: ShellExecute(NULL,TEXT("open"), TEXT("hcp://services/subsite?node=Management_and_Administration_Tools/") TEXT("Terminal_Server&topic=MS-ITS:termsrv.chm::/sag_termsrv_topnode.htm"),NULL,NULL,SW_SHOW); break; default: break; } } //************************************************************* // // CRemotePage::OnRemoteEnable() // // Purpose: If user tries to allow remote connections and // "Offline Files" is enabled it shows // "Disable Offline Files" dialog and unchecks // "Remote Connections" checkbox. // // Parameters: NONE // // Return: TRUE - if the check box state was changed. // FALSE - otherwise // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* typedef BOOL (WINAPI * PCHECKFN)(); BOOL CRemotePage::OnRemoteEnable() { //First check if multiple connections are allowed DWORD dwAllowMultipleTSSessions = 0; DWORD dwType; DWORD cbSize; LONG Err; HKEY hKey; BOOL bResult = TRUE; //Fast User Switching / Remote Connections and Offline Files should work together fine. //when Brian Aust makes his changes to offline files. //therefore we should not restrict remote connections in any case on Professional Machines. //on server machine however we conntinue to disallow remote connections if Offline files are on. if(m_bProfessional) { return TRUE; } //allow user to uncheck the checkbox if(IsDlgButtonChecked(m_hDlg,IDC_REMOTE_ENABLE) == BST_UNCHECKED ) { return TRUE; } //check if multiple sessions is allowed. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), 0, KEY_QUERY_VALUE, &hKey); if(Err == ERROR_SUCCESS) { cbSize = sizeof(DWORD); Err = RegQueryValueEx(hKey, TEXT("AllowMultipleTSSessions"), NULL, &dwType, (LPBYTE)&dwAllowMultipleTSSessions, &cbSize); if(Err == ERROR_SUCCESS && dwAllowMultipleTSSessions) { //multiple sessions is allowed. //check if CSC (Offline Files) is enabled HMODULE hLib = LoadLibrary(TEXT("cscdll.dll")); if(hLib) { PCHECKFN pfnCSCIsCSCEnabled = (PCHECKFN)GetProcAddress(hLib,"CSCIsCSCEnabled"); if(pfnCSCIsCSCEnabled && pfnCSCIsCSCEnabled()) { //Offline Files is enabled //uncheck the checkbox; show the dialog COfflineFilesDialog Dlg(m_hInst); CheckDlgButton(m_hDlg,IDC_REMOTE_ENABLE,BST_UNCHECKED); Dlg.DoDialog(m_hDlg); bResult = FALSE; } } FreeLibrary(hLib); } RegCloseKey(hKey); } return bResult; } //************************************************************* // // CRemotePage::OnRemoteSelectUsers() // // Purpose: Creates "Remote Desktop Users" dialog. // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* void CRemotePage::OnRemoteSelectUsers() { m_RemoteUsersDialog.DoDialog(m_hDlg); } //************************************************************* // // CRemotePage::RemoteEnableWarning() // // Purpose: Displays a message box about empty passwords // firewalls and other stuff that can prevent // remote sessions from working properly. // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 3/28/01 a-skuzin Created // //************************************************************* void CRemotePage::RemoteEnableWarning() { if(IsDlgButtonChecked(m_hDlg,IDC_REMOTE_ENABLE) == BST_CHECKED ) { // //Now warn admin about empty passwords. //Empty passwords are not allowed with //RemoteInteractive logon. // //Allocate a buffer for the string 1000 chars should be enough // TCHAR szTitle[MAX_PATH+1]; DWORD cMsg = 1000; LPTSTR szMsg = (LPTSTR) LocalAlloc(LPTR,(cMsg+1)*sizeof(TCHAR)); if(szMsg) { if(LoadString(m_hInst,IDS_WRN_EMPTY_PASSWORD,szMsg,cMsg) && LoadString(m_hInst,IDS_REMOTE_SESSIONS,szTitle,MAX_PATH)) { MessageBox(m_hDlg,szMsg,szTitle, MB_OK | MB_ICONINFORMATION); } LocalFree(szMsg); } } } //************************************************************* // // DisplayError() // // Purpose: shows message box with error description // // Parameters: ErrID - error code // MsgID - ID of the first part of error messsage in the string table // TitleID - ID of the title in the string table // Return: NONE // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* void DisplayError( IN HINSTANCE hInst, IN HWND hDlg, IN UINT ErrID, IN UINT MsgID, IN UINT TitleID, ...) { TCHAR szTemplate[MAX_PATH+1]; TCHAR szErr[MAX_PATH+1]; if(!LoadString(hInst,MsgID,szTemplate,MAX_PATH)) { return; } va_list arglist; va_start(arglist, TitleID); wvsprintf(szErr,szTemplate,arglist); va_end(arglist); TCHAR szTitle[MAX_PATH+1]; if(!LoadString(hInst,TitleID,szTitle,MAX_PATH)) { return; } LPTSTR szDescr; //load module with network error messages HMODULE hNetErrModule=LoadLibraryEx(TEXT("netmsg.dll"),NULL, LOAD_LIBRARY_AS_DATAFILE|DONT_RESOLVE_DLL_REFERENCES); DWORD dwFlags; if(hNetErrModule) { dwFlags=FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_FROM_HMODULE| FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_IGNORE_INSERTS; } else { dwFlags=FORMAT_MESSAGE_FROM_SYSTEM| FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_IGNORE_INSERTS; } if(FormatMessage(dwFlags, hNetErrModule, ErrID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&szDescr, 0, NULL)) { LPTSTR szErrMessage=(LPTSTR)LocalAlloc(LPTR, (lstrlen(szErr)+lstrlen(szDescr)+3)*sizeof(TCHAR)); if(szErrMessage) { wsprintf(szErrMessage,TEXT("%s\n\n%s"),szErr,szDescr); MessageBox(hDlg,szErrMessage,szTitle,MB_OK | MB_ICONSTOP); LocalFree(szErrMessage); } LocalFree(szDescr); } else { MessageBox(hDlg,szErr,szTitle,MB_OK | MB_ICONSTOP); } if(hNetErrModule) { FreeLibrary(hNetErrModule); } } //************************************************************* // // getGroupMembershipPickerSettings() // // Purpose: prepares DSOP_SCOPE_INIT_INFO // // Parameters: OUT DSOP_SCOPE_INIT_INFO*& infos, // OUT ULONG& infoCount // // Return: FALSE if cannot allocate memory // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* BOOL getGroupMembershipPickerSettings( OUT DSOP_SCOPE_INIT_INFO*& infos, OUT ULONG& infoCount) { static const int INFO_COUNT = 5; infos = new DSOP_SCOPE_INIT_INFO[INFO_COUNT]; if(infos == NULL) { infoCount = 0; return FALSE; } infoCount = INFO_COUNT; memset(infos, 0, sizeof(DSOP_SCOPE_INIT_INFO) * INFO_COUNT); int scope = 0; infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); infos[scope].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER; infos[scope].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE | DSOP_SCOPE_FLAG_WANT_DOWNLEVEL_BUILTIN_PATH; // this is implied for machine only scope /* | DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT */ // allow only local users from the machine scope infos[scope].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS; infos[scope].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS; // | DSOP_DOWNLEVEL_FILTER_ALL_WELLKNOWN_SIDS; // for the domain this machine is joined to (native and mixed mode). scope++; infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); infos[scope].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; infos[scope].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN; infos[scope].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE //| DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE | DSOP_FILTER_USERS; // here, we allow only domain global groups and domain users. While // it is possible to add a domain local group to a machine local group, // I'm told such an operation is not really useful from an administraion // perspective. infos[scope].FilterFlags.Uplevel.flMixedModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_USERS; // same comment above re: domain local groups applies here too. infos[scope].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS | DSOP_DOWNLEVEL_FILTER_USERS; // for domains in the same tree (native and mixed mode) scope++; infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); infos[scope].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN; infos[scope].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; infos[scope].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_USERS; // above domain local group comment applies here, too. infos[scope].FilterFlags.Uplevel.flMixedModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_USERS; // for external trusted domains scope++; infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); infos[scope].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; infos[scope].flType = DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN; infos[scope].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_USERS; infos[scope].FilterFlags.Uplevel.flMixedModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_USERS; infos[scope].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS | DSOP_DOWNLEVEL_FILTER_USERS; // for the global catalog scope++; infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); infos[scope].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; infos[scope].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG; // only native mode applies to gc scope. infos[scope].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE | DSOP_FILTER_UNIVERSAL_GROUPS_SE | DSOP_FILTER_USERS; // SPB:252126 the workgroup scope doesn't apply in this case // // for when the machine is not joined to a domain // scope++; // infos[scope].cbSize = sizeof(DSOP_SCOPE_INIT_INFO); // infos[scope].flScope = DSOP_SCOPE_FLAG_WANT_PROVIDER_WINNT; // infos[scope].flType = DSOP_SCOPE_TYPE_WORKGROUP; // // infos[scope].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS; // infos[scope].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS; _ASSERT(scope == INFO_COUNT - 1); return TRUE; } //************************************************************* // // VariantToSid() // // Purpose: Converts a VARIANT containing a safe array // of bytes to a SID // // Parameters: IN VARIANT* var, // OUT PSID *ppSid // // Return: // // Comments: // // History: Date Author Comment // 3/13/00 a-skuzin Created // //************************************************************* HRESULT VariantToSid( IN VARIANT* var, OUT PSID *ppSid) { _ASSERT(var); _ASSERT(V_VT(var) == (VT_ARRAY | VT_UI1)); HRESULT hr = S_OK; SAFEARRAY* psa = V_ARRAY(var); do { _ASSERT(psa); if (!psa) { hr = E_INVALIDARG; break; } if (SafeArrayGetDim(psa) != 1) { hr = E_INVALIDARG; break; } if (SafeArrayGetElemsize(psa) != 1) { hr = E_INVALIDARG; break; } PSID sid = 0; hr = SafeArrayAccessData(psa, reinterpret_cast(&sid)); if(FAILED(hr)) { break; } if (!IsValidSid(sid)) { SafeArrayUnaccessData(psa); hr = E_INVALIDARG; break; } *ppSid = (PSID) new BYTE[GetLengthSid(sid)]; if(!(*ppSid)) { SafeArrayUnaccessData(psa); hr = E_OUTOFMEMORY; break; } CopySid(GetLengthSid(sid),*ppSid,sid); SafeArrayUnaccessData(psa); } while (0); return hr; } /***************************************************************************** * * TestUserForAdmin - Hydrix helper function * * Returns whether the current thread is running under admin * security. * * ENTRY: * NONE * * EXIT: * TRUE/FALSE - whether user is specified admin * ****************************************************************************/ BOOL TestUserForAdmin() { BOOL IsMember, IsAnAdmin; SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY; PSID AdminSid; if (!AllocateAndInitializeSid(&SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdminSid)) { IsAnAdmin = FALSE; } else { if (!CheckTokenMembership( NULL, AdminSid, &IsMember)) { FreeSid(AdminSid); IsAnAdmin = FALSE; } else { FreeSid(AdminSid); IsAnAdmin = IsMember; } } return IsAnAdmin; } //************************************************************* // // OfflineFilesDlgProc() // // Purpose: Dialog box procedure for "Disable Offline Files" dialog // // Parameters: hDlg - handle to the dialog box // uMsg - window message // wParam - wParam // lParam - lParam (if uMsg is WM_INITDIALOG - this is a pointer to // object of COfflineFilesDialog class) // // Return: TRUE if message was processed // FALSE if not // // Comments: // // History: Date Author Comment // 5/9/00 a-skuzin Created // //************************************************************* INT_PTR APIENTRY OfflineFilesDlgProc ( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { COfflineFilesDialog *pDlg = (COfflineFilesDialog *) GetWindowLongPtr(hDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { pDlg=(COfflineFilesDialog *)lParam; SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)pDlg); if(pDlg) { pDlg->OnInitDialog(hDlg); } } break; case WM_NOTIFY: switch (((NMHDR FAR*)lParam)->code) { case NM_CLICK: case NM_RETURN: if(pDlg) { pDlg->OnLink(wParam); } break; default: return FALSE; } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: case IDCANCEL: EndDialog(hDlg,0); break; default: return FALSE; } default: return FALSE; } return TRUE; } //************************************************************* // class COfflineFilesDialog //************************************************************* //************************************************************* // // COfflineFilesDialog::COfflineFilesDialog() // // Purpose: Constructor // Parameters: HINSTANCE hInst // // Return: NONE // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* COfflineFilesDialog::COfflineFilesDialog( IN HINSTANCE hInst) : m_hInst(hInst),m_hDlg(NULL) { } //************************************************************* // // COfflineFilesDialog::DoDialog() // // Purpose: Creates "Disable Offline Files" dialog // // Parameters: HWND hwndParent // // Return: // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* INT_PTR COfflineFilesDialog::DoDialog( IN HWND hwndParent) { return DialogBoxParam( m_hInst, MAKEINTRESOURCE(IDD_DISABLE_OFFLINE_FILES), hwndParent, OfflineFilesDlgProc, (LPARAM) this); } //************************************************************* // // COfflineFilesDialog::OnInitDialog() // // Purpose: Initializes m_hDlg variable // // Parameters: HWND hDlg // // Return: NONE // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* void COfflineFilesDialog::OnInitDialog( IN HWND hDlg) { m_hDlg = hDlg; } //************************************************************* // // COfflineFilesDialog::OnLink() // // Purpose: If ID of the link is IDC_OFFLINE_FILES // it shows "Offline Files" property page. // // Parameters: WPARAM wParam - ID of the link. // // Return: NONE // // Comments: // // History: Date Author Comment // 5/9/00 a-skuzin Created // //************************************************************* typedef DWORD (WINAPI * PFNCSCPROP)(HWND); void COfflineFilesDialog::OnLink( IN WPARAM wParam) { if(wParam == IDC_OFFLINE_FILES) { HINSTANCE hLib = LoadLibrary(TEXT("cscui.dll")); if (hLib) { PFNCSCPROP pfnCSCUIOptionsPropertySheet = (PFNCSCPROP)GetProcAddress(hLib, "CSCUIOptionsPropertySheet"); if (pfnCSCUIOptionsPropertySheet) { pfnCSCUIOptionsPropertySheet(m_hDlg); } FreeLibrary(hLib); } } } //************************************************************* // class CRemoteUsersDialog //************************************************************* //************************************************************* // // RemoteUsersDlgProc() // // Purpose: Dialog box procedure for "Remote Desktop Users" dialog // // Parameters: hDlg - handle to the dialog box // uMsg - window message // wParam - wParam // lParam - lParam (if uMsg is WM_INITDIALOG - this is a pointer to // object of CRemoteUsersDialog class) // // Return: TRUE if message was processed // FALSE if not // // Comments: // // History: Date Author Comment // 12/22/00 skuzin Created // //************************************************************* INT_PTR APIENTRY RemoteUsersDlgProc ( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { CRemoteUsersDialog *pDlg = (CRemoteUsersDialog *) GetWindowLongPtr(hDlg, DWLP_USER); switch (uMsg) { case WM_INITDIALOG: { pDlg=(CRemoteUsersDialog *)lParam; SetWindowLongPtr(hDlg,DWLP_USER,(LONG_PTR)pDlg); if(pDlg) { pDlg->OnInitDialog(hDlg); } } return TRUE; case WM_NOTIFY: switch (((NMHDR FAR*)lParam)->code) { case NM_CLICK: case NM_RETURN: if(pDlg) { pDlg->OnLink(wParam); } return TRUE; case LVN_ITEMCHANGED: if(pDlg) { pDlg->OnItemChanged(lParam); } return TRUE; default: break; } break; case WM_COMMAND: switch(LOWORD(wParam)) { case IDOK: if(pDlg) { pDlg->OnOk(); } EndDialog(hDlg,0); break; case IDCANCEL: EndDialog(hDlg,0); break; case IDC_REMOTE_USR_ADD: if(pDlg) { pDlg->AddUsers(); } break; case IDC_REMOTE_USR_REMOVE: if(pDlg) { pDlg->RemoveUsers(); } break; default: return FALSE; } SetWindowLong(hDlg,DWLP_MSGRESULT,0); return TRUE; case WM_DESTROY: if(pDlg) { pDlg->OnDestroyWindow(); } SetWindowLong(hDlg,DWLP_MSGRESULT,0); return TRUE; case WM_HELP: { LPHELPINFO phi=(LPHELPINFO)lParam; if(phi && phi->dwContextId) { WinHelp(hDlg,TEXT("SYSDM.HLP"),HELP_CONTEXTPOPUP,phi->dwContextId); SetWindowLong(hDlg,DWLP_MSGRESULT,TRUE); return TRUE; } } break; case WM_CONTEXTMENU: // right mouse click WinHelp((HWND) wParam, TEXT("SYSDM.HLP"), HELP_CONTEXTMENU, (DWORD_PTR)aHelpIds); return TRUE; default: break; } return FALSE; } //************************************************************* // // CRemoteUsersDialog::CRemoteUsersDialog() // // Purpose: Constructor // Parameters: HINSTANCE hInst // // Return: NONE // // Comments: // // History: Date Author Comment // 12/22/00 skuzin Created // //************************************************************* CRemoteUsersDialog::CRemoteUsersDialog( IN HINSTANCE hInst) : m_hInst(hInst),m_hDlg(NULL),m_bCanShowDialog(FALSE) { m_szRemoteGroupName[0] = 0; m_szLocalCompName[0] = 0; m_hList = NULL; m_iLocUser = m_iGlobUser = m_iLocGroup = m_iGlobGroup = m_iUnknown = 0; } //************************************************************* // // CRemoteUsersDialog::DoDialog() // // Purpose: Creates "Remote Desktop Users" dialog // // Parameters: HWND hwndParent // // Return: // // Comments: // // History: Date Author Comment // 12/22/00 a-skuzin Created // //************************************************************* INT_PTR CRemoteUsersDialog::DoDialog( IN HWND hwndParent) { if(!m_bCanShowDialog) { return -1; } else { return DialogBoxParam( m_hInst, MAKEINTRESOURCE(IDD_REMOTE_DESKTOP_USERS), hwndParent, RemoteUsersDlgProc, (LPARAM) this); } } //************************************************************* // // CRemoteUsersDialog::CanShowDialog() // // Purpose: // // Parameters: IN OUT LPBOOL pbAccessDenied - set to TRUE if // NetLocalGroupAddMembers returns ACCESS_DENIED. // // Return: // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* BOOL CRemoteUsersDialog::CanShowDialog( IN OUT LPBOOL pbAccessDenied) { *pbAccessDenied = FALSE; //get name of the "Remote Desktop Users" group //(it can depend on the language used) //first create SID SID_IDENTIFIER_AUTHORITY NtSidAuthority = SECURITY_NT_AUTHORITY; PSID pSid = NULL; if( !AllocateAndInitializeSid( &NtSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS, 0, 0, 0, 0, 0, 0, &pSid )) { return FALSE; } //Lookup name m_szRemoteGroupName[0] = 0; DWORD cRemoteGroupName = MAX_PATH; WCHAR szDomainName[MAX_PATH+1]; DWORD cDomainName = MAX_PATH; SID_NAME_USE eUse; if(!LookupAccountSidW(NULL,pSid, m_szRemoteGroupName,&cRemoteGroupName, szDomainName,&cDomainName, &eUse)) { FreeSid(pSid); return FALSE; } FreeSid(pSid); //on the group //we trying to add 0 members to the group to see if it returns //ACCESS DENIED NET_API_STATUS Result= NetLocalGroupAddMembers(NULL,m_szRemoteGroupName,0,NULL,0); if(Result == ERROR_ACCESS_DENIED) { *pbAccessDenied = TRUE; } m_bCanShowDialog = TRUE; return TRUE; } //************************************************************* // // CRemoteUsersDialog::OnInitDialog() // // Purpose: Initializes m_hDlg variable // // Parameters: HWND hDlg // // Return: NONE // // Comments: // // History: Date Author Comment // 5/8/00 a-skuzin Created // //************************************************************* void CRemoteUsersDialog::OnInitDialog( IN HWND hDlg) { m_hDlg = hDlg; m_szLocalCompName[0] = 0; DWORD cCompName = MAX_PATH; GetComputerNameW(m_szLocalCompName,&cCompName); //fill list of Remote Desktop Users m_hList = GetDlgItem(m_hDlg,IDC_REMOTE_USR_LIST); if(m_hList) { //create image list HIMAGELIST hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK , 5, 1); if(hImageList) { HICON hIcon; hIcon = (HICON) LoadImage(m_hInst, MAKEINTRESOURCE(IDI_UNKNOWN), IMAGE_ICON, 16, 16, 0); if (hIcon) { m_iUnknown = ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } hIcon = (HICON) LoadImage(m_hInst, MAKEINTRESOURCE(IDI_LOC_USER), IMAGE_ICON, 16, 16, 0); if (hIcon) { m_iLocUser = ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } hIcon = (HICON) LoadImage(m_hInst, MAKEINTRESOURCE(IDI_GLOB_USER), IMAGE_ICON, 16, 16, 0); if (hIcon) { m_iGlobUser = ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } hIcon = (HICON) LoadImage(m_hInst, MAKEINTRESOURCE(IDI_LOC_GROUP), IMAGE_ICON, 16, 16, 0); if (hIcon) { m_iLocGroup = ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } hIcon = (HICON) LoadImage(m_hInst, MAKEINTRESOURCE(IDI_GLOB_GROUP), IMAGE_ICON, 16, 16, 0); if (hIcon) { m_iGlobGroup = ImageList_AddIcon(hImageList, hIcon); DestroyIcon(hIcon); } ListView_SetImageList(m_hList,hImageList,LVSIL_SMALL); } ReloadList(); } //If current user already has remote logon access, //remind it to him by showing corresponding text in the dialog. InitAccessMessage(); } //************************************************************* // // CRemoteUsersDialog::OnLink() // // Purpose: // // Parameters: WPARAM wParam - ID of the link. // // Return: NONE // // Comments: // // History: Date Author Comment // 5/9/00 a-skuzin Created // //************************************************************* void CRemoteUsersDialog::OnLink( IN WPARAM wParam) { switch(wParam) { case IDC_REMOTE_UPLINK: ShellExecute(NULL,TEXT("open"),TEXT("control"),TEXT("userpasswords"),NULL,SW_SHOW); break; default: break; } } //************************************************************* // // CRemoteUsersDialog::OnOk() // // Purpose: // // Parameters: NONE // // Return: TRUE if success // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* BOOL CRemoteUsersDialog::OnOk() { if(m_hList) { //Apply members LOCALGROUP_MEMBERS_INFO_0 *plmi0 = NULL; DWORD entriesread; DWORD totalentries; NET_API_STATUS Result; Result = NetLocalGroupGetMembers(NULL,m_szRemoteGroupName,0,(LPBYTE *)&plmi0, MAX_PREFERRED_LENGTH,&entriesread,&totalentries,NULL); if(Result == NERR_Success) { int j; LOCALGROUP_MEMBERS_INFO_0 lmi0; LVITEM lvi; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM ; int iItems=ListView_GetItemCount(m_hList); BOOL *pbDoNotAdd = new BOOL[iItems]; if(!pbDoNotAdd) { if(plmi0) { NetApiBufferFree(plmi0); } //not enough memory - too bad return TRUE; } ZeroMemory(pbDoNotAdd,iItems*sizeof(BOOL)); for(DWORD i=0;i(lParam); if (lv->uChanged & LVIF_STATE) { // a list item changed state BOOL selected = ListView_GetSelectedCount(m_hList) > 0; EnableWindow(GetDlgItem(m_hDlg, IDC_REMOTE_USR_REMOVE), selected); //If we disabled IDC_REMOTE_USR_REMOVE button while it had focus //all property page loses focus so "Tab" key does not //work anymore. We need to restore focus. if(!GetFocus()) { SetFocus(m_hDlg); } } } //************************************************************* // // CRemoteUsersDialog::OnDestroyWindow() // // Purpose: Frees memory allocated by member's SIDs // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* void CRemoteUsersDialog::OnDestroyWindow() { if(m_hList) { int iItems=ListView_GetItemCount(m_hList); LVITEM lvi; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; while(iItems) { lvi.iItem = 0; ListView_GetItem( m_hList, &lvi ); //delete item ListView_DeleteItem(m_hList, 0); if(lvi.lParam) { delete (LPVOID)lvi.lParam; } iItems--; //decrease item count } } } //************************************************************* // // CRemoteUsersDialog::AddUsers() // // Purpose: adds users to the list // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* void CRemoteUsersDialog::AddUsers() { HRESULT hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); if(SUCCEEDED(hr)) { IDsObjectPicker *pDsObjectPicker = NULL; hr = CoCreateInstance(CLSID_DsObjectPicker, NULL, CLSCTX_INPROC_SERVER, IID_IDsObjectPicker, (void **) &pDsObjectPicker); if(SUCCEEDED(hr)) { DSOP_INIT_INFO initInfo; memset(&initInfo, 0, sizeof(initInfo)); initInfo.cbSize = sizeof(initInfo); initInfo.flOptions = DSOP_FLAG_MULTISELECT; // aliasing the computerName internal pointer here -- ok, as lifetime // of computerName > initInfo initInfo.pwzTargetComputer = NULL; initInfo.cAttributesToFetch = 1; PWSTR attrs[2] = {0, 0}; attrs[0] = L"ObjectSID"; // obtuse notation required to cast *in* const and away the static len initInfo.apwzAttributeNames = const_cast(&attrs[0]); if(getGroupMembershipPickerSettings(initInfo.aDsScopeInfos, initInfo.cDsScopeInfos)) { IDataObject* pdo = NULL; if(SUCCEEDED(pDsObjectPicker->Initialize(&initInfo)) && pDsObjectPicker->InvokeDialog(m_hDlg, &pdo) == S_OK && pdo ) { CWaitCursor wait; static const UINT cf = RegisterClipboardFormat(CFSTR_DSOP_DS_SELECTION_LIST); FORMATETC formatetc = { (CLIPFORMAT)cf, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; STGMEDIUM stgmedium = { TYMED_HGLOBAL, 0 }; if(cf && SUCCEEDED(pdo->GetData(&formatetc, &stgmedium))) { PVOID lockedHGlobal = GlobalLock(stgmedium.hGlobal); DS_SELECTION_LIST* selections = reinterpret_cast(lockedHGlobal); AddPickerItems(selections); GlobalUnlock(stgmedium.hGlobal); } pdo->Release(); } delete initInfo.aDsScopeInfos; } pDsObjectPicker->Release(); } CoUninitialize(); } } //************************************************************* // // CRemoteUsersDialog::RemoveUsers() // // Purpose: Removes users from the list // // Parameters: NONE // // Return: NONE // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* void CRemoteUsersDialog::RemoveUsers() { //delete all selected items if(m_hList) { int iItems=ListView_GetItemCount(m_hList); UINT uiState=0; int i=0; LVITEM lvi; lvi.iSubItem = 0; lvi.mask = LVIF_STATE | LVIF_PARAM; lvi.stateMask = LVIS_SELECTED; while(iaDsSelection[0]); if(m_hList) { for (ULONG i = 0; i < selections->cItems; i++, current++) { // extract the ObjectSID of the object (this should always be // present) PSID pSid; HRESULT hr = VariantToSid(¤t->pvarFetchedAttributes[0],&pSid); if( SUCCEEDED(hr) ) { //This SID is not in the list //Let's add it. if(FindItemBySid(pSid) == -1) { LPWSTR szFullName = NULL; SID_NAME_USE eUse; LVITEM item; ZeroMemory(&item,sizeof(item)); item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; //put SID it into the item data //the allocated memory will be freed in OnDestroyWindow() item.lParam = (LPARAM)pSid; if(LookupSid(pSid,&szFullName, &eUse)) { item.pszText = szFullName; } else { eUse = SidTypeUnknown; if(current->pwzName) { item.pszText = current->pwzName; } else { item.pszText = L"?"; } } switch(eUse) { case SidTypeUser: item.iImage = IsLocal(szFullName) ? m_iLocUser : m_iGlobUser; break; case SidTypeGroup: item.iImage = IsLocal(szFullName) ? m_iLocGroup : m_iGlobGroup; break; case SidTypeWellKnownGroup: item.iImage = m_iLocGroup; break; default: item.iImage = m_iUnknown; break; } if(ListView_InsertItem(m_hList,&item) == -1) { delete pSid; } if(szFullName) { LocalFree(szFullName); } } else { //Free allocated memory delete pSid; } } } } } //************************************************************* // // CRemoteUsersDialog::FindItemBySid() // // Purpose: finds user with particular SID in the list // // Parameters: pSid - SID to find // // Return: item index (-1 if not found) // // Comments: // // History: Date Author Comment // 12/27/00 skuzin Created // //************************************************************* int CRemoteUsersDialog::FindItemBySid( IN PSID pSid) { if(m_hList) { LVITEM lvi; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM ; int iItems=ListView_GetItemCount(m_hList); for(int i=0;iUser.Sid,ppName,&eUse); } LocalFree(pTUser); } } return FALSE; } //************************************************************* // // GetRDPSecurityDescriptor() // // Purpose: Returns security descriptor for RDP-Tcp // // Parameters: OUT PSECURITY_DESCRIPTOR *ppSD // // Return: TRUE - if success // FALSE - in case of any error // // Comments: Caller should free memory allocated for // security descriptor using LocalFree function // // History: Date Author Comment // 01/04/01 skuzin Created // //************************************************************* BOOL GetRDPSecurityDescriptor( OUT PSECURITY_DESCRIPTOR *ppSD) { *ppSD = NULL; if( FAILED( CoInitializeEx(NULL, COINIT_APARTMENTTHREADED) ) ) { return FALSE; } ICfgComp *pCfgcomp; if( SUCCEEDED( CoCreateInstance( CLSID_CfgComp , NULL , CLSCTX_INPROC_SERVER , IID_ICfgComp , ( LPVOID *)&pCfgcomp ) ) ) { LONG lSDsize; PSECURITY_DESCRIPTOR pSD = NULL; if( SUCCEEDED( pCfgcomp->Initialize() ) && SUCCEEDED( pCfgcomp->GetSecurityDescriptor( L"RDP-Tcp" , &lSDsize , &pSD ) ) ) { *ppSD = pSD; } pCfgcomp->Release(); } CoUninitialize(); return (*ppSD != NULL); } //************************************************************* // // CheckWinstationLogonAccess() // // Purpose: Tests access token for LOGON access to WinStation // // Parameters: IN HANDLE hToken // IN PSECURITY_DESCRIPTOR pSD // // Return: TRUE - if user has access // FALSE - in case of any error or if user // does not have access // // Comments: // // History: Date Author Comment // 01/04/01 skuzin Created // //************************************************************* BOOL CheckWinstationLogonAccess( IN HANDLE hToken, IN PSECURITY_DESCRIPTOR pSD) { //this is taken from "termsrv\winsta\server\acl.c" // // Structure that describes the mapping of generic access rights to object // specific access rights for Window Station objects. // GENERIC_MAPPING WinStaMapping = { STANDARD_RIGHTS_READ | WINSTATION_QUERY, STANDARD_RIGHTS_WRITE | WINSTATION_SET, STANDARD_RIGHTS_EXECUTE, WINSTATION_ALL_ACCESS }; PRIVILEGE_SET PrivilegeSet; //There are no privileges used for this access check //so we don't need to allocate additional memory DWORD dwPrivilegeSetLength = sizeof(PrivilegeSet); DWORD dwGrantedAccess = 0; BOOL bAccessStatus = FALSE; if(!AccessCheck( pSD, // SD hToken, // handle to client access token WINSTATION_LOGON, // requested access rights &WinStaMapping, // mapping &PrivilegeSet, // privileges &dwPrivilegeSetLength, // size of privileges buffer &dwGrantedAccess, // granted access rights &bAccessStatus // result of access check ) || !bAccessStatus ) { return FALSE; } return TRUE; } //************************************************************* // // LookupSid() // // Purpose: Given SID allocates and returns string containing // name of the user in format DOMAINNAME\USERNAME // // Parameters: IN PSID pSid // OUT LPWSTR ppName // OUT SID_NAME_USE *peUse // // Return: TRUE if success, FALSE otherwise // // Comments: // // History: Date Author Comment // 10/23/00 skuzin Created // //************************************************************* BOOL LookupSid( IN PSID pSid, OUT LPWSTR *ppName, OUT SID_NAME_USE *peUse) { LPWSTR szName = NULL; DWORD cName = 0; LPWSTR szDomainName = NULL; DWORD cDomainName = 0; *ppName = NULL; if(!LookupAccountSidW(NULL,pSid, szName,&cName, szDomainName,&cDomainName, peUse) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { //cName and cDomainName include terminating 0 *ppName = (LPWSTR)LocalAlloc(LPTR,(cName+cDomainName)*sizeof(WCHAR)); if(*ppName) { szDomainName = *ppName; szName = &(*ppName)[cDomainName]; if(LookupAccountSidW(NULL,pSid, szName,&cName, szDomainName,&cDomainName, peUse)) { //user name now in format DOMAINNAME\0USERNAME //let's replace '\0' with '\\' //now cName and cDomainName do not include terminating 0 //very confusing if(cDomainName) { (*ppName)[cDomainName] = L'\\'; } return TRUE; } else { LocalFree(*ppName); *ppName = NULL; } } } return FALSE; }