//********************************************************************* //* Microsoft Windows ** //* Copyright(c) Microsoft Corp., 1995 ** //********************************************************************* // // PROGRAMS.C - "Programs" property sheet UI handlers doe InetCpl // // // // History: // // 6/20/96 t-gpease created // #include "inetcplp.h" #include #include // // Private Functions and Structures // BOOL ProgramsDlgInit( HWND hDlg); void UpdateMailIconLabel(); typedef struct { HWND hDlg; // dialog windows handle HWND hwndMail; // Mail dropdown HWND hwndNews; // News dropdown HWND hwndCalendar; // Calendar dropdown HWND hwndContact; // Contact dropdown HWND hwndCall; // Internet call dropdown HWND hwndHtmlEdit; // HTML Editors dropdown BOOL bAssociationCheck; // Is IE the default browser? #ifndef UNIX BOOL bIEIsFTPClient; // Is IE the default FTP Client? IFtpInstaller * pfi; // FTP Installer #endif // UNIX int iHtmlEditor; int iMail; int iNews; int iCalendar; int iContact; int iCall; BOOL fChanged; #ifdef UNIX HWND hwndVSource; // View Source HWND hwndMailEdit; HWND hwndMailFind; HWND hwndNewsFind; HWND hwndNewsEdit; DWORD dwUseOEMail; DWORD dwUseOENews; HWND hwndEnableUseOEMail; HWND hwndEnableUseOENews; int iVSource; #endif } PROGRAMSPAGE, *LPPROGRAMSPAGE; #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #ifdef WALLET typedef int (*PFN_DISPLAYWALLETPAYDIALOG_PROC)(HWND, HINSTANCE, LPTSTR, int); typedef int (*PFN_DISPLAYWALLETADDRDIALOG_PROC)(HWND, HINSTANCE, LPTSTR, int); // NOTE: This is dumb. Wallet uses different GUIDs for Alpha and x86 versions // #ifdef _ALPHA_ static const TCHAR g_szWalletPaymentDirKey[] = TEXT("CLSID\\{B7FB4D5C-9FBE-11D0-8965-0000F822DEA9}\\InprocServer32"); static const TCHAR g_szWalletAddressDirKey[] = TEXT("CLSID\\{B7FB4D5C-9FBE-11D0-8965-0000F822DEA9}\\InprocServer32"); #else static const TCHAR g_szWalletPaymentDirKey[] = TEXT("CLSID\\{87D3CB66-BA2E-11CF-B9D6-00A0C9083362}\\InprocServer32"); static const TCHAR g_szWalletAddressDirKey[] = TEXT("CLSID\\{87D3CB63-BA2E-11CF-B9D6-00A0C9083362}\\InprocServer32"); #endif static const char g_szWalletPaymentFN[] = "DisplayWalletPaymentDialog"; static const char g_szWalletAddressFN[] = "DisplayWalletAddressDialog"; HINSTANCE GetWalletPaymentDProc(PFN_DISPLAYWALLETPAYDIALOG_PROC * ppfnDialogProc) { TCHAR szDLLFile[MAX_PATH]; DWORD dwType; DWORD dwSize = SIZEOF(szDLLFile); HINSTANCE hInst = NULL; *ppfnDialogProc = NULL; if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, g_szWalletPaymentDirKey, NULL, &dwType, (LPVOID)szDLLFile, &dwSize)) { hInst = LoadLibrary(szDLLFile); // Will Fail if OCX is not installed. if (hInst) { *ppfnDialogProc = (PFN_DISPLAYWALLETPAYDIALOG_PROC) GetProcAddress(hInst, g_szWalletPaymentFN); } } if (!*ppfnDialogProc && hInst) { FreeLibrary(hInst); hInst = NULL; } return hInst; } BOOL IsWalletPaymentAvailable(VOID) { HINSTANCE hInst; PFN_DISPLAYWALLETPAYDIALOG_PROC pfnDialogProc; BOOL fIsAvailable = FALSE; hInst = GetWalletPaymentDProc(&pfnDialogProc); if (hInst) { fIsAvailable = TRUE; FreeLibrary(hInst); } return fIsAvailable; } VOID DisplayWalletPaymentDialog(HWND hWnd) { HINSTANCE hInst; PFN_DISPLAYWALLETPAYDIALOG_PROC pfnDialogProc; hInst = GetWalletPaymentDProc(&pfnDialogProc); if (hInst) { (*pfnDialogProc)(hWnd, NULL, NULL, 0); FreeLibrary(hInst); } } HINSTANCE GetWalletAddressDProc(PFN_DISPLAYWALLETADDRDIALOG_PROC * ppfnDialogProc) { TCHAR szDLLFile[MAX_PATH]; DWORD dwType; DWORD dwSize = SIZEOF(szDLLFile); HINSTANCE hInst = NULL; *ppfnDialogProc = NULL; if (ERROR_SUCCESS == SHGetValue(HKEY_CLASSES_ROOT, g_szWalletAddressDirKey, NULL, &dwType, (LPVOID)szDLLFile, &dwSize)) { hInst = LoadLibrary(szDLLFile); // Will Fail if OCX is not installed. if (hInst) { *ppfnDialogProc = (PFN_DISPLAYWALLETADDRDIALOG_PROC) GetProcAddress(hInst, g_szWalletAddressFN); } } if (!*ppfnDialogProc && hInst) { FreeLibrary(hInst); hInst = NULL; } return hInst; } BOOL IsWallet3Installed() { HINSTANCE hInst; PFN_DISPLAYWALLETADDRDIALOG_PROC pfnDialogProc; BOOL fWallet3 = FALSE; hInst = GetWalletAddressDProc(&pfnDialogProc); if (hInst) { CHAR chPath[MAX_PATH]; if (GetModuleFileNameA(hInst, chPath, ARRAYSIZE(chPath))) { DWORD dwMSVer, dwLSVer; if (SUCCEEDED(GetVersionFromFile(chPath, &dwMSVer, &dwLSVer, TRUE))) { if (dwMSVer >= 3) { fWallet3 = TRUE; } } } FreeLibrary(hInst); } return fWallet3; } BOOL IsWalletAddressAvailable(VOID) { HINSTANCE hInst; PFN_DISPLAYWALLETADDRDIALOG_PROC pfnDialogProc; BOOL fIsAvailable = FALSE; hInst = GetWalletAddressDProc(&pfnDialogProc); if (hInst) { fIsAvailable = TRUE; FreeLibrary(hInst); } return fIsAvailable; } VOID DisplayWalletAddressDialog(HWND hWnd) { HINSTANCE hInst; PFN_DISPLAYWALLETADDRDIALOG_PROC pfnDialogProc; hInst = GetWalletAddressDProc(&pfnDialogProc); if (hInst) { (*pfnDialogProc)(hWnd, NULL, NULL, 0); FreeLibrary(hInst); } } #endif // WALLET // // // // "Programs" Tab // // // // // RegPopulateComboBox() // // Takes an open HKEY (hkeyProtocol) and populates hwndCB with the friendly // names of clients. The currently selected client is the "(default)" key of // hkeyProtocol. The clients are sub-keys under the open key. The friendly // names of the clients are in the "(default)" value of these sub-keys. This // function also makes the currently selected client the selected item in // hwndCB and returns the index number to the item. // // History: // // 7/ 8/96 t-gpease created // UINT RegPopulateComboBox(HWND hwndCB, HKEY hkeyProtocol) { TCHAR szFriendlyName [MAX_PATH]; TCHAR szKeyName [MAX_PATH]; TCHAR szCurrent [MAX_PATH]; TCHAR szFriendlyCurrent [MAX_PATH]; FILETIME ftLastWriteTime; DWORD i; // Index counter HKEY hkeyClient; DWORD cb; // find the currently selected client cb = sizeof(szCurrent); if (RegQueryValueEx(hkeyProtocol, NULL, NULL, NULL, (LPBYTE)szCurrent, &cb) != ERROR_SUCCESS) { // if not found then blank the friendly name and keyname. szCurrent[0]=0; szFriendlyCurrent[0]=0; } // populate the dropdown for(i=0; // always start with 0 cb=ARRAYSIZE(szKeyName), // string size ERROR_SUCCESS==RegEnumKeyEx(hkeyProtocol, i, szKeyName, &cb, NULL, NULL, NULL, &ftLastWriteTime); i++) // get next entry { // get the friendly name of the client if (RegOpenKeyEx(hkeyProtocol, szKeyName, 0, KEY_READ, &hkeyClient)==ERROR_SUCCESS) { cb = sizeof(szFriendlyName); if (RegQueryValueEx(hkeyClient, NULL, NULL, NULL, (LPBYTE)szFriendlyName, &cb) == ERROR_SUCCESS) { // add name to dropdown SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)szFriendlyName); // check to see if it's the current default if (!StrCmp(szKeyName, szCurrent)) { // save its the friendly name which we'll use later to // select the current client and what index it is. StrCpyN(szFriendlyCurrent, szFriendlyName, ARRAYSIZE(szFriendlyCurrent)); } } // close key RegCloseKey(hkeyClient); } } // for // select current client and get index number... just in case listboxes are sorted we // are doing this last. return (unsigned int) SendMessage(hwndCB, CB_SELECTSTRING, (WPARAM) 0, (LPARAM) szFriendlyCurrent); } // RegPopulateComboBox() // // Adds the item and its associated HKEY in the combobox. Stores the hkey // as data associated with the item. Frees hkey if the item is already present // or if an error occurs. // BOOL AddItemToEditorsCombobox ( HWND hwndCB, LPTSTR pszFriendlyName, // friendly name of the app HKEY hkey // location of assoc shell\edit verb ) { ASSERT(pszFriendlyName); ASSERT(hkey); BOOL fRet = FALSE; // Only add if not already in combo if (SendMessage(hwndCB, CB_FINDSTRINGEXACT, -1, (LPARAM)pszFriendlyName) == CB_ERR) { // Add name to dropdown INT_PTR i = SendMessage(hwndCB, CB_ADDSTRING, 0, (LPARAM)pszFriendlyName); if (i >= 0) { fRet = (SendMessage(hwndCB, CB_SETITEMDATA, i, (LPARAM)hkey) != CB_ERR); } } if (!fRet) { RegCloseKey(hkey); } return fRet; } // // Adds the edit verb to the OpenWithList associated with .htm files. // void AddToOpenWithList(LPCTSTR pszFriendly, HKEY hkeyFrom, HKEY hkeyOpenWithList) { ASSERT(pszFriendly); ASSERT(hkeyFrom); if (NULL == hkeyOpenWithList) { return; } TCHAR szBuf[MAX_PATH]; StrCpyN(szBuf, pszFriendly, ARRAYSIZE(szBuf)); StrCatBuff(szBuf, TEXT("\\shell\\edit"), ARRAYSIZE(szBuf)); DWORD dwDisposition; HKEY hkeyDest; if (hkeyOpenWithList && ERROR_SUCCESS == RegCreateKeyEx(hkeyOpenWithList, szBuf, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyDest, &dwDisposition)) { // Copy everything under shell if this item did not exist if (dwDisposition == REG_CREATED_NEW_KEY) { SHCopyKey(hkeyFrom, L"shell\\edit", hkeyDest, 0); } RegCloseKey(hkeyDest); } } // // Returns TRUE if the verb // BOOL IsHtmlStub ( HKEY hkeyVerb, // reg location of the shell\verb\command LPCWSTR pszVerb // verb to check for ("edit" or "open") ) { BOOL fRet = FALSE; // We don't display programs that are simple redirectors (such as Office's msohtmed.exe) TCHAR sz[MAX_PATH]; if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, hkeyVerb, pszVerb, sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz))))) { // Get the MULTISZ list of known redirectors TCHAR szRedir[MAX_PATH]; ZeroMemory(szRedir, sizeof(szRedir)); // Protect against non-multisz strings in the reg DWORD dwType; DWORD cb = sizeof(szRedir) - 4; if (ERROR_SUCCESS != SHGetValue(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, L"Stubs", &dwType, szRedir, &cb)) { // Nothing in registry, so default to ignore the Office redirector StrCpyN(szRedir, L"msohtmed.exe\0", ARRAYSIZE(szRedir)); } // Compare exe name with list of redirectors LPCTSTR pszFile = PathFindFileName(sz); for (LPTSTR p = szRedir; *p != NULL; p += lstrlen(p) + 1) { if (StrCmpI(p, pszFile) == 0) { fRet = TRUE; break; } } } return fRet; } BOOL GetAppKey(LPCWSTR pszApp, HKEY *phkApp) { ASSERT(pszApp && *pszApp); WCHAR szKey[MAX_PATH]; StrCpy(szKey, L"Applications\\"); StrCatBuff(szKey, pszApp, SIZECHARS(szKey)); return (NOERROR == RegOpenKeyEx( HKEY_CLASSES_ROOT, szKey, 0L, MAXIMUM_ALLOWED, phkApp)); } // // Adds the html editors to the combobox. Looks for edit verbs associated // with the .htm extension, the .htm OpenWithList, and the current default // editor. // void PopulateEditorsCombobox(HWND hwndCB) { // // Add items from the OpenWithList for .htm // DWORD dw; HKEY hkeyOpenWithList = NULL; TCHAR szOpenWith[MAX_PATH]; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CLASSES_ROOT, L".htm\\OpenWithList", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyOpenWithList, &dw)) { // // First enumerate the entries in the OpenWithList // HKEY hkeyOpenWith = NULL; DWORD dwIndex = 0; DWORD dwSize = ARRAYSIZE(szOpenWith); while (ERROR_SUCCESS == RegEnumKeyEx(hkeyOpenWithList, dwIndex, szOpenWith, &dwSize, NULL, NULL, NULL, NULL)) { if (GetAppKey(szOpenWith, &hkeyOpenWith)) { // We only accept items that have an edit verb TCHAR sz[MAX_PATH]; if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, hkeyOpenWith, L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz))))) { // Note that we store hkeyOpenWith in the combo so don't close it AddItemToEditorsCombobox(hwndCB, sz, hkeyOpenWith); } else { RegCloseKey(hkeyOpenWith); } } ++dwIndex; dwSize = ARRAYSIZE(szOpenWith); } // hkeyOpenWithList is closed below } // // Add the editor associated with .htm // HKEY hkeyHtm; // FEATURE - should use AssocCreate(IQueryAssociations) here instead if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, L".htm", NULL, &hkeyHtm))) { TCHAR sz[MAX_PATH]; if (!IsHtmlStub(hkeyHtm, L"edit") && SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, hkeyHtm, L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz))))) { AddItemToEditorsCombobox(hwndCB, sz, hkeyHtm); AddToOpenWithList(sz, hkeyHtm, hkeyOpenWithList); // Don't free the key we cached away hkeyHtm = NULL; } if (hkeyHtm) { RegCloseKey(hkeyHtm); } } // // Get the default editor. We check both hkcu & hklm. // HKEY hkeyDefault; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyDefault) || ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, KEY_READ, &hkeyDefault)) { TCHAR sz[MAX_PATH]; if (SUCCEEDED(AssocQueryStringByKey(ASSOCF_VERIFY, ASSOCSTR_FRIENDLYAPPNAME, hkeyDefault, L"edit", sz, (LPDWORD)MAKEINTRESOURCE(SIZECHARS(sz))))) { // Add name to dropdown and save hkeyDefault in the combobox (so don't close it) AddItemToEditorsCombobox(hwndCB, sz, hkeyDefault); // Select this item SendMessage(hwndCB, CB_SELECTSTRING, -1, (LPARAM)sz); // // Make sure the default editor is in the htm OpenWithList so it doesn't dissapear // if we change it // AddToOpenWithList(sz, hkeyDefault, hkeyOpenWithList); } else { RegCloseKey(hkeyDefault); } } if (hkeyOpenWithList) { RegCloseKey(hkeyOpenWithList); } } // // ProgramsDlgInit() // // Does initalization for Programs Dlg. // // History: // // 6/17/96 t-gpease created // 7/ 8/96 t-gpease added Mail and News initialization // BOOL ProgramsDlgInit( HWND hDlg) { LPPROGRAMSPAGE pPrg; DWORD dw; HKEY hkey; pPrg = (LPPROGRAMSPAGE)LocalAlloc(LPTR, sizeof(*pPrg)); if (!pPrg) { EndDialog(hDlg, 0); return FALSE; // no memory? } // tell dialog where to get info SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)pPrg); // save the handle to the page pPrg->hDlg = hDlg; // // Set default values. // pPrg->bAssociationCheck = TRUE; // we want everybody to use IE! SUCCEEDED(CoCreateInstance(CLSID_FtpInstaller, NULL, CLSCTX_INPROC_SERVER, IID_IFtpInstaller, (void **) &pPrg->pfi)); if (pPrg->pfi) pPrg->bIEIsFTPClient = ((S_OK == pPrg->pfi->IsIEDefautlFTPClient()) ? TRUE : FALSE); pPrg->iMail = -1; // nothing selected pPrg->iNews = -1; // nothing selected pPrg->bAssociationCheck = SHRegGetBoolUSValue(REGSTR_PATH_MAIN,REGSTR_VAL_CHECKASSOC,FALSE,TRUE); // // Get the html editors // pPrg->hwndHtmlEdit = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_HTMLEDITOR_COMBO); PopulateEditorsCombobox(pPrg->hwndHtmlEdit); // Sundown: coercion to int because 32b is sufficient for cursor selection pPrg->iHtmlEditor = (int) SendMessage(pPrg->hwndHtmlEdit, CB_GETCURSEL, 0, 0); // // Get the Mail Clients // pPrg->hwndMail = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_MAIL_COMBO); if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_MAILCLIENTS, 0, NULL, 0, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // populate the combobox pPrg->iMail = RegPopulateComboBox(pPrg->hwndMail, hkey); // close the keys RegCloseKey(hkey); } // // Get the News Clients // pPrg->hwndNews = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_NEWS_COMBO); if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_NEWSCLIENTS, 0, NULL, 0, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // populate the combobox pPrg->iNews = RegPopulateComboBox(pPrg->hwndNews, hkey); // close the keys RegCloseKey(hkey); } // // get the calendar clients // pPrg->hwndCalendar = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_CALENDAR_COMBO); if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CALENDARCLIENTS, 0, NULL, 0, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // populate the combobox pPrg->iCalendar = RegPopulateComboBox(pPrg->hwndCalendar, hkey); // close the keys RegCloseKey(hkey); } // // get the contacts clients // pPrg->hwndContact = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_CONTACT_COMBO); if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CONTACTCLIENTS, 0, NULL, 0, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // populate the combobox pPrg->iContact = RegPopulateComboBox(pPrg->hwndContact, hkey); // close the keys RegCloseKey(hkey); } // // get the internet call clients // pPrg->hwndCall = GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_CALL_COMBO); if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_CALLCLIENTS, 0, NULL, 0, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // populate the combobox pPrg->iCall = RegPopulateComboBox(pPrg->hwndCall, hkey); // close the keys RegCloseKey(hkey); } // Set dialog items CheckDlgButton(hDlg, IDC_CHECK_ASSOCIATIONS_CHECKBOX, pPrg->bAssociationCheck); HRESULT hrIEDefaultFTPClient = E_FAIL; if (pPrg->pfi) { hrIEDefaultFTPClient = pPrg->pfi->IsIEDefautlFTPClient(); // Is this option not applicable because only the IE FTP client is installed? if (SUCCEEDED(hrIEDefaultFTPClient)) CheckDlgButton(hDlg, IDC_PROGRAMS_IE_IS_FTPCLIENT, pPrg->bIEIsFTPClient); } if (FAILED(hrIEDefaultFTPClient)) { // Yes, so remove the option. ShowWindow(GetDlgItem(hDlg, IDC_PROGRAMS_IE_IS_FTPCLIENT), SW_HIDE); } if( g_restrict.fMailNews ) { EnableWindow( GetDlgItem(hDlg, IDC_PROGRAMS_MAIL_COMBO), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_PROGRAMS_NEWS_COMBO), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_PROGRAMS_CALL_COMBO), FALSE); } if ( g_restrict.fCalContact ) { EnableWindow( GetDlgItem(hDlg, IDC_PROGRAMS_CALENDAR_COMBO), FALSE); EnableWindow( GetDlgItem(hDlg, IDC_PROGRAMS_CONTACT_COMBO), FALSE); } EnableWindow( GetDlgItem(hDlg, IDC_RESETWEBSETTINGS), !g_restrict.fResetWebSettings ); EnableWindow( GetDlgItem(hDlg, IDC_CHECK_ASSOCIATIONS_CHECKBOX), !g_restrict.fDefault ); return TRUE; // success } // ProgramsDlgInit() // // RegCopyKey() // // Copies all the keys from hkeySrc down into hkeyRoot:pszDest. // // History: // // 7/ 8/96 t-gpease created // void RegCopyKey(HKEY hkeyRoot, const TCHAR *pszDest, HKEY hkeySrc) { HKEY hkeyDest; HKEY hkey; DWORD dw; DWORD i; DWORD cb; DWORD cbData; DWORD Type; TCHAR szName[MAX_PATH]; TCHAR szData[MAX_URL_STRING+1]; // open/create the destination key if (RegCreateKeyEx(hkeyRoot, pszDest, NULL, 0, NULL, KEY_READ|KEY_WRITE, NULL, &hkeyDest, &dw) == ERROR_SUCCESS) { i=0; // copy values of the key while(1) { // find next value cb=ARRAYSIZE(szName); cbData=sizeof(szData); if (RegEnumValue(hkeySrc, i, szName, &cb, NULL, &Type, (LPBYTE)&szData, &cbData)!=ERROR_SUCCESS) break; // not found... exit loop // make a copy of the value in new location RegSetValueEx(hkeyDest, szName, NULL, Type, (CONST BYTE *)szData, cbData); // increase index count i++; } // while // look for more sub-keys in the source for(i=0; cb=ARRAYSIZE(szName), RegEnumKey(hkeySrc, i, szName, cb)==ERROR_SUCCESS; i++) { // open the sub-key if (RegCreateKeyEx(hkeySrc, szName, NULL, 0, NULL, KEY_READ, NULL, &hkey, &dw) == ERROR_SUCCESS) { // copy the sub-key RegCopyKey(hkeyDest, szName, hkey); // close the key RegCloseKey(hkey); } // if RegCreateKey() } // for // close the key RegCloseKey(hkeyDest); } // if RegCreateKey() } // RegCopyKey() // // CopyInfoTo() // // Copies the information needed to run a mailto: or news: protocol // // History: // // 7/ 8/96 t-gpease created // void CopyInfoTo(const TCHAR *pszKeyName, HKEY hkeyClient) { HKEY hkey; TCHAR szName[MAX_PATH]; // create the protocol sub-key path StrCpyN(szName, TSZPROTOCOLSPATH, ARRAYSIZE(szName)); int len = lstrlen(szName); StrCpyN(szName + len, pszKeyName, ARRAYSIZE(szName) - len); // make sure it has the protocol we are looking for if (RegOpenKeyEx(hkeyClient, szName, NULL, KEY_READ|KEY_WRITE, &hkey) ==ERROR_SUCCESS) { // Netscape Messenger registry patch: they are missing "URL Protocol" in the HKLM mailto branch // and we should set this value, otherwise we get the 68992 bug. The source is changed rather // than the destination to protect against other programs copying the tree without the value. // Might as well check this for all clients rather than look for Netscape, since we don't // change any data if it exists. if (lstrcmpi(pszKeyName, TSZMAILTOPROTOCOL) == 0 && RegQueryValueEx(hkey, TEXT("URL Protocol"), NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { RegSetValueEx(hkey, TEXT("URL Protocol"), 0, REG_SZ, (BYTE *) TEXT(""), sizeof(TCHAR)); } // start by deleting all the old info if ( lstrcmpi(pszKeyName, TSZLDAPPROTOCOL) ) SHDeleteKey(HKEY_CLASSES_ROOT, pszKeyName); // recreate key and copy the protocol info RegCopyKey(HKEY_CLASSES_ROOT, pszKeyName, hkey); // close the key RegCloseKey(hkey); } // if RegOpenKey() } // CopyInfoTo() // // FindClient() // // Finds the currently selected item in hwndComboBox and locates it // in the szPath's subkeys. If found it will then make a call to copy // the information to szProtocol key under HKCR. // // History: // // 7/ 8/96 t-gpease created // void FindClient(LPCTSTR szProtocol, HWND hwndComboBox, int iSelected, LPCTSTR szPath) { TCHAR szFriendlyName[MAX_PATH]; TCHAR szKeyName[MAX_PATH]; TCHAR szCurrent[MAX_PATH]; FILETIME ftLastWriteTime; DWORD i; // Index counter HKEY hkeyClient; HKEY hkey; DWORD dw; // get the name of the new client if (CB_ERR!=SendMessage(hwndComboBox, CB_GETLBTEXT, (WPARAM)iSelected, (LPARAM)szCurrent)) { // got the friendly name... now lets find the internal name if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, NULL, 0, KEY_READ|KEY_WRITE, NULL, &hkey, &dw) == ERROR_SUCCESS) { DWORD cb; // we must search all the sub-keys for the correct friendly name for(i=0; // always start with 0 cb=ARRAYSIZE(szKeyName), // string size ERROR_SUCCESS==RegEnumKeyEx(hkey, i, szKeyName, &cb, NULL, NULL, NULL, &ftLastWriteTime); i++) // get next entry { // get more info on the entry if (RegOpenKeyEx(hkey, szKeyName, 0, KEY_READ, &hkeyClient)==ERROR_SUCCESS) { // get the friendly name of the client cb = sizeof(szFriendlyName); if (RegQueryValueEx(hkeyClient, NULL, NULL, NULL, (LPBYTE)szFriendlyName, &cb) == ERROR_SUCCESS) { // is it the one we are looking for? if (!StrCmp(szFriendlyName, szCurrent)) { // yep... copy its info CopyInfoTo(szProtocol, hkeyClient); // make it the default handler cb = (lstrlen(szKeyName) + 1)*sizeof(TCHAR); RegSetValueEx(hkey, NULL, NULL, REG_SZ, (LPBYTE)szKeyName, cb); } } // close key RegCloseKey(hkeyClient); } // if RegOpenKey() } // for // close the keys RegCloseKey(hkey); } // if RegCreateKeyEx() } } // FindClient() // // ProgramsDlgApplyNow() // // Enters "Programs" changes into registry. // // History: // // 6/20/96 t-gpease created // 7/ 8/96 t-gpease added Mail and News // void ProgramsDlgApplyNow(LPPROGRAMSPAGE pPrg) { int tmp; if (pPrg->fChanged) { // Did the user have a chance to change this option? if (pPrg->pfi) { HRESULT hrIEDefaultFTPClient = pPrg->pfi->IsIEDefautlFTPClient(); if (IsWindowVisible(GetDlgItem(pPrg->hDlg, IDC_PROGRAMS_IE_IS_FTPCLIENT))) { // Yes, so see if they changed it. pPrg->bIEIsFTPClient = IsDlgButtonChecked(pPrg->hDlg, IDC_PROGRAMS_IE_IS_FTPCLIENT); // Did they user want IE as default and currently someone else is? if (pPrg->bIEIsFTPClient && (S_FALSE == hrIEDefaultFTPClient)) pPrg->pfi->MakeIEDefautlFTPClient(); // Did they user NOT want IE as default and it currently is? if (!pPrg->bIEIsFTPClient && (S_OK == hrIEDefaultFTPClient)) pPrg->pfi->RestoreFTPClient(); } } pPrg->bAssociationCheck = IsDlgButtonChecked(pPrg->hDlg, IDC_CHECK_ASSOCIATIONS_CHECKBOX); TCHAR szYesNo[5]; StrCpyN(szYesNo, (pPrg->bAssociationCheck ? TEXT("yes") : TEXT("no")), ARRAYSIZE(szYesNo)); SHRegSetUSValue(REGSTR_PATH_MAIN, REGSTR_VAL_CHECKASSOC, REG_SZ, (LPVOID)szYesNo, (lstrlen(szYesNo)+1)*sizeof(TCHAR), SHREGSET_DEFAULT); // // Save the new default editor // // See if the selection was changed tmp = (int) SendMessage(pPrg->hwndHtmlEdit, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iHtmlEditor) { pPrg->iHtmlEditor = tmp; // Get the text and hkey for the selected item WCHAR szDefault[MAX_PATH]; SendMessage(pPrg->hwndHtmlEdit, CB_GETLBTEXT, tmp, (LPARAM)szDefault); HKEY hkeyFrom = (HKEY)SendMessage(pPrg->hwndHtmlEdit, CB_GETITEMDATA, tmp, 0); if (hkeyFrom && (INT_PTR)hkeyFrom != CB_ERR) { // // Save the selected item as the default editor // DWORD dw; HKEY hkeyDest; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, REGSTR_PATH_DEFAULT_HTML_EDITOR, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyDest, &dw)) { // Update the name of the default editor SHSetValue(hkeyDest, NULL, L"Description", REG_SZ, szDefault, CbFromCch(lstrlen(szDefault)+1)); // Delete the old shell command (and all subkeys). This purges keys such as DDEEXEC. SHDeleteKey(hkeyDest, L"shell"); // Update the verb of the default editor HKEY hkeyEdit; if (ERROR_SUCCESS == RegCreateKeyEx(hkeyDest, L"shell\\edit", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyEdit, &dw)) { SHCopyKey(hkeyFrom, L"shell\\edit", hkeyEdit, 0); RegCloseKey(hkeyEdit); } RegCloseKey(hkeyDest); } // // Also update Office's default editor // if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Shared\\HTML\\Default Editor", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyDest, &dw)) { // Delete the old shell command (and all subkeys). This purges keys such as DDEEXEC. SHDeleteKey(hkeyDest, L"shell\\edit"); // Update the verb of the default editor HKEY hkeyEdit; if (ERROR_SUCCESS == RegCreateKeyEx(hkeyDest, L"shell\\edit", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyEdit, &dw)) { SHCopyKey(hkeyFrom, L"shell\\edit", hkeyEdit, 0); RegCloseKey(hkeyEdit); } RegCloseKey(hkeyDest); } // // Finally, update the edit verb for .htm files so that the shell honors the change. // But if .htm uses a stub like moshtmed, we leave it alone and assume that it // uses one of the above keys as the default editor. // HKEY hkeyHtm; if (SUCCEEDED(AssocQueryKey(0, ASSOCKEY_SHELLEXECCLASS, L".htm", NULL, &hkeyHtm))) { if (!IsHtmlStub(hkeyHtm, L"edit")) { // Delete the old shell command (and all subkeys). This purges keys such as DDEEXEC. SHDeleteKey(hkeyHtm, L"shell\\edit"); // Copy the edit verb to the .htm HKEY hkeyEdit; if (ERROR_SUCCESS == RegCreateKeyEx(hkeyHtm, L"shell\\edit", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &hkeyEdit, &dw)) { SHCopyKey(hkeyFrom, L"shell\\edit", hkeyEdit, 0); RegCloseKey(hkeyEdit); } } RegCloseKey(hkeyHtm); } } } // // Save Mail Client Info // // is there a new client? tmp = (int) SendMessage(pPrg->hwndMail, CB_GETCURSEL, 0, 0); if (tmp!=pPrg->iMail) { pPrg->iMail = tmp; // find it and copy its info FindClient(TSZMAILTOPROTOCOL, pPrg->hwndMail, tmp, REGSTR_PATH_MAILCLIENTS); //Update the mail icon label UpdateMailIconLabel(); // tell the world that something has changed SendBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_MAILCLIENTS); } // // Save News Client Info // // is there a new client? tmp = (int) SendMessage(pPrg->hwndNews, CB_GETCURSEL, 0, 0); if (tmp!=pPrg->iNews) { pPrg->iNews = tmp; // find it and copy its info FindClient(TSZNEWSPROTOCOL, pPrg->hwndNews, tmp, REGSTR_PATH_NEWSCLIENTS); FindClient(TEXT("snews"), pPrg->hwndNews, tmp, REGSTR_PATH_NEWSCLIENTS); FindClient(TEXT("nntp"), pPrg->hwndNews, tmp, REGSTR_PATH_NEWSCLIENTS); // tell the world that something has changed SendBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_NEWSCLIENTS); } // // Save Internet Call Client info // // is there a new client? tmp = (int) SendMessage(pPrg->hwndCall, CB_GETCURSEL, 0, 0); if (tmp!=pPrg->iCall) { pPrg->iCall = tmp; // find it and copy its info FindClient(TSZCALLTOPROTOCOL, pPrg->hwndCall, tmp, REGSTR_PATH_CALLCLIENTS); // tell the world that something has changed SendBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_CALLCLIENTS); } // // Save Contacts Client Info // // is there a new client? tmp = (int) SendMessage(pPrg->hwndContact, CB_GETCURSEL, 0, 0); if (tmp!=pPrg->iContact) { pPrg->iContact = tmp; // find it and copy its info FindClient(TSZLDAPPROTOCOL, pPrg->hwndContact, tmp, REGSTR_PATH_CONTACTCLIENTS); // tell the world that something has changed SendBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_CONTACTCLIENTS); } // // Save Calendar Client Info // // is there a new client? tmp = (int) SendMessage(pPrg->hwndCalendar, CB_GETCURSEL, 0, 0); if (tmp!=pPrg->iCalendar) { pPrg->iCalendar = tmp; // find it and copy its info FindClient(TSZCALENDARPROTOCOL, pPrg->hwndCalendar, tmp, REGSTR_PATH_CALENDARCLIENTS); // tell the world that something has changed SendBroadcastMessage(WM_WININICHANGE, 0, (LPARAM)REGSTR_PATH_CALENDARCLIENTS); } UpdateAllWindows(); pPrg->fChanged = FALSE; } } // ProgramsDlgApplyNow() extern HRESULT ResetWebSettings(HWND hwnd, BOOL *pfChangedHomePage); // // ProgramsOnCommand() // // Handles "Programs" property page's window commands // // History: // // 6/20/96 t-gpease created // void ProgramsOnCommand(LPPROGRAMSPAGE pPrg, UINT id, UINT nCmd) { switch (id) { case IDC_PROGRAMS_HTMLEDITOR_COMBO: { INT_PTR tmp; // Is there a new editor? tmp = SendMessage(pPrg->hwndHtmlEdit, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iHtmlEditor) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_PROGRAMS_NEWS_COMBO: { INT_PTR tmp; // is there a new client? tmp = SendMessage(pPrg->hwndNews, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iNews) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_PROGRAMS_MAIL_COMBO: { INT_PTR tmp; // is there a new client? tmp = SendMessage(pPrg->hwndMail, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iMail) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_PROGRAMS_CALENDAR_COMBO: { INT_PTR tmp; // is there a new client? tmp = SendMessage(pPrg->hwndCalendar, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iCalendar) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_PROGRAMS_CONTACT_COMBO: { INT_PTR tmp; // is there a new client? tmp = SendMessage(pPrg->hwndContact, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iContact) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_PROGRAMS_CALL_COMBO: { INT_PTR tmp; // is there a new client? tmp = SendMessage(pPrg->hwndCall, CB_GETCURSEL, 0, 0); if (tmp != pPrg->iCall) { ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; } } break; case IDC_RESETWEBSETTINGS: { BOOL fReloadHomePage; ResetWebSettings(pPrg->hDlg,&fReloadHomePage); if (fReloadHomePage) g_fReloadHomePage = TRUE; } break; case IDC_PROGRAMS_IE_IS_FTPCLIENT: case IDC_CHECK_ASSOCIATIONS_CHECKBOX: ENABLEAPPLY(pPrg->hDlg); pPrg->fChanged = TRUE; break; } // switch } // ProgramsOnCommand() // // ProgramsDlgProc() // // Handles window messages sent to the Programs Property Sheet. // // History: // // 6/20/96 t-gpease created // INT_PTR CALLBACK ProgramsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPPROGRAMSPAGE pPrg; if (uMsg == WM_INITDIALOG) return ProgramsDlgInit( hDlg ); else pPrg= (LPPROGRAMSPAGE) GetWindowLongPtr(hDlg, DWLP_USER); if (!pPrg) return FALSE; switch (uMsg) { case WM_COMMAND: ProgramsOnCommand(pPrg, LOWORD(wParam), HIWORD(wParam)); return TRUE; case WM_NOTIFY: { NMHDR *lpnm = (NMHDR *) lParam; ASSERT(lpnm); switch (lpnm->code) { case PSN_KILLACTIVE: case PSN_QUERYCANCEL: case PSN_RESET: SetWindowLongPtr(hDlg, DWLP_MSGRESULT, FALSE); return TRUE; case PSN_APPLY: // // Save Programs Dlg Stuff. // ProgramsDlgApplyNow(pPrg); break; } } break; case WM_HELP: // F1 ResWinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle, IDS_HELPFILE, HELP_WM_HELP, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_CONTEXTMENU: // right mouse click ResWinHelp( (HWND) wParam, IDS_HELPFILE, HELP_CONTEXTMENU, (DWORD_PTR)(LPSTR)mapIDCsToIDHs); break; case WM_DESTROY: { // Free the data stored the HTML editor combo int iMax = (int) SendMessage(pPrg->hwndHtmlEdit, CB_GETCOUNT, 0, 0); HKEY hkey; for (int i = 0; i < iMax; ++i) { hkey = (HKEY) SendMessage(pPrg->hwndHtmlEdit, CB_GETITEMDATA, i, 0); if (hkey && (INT_PTR)hkey != CB_ERR) { RegCloseKey(hkey); } } if (pPrg) { if (pPrg->pfi) pPrg->pfi->Release(); LocalFree(pPrg); } SetWindowLongPtr(hDlg, DWLP_USER, (LONG)NULL); break; } } return FALSE; } static const TCHAR c_szMailIcon[] = TEXT("Software\\Microsoft\\MailIcon"); static const TCHAR c_szMailIconGuid[] = TEXT("CLSID\\{dacf95b0-0a3f-11d1-9389-006097d503d9}"); static const TCHAR c_szKeyMail[] = TEXT("Software\\Clients\\Mail"); static const TCHAR c_szRegFmt2[] = TEXT("%s\\%s"); static const TCHAR c_szFormatClient[] = TEXT("FormatClient"); static const TCHAR c_szFormatNoClient[] = TEXT("FormatNoClient"); static WCHAR c_wszMailIconGuid[] = L"::{dacf95b0-0a3f-11d1-9389-006097d503d9}"; void UpdateMailIconLabel() { TCHAR szOldLabel[MAX_PATH]; TCHAR szNewLabel[MAX_PATH]; TCHAR szDefClient[MAX_PATH]; TCHAR szTemp[MAX_PATH]; DWORD cbSize; HKEY hKey; *szNewLabel = 0; *szOldLabel = 0; // check if the mail icon is even installed if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szMailIcon, 0, KEY_READ, &hKey)) { cbSize = sizeof(szOldLabel); // get the current mail icon label if (ERROR_SUCCESS == RegQueryValue(HKEY_CLASSES_ROOT, c_szMailIconGuid, szOldLabel, (PLONG)&cbSize)) { cbSize = sizeof(szDefClient); // get the default client's reg key if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, c_szKeyMail, szDefClient, (PLONG)&cbSize) && cbSize) { wnsprintf(szTemp, ARRAYSIZE(szTemp), c_szRegFmt2, c_szKeyMail, szDefClient); cbSize = sizeof(szDefClient); // get the default client's display name if (ERROR_SUCCESS == RegQueryValue(HKEY_LOCAL_MACHINE, szTemp, szDefClient, (PLONG)&cbSize) && cbSize) { cbSize = sizeof(szTemp); // get the mail icon label format string if (ERROR_SUCCESS == RegQueryValueEx(hKey, c_szFormatClient, 0, NULL, (LPBYTE)szTemp, &cbSize)) { wnsprintf(szNewLabel, ARRAYSIZE(szNewLabel), szTemp, szDefClient); } } } else { cbSize = sizeof(szNewLabel); // get the mail icon label format string RegQueryValueEx(hKey, c_szFormatNoClient, 0, NULL, (LPBYTE)szNewLabel, &cbSize); } } // if the above succeeded, and the label is different if (*szNewLabel && StrCmp(szNewLabel, szOldLabel)) { IShellFolder *psf; // set the new label RegSetValue(HKEY_CLASSES_ROOT, c_szMailIconGuid, REG_SZ, szNewLabel, (lstrlen(szNewLabel)+1)*sizeof(TCHAR)); // let the shell know that it changed if (SUCCEEDED(SHGetDesktopFolder(&psf))) { LPITEMIDLIST pidl; ULONG chEaten; if (SUCCEEDED(psf->ParseDisplayName(NULL, NULL, c_wszMailIconGuid, &chEaten, &pidl, NULL))) { SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_IDLIST, pidl, NULL); SHFree(pidl); } psf->Release(); } } RegCloseKey(hKey); } }