|
|
//+---------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1993 - 1997.
//
// File: clspsht.cpp
//
// Contents: Implements class CClsidPropertySheet
//
// Classes:
//
// Methods: CClsidPropertySheet::CClsidPropertySheet
// CClsidPropertySheet::~CClsidPropertySheet
// CClsidPropertySheet::InitData
// CClsidPropertySheet::OnNcCreate
// CClsidPropertySheet::ValidateAndUpdate
// CClsidPropertySheet::OnCommand
// CClsidPropertySheet::LookAtCLSIDs
// CClsidPropertySheet::ChangeCLSIDInfo
//
// History: 23-Apr-96 BruceMa Created.
//
//----------------------------------------------------------------------
#include "stdafx.h"
#include "resource.h"
#include "clspsht.h"
#include "datapkt.h"
#if !defined(STANDALONE_BUILD)
extern "C" { #include <getuser.h>
} #endif
#include "util.h"
#include "newsrvr.h"
#if !defined(STANDALONE_BUILD)
extern "C" { #include <sedapi.h>
#include <ntlsa.h>
} #endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__; #endif
/////////////////////////////////////////////////////////////////////////////
// CClsidPropertySheet
IMPLEMENT_DYNAMIC(CClsidPropertySheet, CPropertySheet)
CClsidPropertySheet::CClsidPropertySheet(CWnd* pParentWnd) : CPropertySheet(IDS_PROPSHT_CAPTION1, pParentWnd) { }
CClsidPropertySheet::~CClsidPropertySheet() { }
BEGIN_MESSAGE_MAP(CClsidPropertySheet, CPropertySheet) //{{AFX_MSG_MAP(CClsidPropertySheet)
ON_WM_NCCREATE() //}}AFX_MSG_MAP
END_MESSAGE_MAP()
CClsidPropertySheet::InitData( CString szAppName, HKEY hkAppID, HKEY * rghkCLSID, unsigned cCLSIDs) { m_szAppName = szAppName; m_hkAppID = hkAppID; m_rghkCLSID = rghkCLSID; m_cCLSIDs = cCLSIDs;
// Save the appid key, the table of clsid keys and the application
// title globally so the property pages can access them
// it
g_hAppid = hkAppID; g_rghkCLSID = rghkCLSID; g_cCLSIDs = cCLSIDs; g_szAppTitle = (TCHAR *) LPCTSTR(szAppName);
m_Page2.m_fRemote = FALSE; m_Page4.m_fService = FALSE; m_Page2.m_fCanBeLocal = FALSE; m_Page2.m_fLocal = FALSE; m_Page1.m_fSurrogate = FALSE;
if (!LookAtCLSIDs()) { return FALSE; }
TCHAR szBuffer[MAX_PATH]; DWORD dwSize; long lErr;
dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( m_hkAppID, TEXT("LocalService"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page4.m_fService = TRUE; m_Page2.m_fCanBeLocal = TRUE; m_Page2.m_fLocal = TRUE; } else { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( m_hkAppID, TEXT("_LocalService"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page4.m_fService = TRUE; m_Page2.m_fCanBeLocal = TRUE; } }
dwSize = sizeof(szBuffer);
if (!m_Page2.m_fLocal) { lErr = RegQueryValueEx( m_hkAppID, TEXT("DllSurrogate"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { if (szBuffer[0]) m_Page1.m_szServerPath = szBuffer; else m_Page1.m_szServerPath.LoadString(IDS_DEFAULT); m_Page1.m_fSurrogate = TRUE; }
} dwSize = sizeof(szBuffer);
lErr = RegQueryValueEx( m_hkAppID, TEXT("RemoteServerName"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szComputerName = szBuffer; m_Page2.m_szComputerName = szBuffer; m_Page2.m_fRemote = TRUE; }
m_Page2.m_fAtStorage = FALSE; dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( m_hkAppID, TEXT("ActivateAtStorage"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { if (szBuffer[0] == L'Y' || szBuffer[0] == L'y') { // m_Page2.m_fRemote = TRUE;
m_Page2.m_fAtStorage = TRUE; } }
dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( m_hkAppID, TEXT("RunAs"), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { // If the RunAs name is empty, jam in something
if (szBuffer[0] == TEXT('\0')) { _tcscpy(szBuffer, TEXT("<domain>\\<user>")); }
if (0 == _tcsicmp(szBuffer, TEXT("Interactive User"))) { m_Page4.m_iIdentity = 0; } else { m_Page4.m_iIdentity = 2; m_Page4.m_szUserName = szBuffer;
// Extract password from the Lsa private database
g_util.RetrieveUserPassword(g_szAppid , m_Page4.m_szPassword); m_Page4.m_szConfirmPassword = m_Page4.m_szPassword; } } else { if (m_Page4.m_fService) { m_Page4.m_iIdentity = 3; } else { m_Page4.m_iIdentity = 1; } }
m_Page1.m_szServerName = m_szAppName;
if (!m_Page1.m_fSurrogate) { if (m_Page2.m_fCanBeLocal) { if (m_Page4.m_fService) m_Page1.m_iServerType = SERVICE; else m_Page1.m_iServerType = LOCALEXE; if (m_Page2.m_fRemote) m_Page1.m_iServerType += 3; } else m_Page1.m_iServerType = PURE_REMOTE; } else { m_Page1.m_iServerType = SURROGATE; }
// Set the title
SetTitle((const TCHAR *) m_szAppName, PSH_PROPTITLE); m_Page1.m_szServerName = m_szAppName;
// TODO: If there are running instances, then make IDC_RUNNING,
// IDC_LIST2, IDC_BUTTON1, IDC_BUTTON2, and IDC_BUTTON3 visible
// and fill in IDC_LIST2 on page 1.
m_Page2.m_pPage1 = &m_Page1;
// Fetch RunAs key, LaunchPermission, AccessPermission and
// ConfigurationPermission
int err; DWORD dwType; BYTE bValue[16]; BYTE *pbValue = NULL; ULONG ulSize = 1;
m_Page3.m_iAccess = 0; m_Page3.m_iLaunch = 0; m_Page3.m_iConfig = 0;
// "AccessPermission"
// Note: We always expect to get ERROR_MORE_DATA
err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0, &dwType, bValue, &ulSize); if (err == ERROR_MORE_DATA) { pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize); if (pbValue == NULL) { return FALSE; } err = RegQueryValueEx(g_hAppid, TEXT("AccessPermission"), 0, &dwType, pbValue, &ulSize); }
if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue)) { m_Page3.m_iAccess = 1; g_virtreg.NewRegSingleACL(g_hAppid, NULL, TEXT("AccessPermission"), (SECURITY_DESCRIPTOR *) pbValue, TRUE, // Already in self-relative form
&m_Page3.m_iAccessIndex); CDataPacket *pCdb = g_virtreg.GetAt(m_Page3.m_iAccessIndex); pCdb->SetModified(FALSE); } GlobalFree(pbValue); pbValue = NULL;
// "LaunchPermission"
// Note: We always expect to get ERROR_MORE_DATA
ulSize = 1; pbValue = NULL; err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0, &dwType, bValue, &ulSize); if (err == ERROR_MORE_DATA) { pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize); if (pbValue == NULL) { return FALSE; } err = RegQueryValueEx(g_hAppid, TEXT("LaunchPermission"), 0, &dwType, pbValue, &ulSize); }
if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue)) { m_Page3.m_iLaunch = 1; g_virtreg.NewRegSingleACL(g_hAppid, NULL, TEXT("LaunchPermission"), (SECURITY_DESCRIPTOR *) pbValue, TRUE, // Already in self-relative form
&m_Page3.m_iLaunchIndex); CDataPacket * pCdb = g_virtreg.GetAt(m_Page3.m_iLaunchIndex); pCdb->SetModified(FALSE); } GlobalFree(pbValue); pbValue = NULL;
// "ConfigurationPermission"
// Fetch the security descriptor on this AppID
// Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
ulSize = 1; err = RegGetKeySecurity(g_hAppid, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbValue, &ulSize); if (err == ERROR_INSUFFICIENT_BUFFER) { pbValue = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize); if (pbValue == NULL) { return FALSE; } err = RegGetKeySecurity(g_hAppid, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbValue, &ulSize); }
// Fetch the current security descriptor on HKEY_CLASSES_ROOT
// Note: We always expect to get ERROR_INSUFFICIENT_BUFFER
BYTE *pbValue2 = NULL;
ulSize = 1; pbValue2 = NULL; err = RegGetKeySecurity(HKEY_CLASSES_ROOT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbValue2, &ulSize); if (err == ERROR_INSUFFICIENT_BUFFER) { pbValue2 = (BYTE *)GlobalAlloc(GMEM_FIXED, ulSize); if (pbValue2 == NULL) { return FALSE; } err = RegGetKeySecurity(HKEY_CLASSES_ROOT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbValue2, &ulSize); }
// Now compare them. If they differ then this AppId uses custom
// configuration permissions
if (err == ERROR_SUCCESS && g_util.CheckForValidSD((SECURITY_DESCRIPTOR *)pbValue)) { if (!g_util.CompareSDs((PSrSecurityDescriptor) pbValue, (PSrSecurityDescriptor) pbValue2)) { err = g_virtreg.NewRegKeyACL(g_hAppid, rghkCLSID, cCLSIDs, g_szAppTitle, (SECURITY_DESCRIPTOR *) pbValue, (SECURITY_DESCRIPTOR *) pbValue, TRUE, &m_Page3.m_iConfigurationIndex); CDataPacket * pCdb = g_virtreg.GetAt(m_Page3.m_iConfigurationIndex); pCdb->SetModified(FALSE); m_Page3.m_iConfig = 1; } } GlobalFree(pbValue); GlobalFree(pbValue2);
// Add all of the property pages here. Note that
// the order that they appear in here will be
// the order they appear in on screen. By default,
// the first page of the set is the active one.
// One way to make a different property page the
// active one is to call SetActivePage().
AddPage(&m_Page1); if (m_Page1.m_iServerType != SURROGATE) { AddPage(&m_Page2); } if (m_Page2.m_fCanBeLocal || m_Page1.m_fSurrogate) { AddPage(&m_Page3); AddPage(&m_Page4); } // add the property page for endpoint options
AddPage(&m_Page5); m_Page5.InitData(szAppName, hkAppID);
return TRUE; }
/////////////////////////////////////////////////////////////////////////////
// CClsidPropertySheet message handlers
BOOL CClsidPropertySheet::OnNcCreate(LPCREATESTRUCT lpCreateStruct) { if (!CPropertySheet::OnNcCreate(lpCreateStruct)) return FALSE;
ModifyStyleEx(0, WS_EX_CONTEXTHELP);
return TRUE; }
BOOL CClsidPropertySheet::ValidateAndUpdate(void) { // Call update data on all initialized pages
// to make sure that their private member variables are correct.
long lErr;
BOOL fReturn = UpdateData(TRUE); if (fReturn && m_Page1.m_hWnd) fReturn = m_Page1.ValidateChanges(); if (fReturn && m_Page2.m_hWnd) fReturn = m_Page2.ValidateChanges(); if (fReturn && m_Page3.m_hWnd) fReturn = m_Page3.ValidateChanges(); if (fReturn && m_Page4.m_hWnd) fReturn = m_Page4.ValidateChanges();
if (fReturn && m_Page5.m_hWnd) fReturn = m_Page5.ValidateChanges();
if (!fReturn) return FALSE;
m_Page1.UpdateChanges(m_hkAppID); m_Page2.UpdateChanges(m_hkAppID); m_Page3.UpdateChanges(m_hkAppID); m_Page4.UpdateChanges(m_hkAppID); m_Page5.UpdateChanges(m_hkAppID);
////////////////////////////////////////////////////////////////////
// Persist cross page data
if (m_Page4.m_fService) { if (m_Page2.m_fLocal) { BOOL fOk;
// Write the LocalService value to the registry
lErr = RegSetValueEx( m_hkAppID, TEXT("LocalService"), 0, REG_SZ, (BYTE *)(LPCTSTR)m_Page1.m_szServerPath, (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR)); lErr = RegDeleteValue( m_hkAppID, TEXT("_LocalService"));
// Persist information to the service manager database
if (m_Page4.m_iIdentity == 3) { fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath, TEXT("LocalSystem"), TEXT(""), (LPCTSTR) m_Page1.m_szServerName); } else { fOk = g_util.ChangeService((LPCTSTR) m_Page1.m_szServerPath, (LPCTSTR) m_Page4.m_szUserName, (LPCTSTR) m_Page4.m_szPassword, (LPCTSTR) m_Page1.m_szServerName); } if (!fOk) { return FALSE; } } else { lErr = RegSetValueEx( m_hkAppID, TEXT("_LocalService"), 0, REG_SZ, (BYTE *)(LPCTSTR)m_Page1.m_szServerPath, (1 + m_Page1.m_szServerPath.GetLength()) * sizeof (TCHAR)); lErr = RegDeleteValue( m_hkAppID, TEXT("LocalService")); } }
return ChangeCLSIDInfo(m_Page2.m_fLocal); }
BOOL CClsidPropertySheet::OnCommand(WPARAM wParam, LPARAM lParam) { switch (LOWORD(wParam)) { case IDOK: case ID_APPLY_NOW: if (!ValidateAndUpdate()) return TRUE; break; } return CPropertySheet::OnCommand(wParam, lParam); }
BOOL CClsidPropertySheet::LookAtCLSIDs(void) { BOOL fFoundLocalServer = FALSE; TCHAR szBuffer[MAX_PATH]; DWORD dwSize; HKEY hKey; long lErr;
unsigned n = 0; while (n < m_cCLSIDs && !fFoundLocalServer) { lErr = RegOpenKeyEx( m_rghkCLSID[n], TEXT("LocalServer32"), 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page2.m_fLocal = TRUE; m_Page2.m_fCanBeLocal = TRUE; fFoundLocalServer = TRUE; } RegCloseKey(hKey); }
if (!fFoundLocalServer) { lErr = RegOpenKeyEx( m_rghkCLSID[n], TEXT("LocalServer"), 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page2.m_fLocal = TRUE; m_Page2.m_fCanBeLocal = TRUE; fFoundLocalServer = TRUE; } RegCloseKey(hKey); } }
if (!fFoundLocalServer) { lErr = RegOpenKeyEx( m_rghkCLSID[n], TEXT("_LocalServer32"), 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page2.m_fCanBeLocal = TRUE; fFoundLocalServer = TRUE; } RegCloseKey(hKey); } }
if (!fFoundLocalServer) { lErr = RegOpenKeyEx( m_rghkCLSID[n], TEXT("_LocalServer"), 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { m_Page1.m_szServerPath = szBuffer; m_Page2.m_fCanBeLocal = TRUE; fFoundLocalServer = TRUE; } RegCloseKey(hKey); } }
n++; } return TRUE; }
BOOL CClsidPropertySheet::ChangeCLSIDInfo(BOOL fLocal) { TCHAR szBuffer[MAX_PATH]; CString szOld; CString szNew; CString szOld16; CString szNew16; DWORD dwSize; HKEY hKey; long lErr;
if (fLocal) { szOld = TEXT("_LocalServer32"); szNew = TEXT("LocalServer32"); szOld16 = TEXT("_LocalServer"); szNew16 = TEXT("LocalServer"); } else { szOld = TEXT("LocalServer32"); szNew = TEXT("_LocalServer32"); szOld16 = TEXT("LocalServer"); szNew16 = TEXT("_LocalServer"); }
unsigned n = 0; while (n < m_cCLSIDs) { // First do 32 servers
lErr = RegOpenKeyEx( m_rghkCLSID[n], szOld, 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { HKEY hKeyNew; DWORD dwDisp;
lErr = RegCreateKeyEx( m_rghkCLSID[n], szNew, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyNew, &dwDisp); if (lErr == ERROR_SUCCESS) { lErr = RegSetValueEx( hKeyNew, TEXT(""), NULL, REG_SZ, (BYTE *)szBuffer, dwSize); RegCloseKey(hKeyNew); } } RegCloseKey(hKey); lErr = RegDeleteKey(m_rghkCLSID[n], szOld); }
// Then do 16 servers
lErr = RegOpenKeyEx( m_rghkCLSID[n], szOld16, 0, KEY_ALL_ACCESS, &hKey); if (lErr == ERROR_SUCCESS) { dwSize = sizeof(szBuffer); lErr = RegQueryValueEx( hKey, TEXT(""), NULL, NULL, (BYTE *)szBuffer, &dwSize); if (lErr == ERROR_SUCCESS) { HKEY hKeyNew; DWORD dwDisp;
lErr = RegCreateKeyEx( m_rghkCLSID[n], szNew16, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyNew, &dwDisp); if (lErr == ERROR_SUCCESS) { lErr = RegSetValueEx( hKeyNew, TEXT(""), NULL, REG_SZ, (BYTE *)szBuffer, dwSize); RegCloseKey(hKeyNew); } } RegCloseKey(hKey); lErr = RegDeleteKey(m_rghkCLSID[n], szOld16); }
n++; } return TRUE; }
|