//+------------------------------------------------------------------------- // // Microsoft Windows // // Copyright (C) Microsoft Corporation, 2000 // // File: cpnamespc.cpp // // This is a rather large module but it's not all that difficult. The // primary purpose is to provide the 'data' associated with the new // 'categorized' Control Panel user interface. Therefore, the visual // work is done in cpview.cpp and the data is provided by cpnamespc.cpp. // Through the implementation of ICplNamespace, the 'view' object obtains // it's display information. All of this 'namespace' information is // defined and made accessible through this module. // // The 'namespace' can be broken down into these concepts: // // 1. Links - title, icon & infotip // 2. Actions // 3. Restrictions // // Each link has a title, icon, infotip and an associated action. The // action is 'invoked' when the user selects the link in the user interface. // Actions may optionally be associated with a 'restriction'. If a // restriction is enforced (usually based on some system state) the // link associated with the action that is associated with the restriction // is not made available to the user interface. Using this indirection // mechanism, any link related to a restricted action is not displayed. // // At first glance one might be concerned with the amount of global data // used (and being initialized). Note however that all of the information // is defined as constant such that it can be resolved at compile and link // time. Several goals drove the design of this module: // // 1. Easy maintenance of Control Panel content. It must be easy // to add/remove/modify links in the UI. // // 2. Fast initialization. Everything is defined as constant data. // // 3. Logical separation of links, actions and restrictions // to facilitate the one-to-many and many-to-many relationships // that might occur in the namespace. // // Following the namespace initialization code, the remainder of the // module implements ICplNamespace to make the data available to the view // in a COM-friendly way. // //-------------------------------------------------------------------------- #include "shellprv.h" #include #include #include "cpviewp.h" #include "cpaction.h" #include "cpguids.h" #include "cpnamespc.h" #include "cpuiele.h" #include "cputil.h" #include "ids.h" #include "securent.h" #include "prop.h" // // These icons are currently all the same image. // Use separate macro names in the code in case the designers // decide to use different icons for one or more. // #define IDI_CPTASK_SEEALSO IDI_CPTASK_ASSISTANCE #define IDI_CPTASK_TROUBLESHOOTER IDI_CPTASK_ASSISTANCE #define IDI_CPTASK_HELPANDSUPPORT IDI_CPTASK_ASSISTANCE #define IDI_CPTASK_LEARNABOUT IDI_CPTASK_ASSISTANCE namespace CPL { typedef CDpa > CDpaItemIDList; typedef CDpa > CDpaUiCommand; // // WebView info type enumeration. // enum eCPWVTYPE { eCPWVTYPE_CPANEL, // The 'Control Panel' item. eCPWVTYPE_SEEALSO, // The 'See Also' list. eCPWVTYPE_TROUBLESHOOT, // The 'Troubleshooters' list. eCPWVTYPE_LEARNABOUT, // The 'Learn About' list. eCPWVTYPE_NUMTYPES }; // // Define the SCID identifying the control panel category. // DEFINE_SCID(SCID_CONTROLPANELCATEGORY, PSGUID_CONTROLPANEL, PID_CONTROLPANEL_CATEGORY); //----------------------------------------------------------------------------- // Resource source classes // // The purpose of this trivial class is to abstract away the implementation // of obtaining a resource identifier. The reason for this comes from needing // different text resources (i.e. infotips) for different retail SKUs. // For example, on Personal SKU, the Users & Passwords applet provides the // ability to associate a picture with a user's account. On Server, it // does not. Therefore, the infotip on Personal can include text about // the user's picture while on Server it cannot. By introducing this level // of abstraction, we can provide resource information through a resource // function that can select the appropriate resource at runtime. Most // links will still use fixed resources but with this abstraction, the calling // code is none the wiser. //----------------------------------------------------------------------------- // // Resource source function must return an LPCWSTR for the resource. // typedef LPCWSTR (*PFNRESOURCE)(ICplNamespace *pns); class IResSrc { public: virtual LPCWSTR GetResource(ICplNamespace *pns) const = 0; }; class CResSrcStatic : public IResSrc { public: CResSrcStatic(LPCWSTR pszResource) : m_pszResource(pszResource) { } LPCWSTR GetResource(ICplNamespace *pns) const { UNREFERENCED_PARAMETER(pns); TraceMsg(TF_CPANEL, "CResSrc::GetResource - m_pszResource = 0x%08X", m_pszResource); return m_pszResource; } private: const LPCWSTR m_pszResource; }; class CResSrcFunc : public IResSrc { public: CResSrcFunc(PFNRESOURCE pfnResource) : m_pfnResource(pfnResource) { } LPCWSTR GetResource(ICplNamespace *pns) const { TraceMsg(TF_CPANEL, "CResSrcFunc::GetResource - m_pfnResource = 0x%08X", m_pfnResource); return (*m_pfnResource)(pns); } private: const PFNRESOURCE m_pfnResource; }; // // This resource type represents "no resource". It simply // returns a NULL value when the resource is requested. Clients // that call this must be ready to handle this NULL pointer // value. It was originally created to handle the no-tooltip // behavior of Learn-About links. // class CResSrcNone : public IResSrc { public: CResSrcNone(void) { } LPCWSTR GetResource(ICplNamespace *pns) const { UNREFERENCED_PARAMETER(pns); return NULL; } }; // ---------------------------------------------------------------------------- // Information describing links. // ---------------------------------------------------------------------------- // // // 'Link' descriptor. // struct CPLINK_DESC { const IResSrc *prsrcIcon; // Icon resource identifier const IResSrc *prsrcName; // The link's title resource ID. const IResSrc *prsrcInfotip; // The link's infotip resource ID. const IAction *pAction; // The link's action when clicked. }; // // Set of 'support' links. // struct CPLINK_SUPPORT { const CPLINK_DESC **ppSeeAlsoLinks; // 'See Also' links for the category. const CPLINK_DESC **ppTroubleshootLinks; // 'Troubleshoot' links for the category. const CPLINK_DESC **ppLearnAboutLinks; // 'Learn About' links for the category. }; // // 'Category' descriptor. One defined for each category. // struct CPCAT_DESC { eCPCAT idCategory; // The category's ID. LPCWSTR pszHelpSelection; // Selection part of HSS help URL. const CPLINK_DESC *pLink; // The category's display info and action const CPLINK_DESC **ppTaskLinks; // The category's task list. CPLINK_SUPPORT slinks; // Support links. }; // ---------------------------------------------------------------------------- // Restrictions // // Restrictions are an important part of the control panel display logic. // Each link element in the UI can be restricted from view based on one or // more system conditions at the time of display. To ensure the correct // logic is used, it is critical to have a method of describing these restrictions // that is easily readable and verifiable against a specification. Testing // all of the possible scenarios is a difficult task, therefore the code must // be written in a manner conducive to finding errors by inspection as well. // This means, keep it simple. Each link action object can be optionally associated // with a 'restriction' object. Restriction objects implement CPL::IRestrict. // The most common restriction object CRestrictFunc simply calls a function // provided to the object's constructor. The function is called when the // restriction status (restricted/allowed) is desired. There is also // class CRestrictApplet for tasks who's presence is directly linked to // the presence/restriction of a particular CPL applet based on policy alone. // // Since there may be many task links on a given Control Panel page that // means there will be multiple restriction expressions evaluated each // time the page is displayed. Often the expressions across a set of // actions are evaluating many of the same terms. Some of these terms require // registry lookups. To help performance, a simple caching mechanism // has been introduced into the 'namespace' object. Each restriction function // is passed a pointer to the current 'namespace' object. As the namespace // object remains alive the entire time the page is being constructed, it // is an appropriate place to cache frequently used data. You'll see // many instances below where the namespace object is queried for restriction // data. The members of the namespace object associated with this restriction // data are of type CTriState. This simple class implements the concept of // an 'uninitialized boolean' value, allowing the code to determine if a given // boolean member has yet to be initialized with a valid boolean value. If // the namespace is asked for the value of one of these tri-state booleans // and that member has not yet been initialized, the namespace calls the // appropriate system functions and initializes the boolean value. From that // time forward, the member's value is returned immediately. This ensures that // for any given restriction term, we do the expensive stuff only once. // Being an on-demand mechanism, we also gather only the information that is // needed. // // [brianau - 03/18/01] // HRESULT Restrict32CtrlPanel(ICplNamespace *pns) { HRESULT hr = S_FALSE; #if !defined(_WIN64) hr = S_OK; // restricted. #endif return hr; } HRESULT RestrictAlways(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); return S_OK; // Always restricted. } HRESULT RestrictDisplayCpl(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowDeskCpl()) { hr = S_OK; } return hr; } HRESULT RestrictThemes(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowDeskCpl() || SHRestricted(REST_NOTHEMESTAB) || SHRestricted(REST_NODISPLAYAPPEARANCEPAGE)) { hr = S_OK; } return hr; } HRESULT RestrictWallpaper(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowDeskCpl() || SHRestricted(REST_NOCHANGINGWALLPAPER) || !pns->AllowDeskCplTab_Background()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictScreenSaver(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowDeskCpl() || !pns->AllowDeskCplTab_Screensaver()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictResolution(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowDeskCpl() || !pns->AllowDeskCplTab_Settings()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictAddPrinter(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; if (SHRestricted(REST_NOPRINTERADD) || !IsAppletEnabled(NULL, MAKEINTRESOURCEW(IDS_PRNANDFAXFOLDER))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictRemoteDesktop(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->IsUserAdmin() || // Admins only. pns->IsPersonal() || // Not available on personal. !IsAppletEnabled(L"sysdm.cpl", MAKEINTRESOURCEW(IDS_CPL_SYSTEM))) // Respect sysdm.cpl policy. { hr = S_OK; // restricted. } return hr; } HRESULT RestrictHomeNetwork(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->IsX86() || // x86 only. pns->IsOnDomain() || // Not available on domains. pns->IsServer() || // Not available on server. !pns->IsUserAdmin() || // Admins only. !IsAppletEnabled(L"hnetwiz.dll", NULL)) // Respect hnetwiz.dll policy. { hr = S_OK; // restricted. } return hr; } HRESULT RestrictTsNetworking(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Available on personal and professional only. // if (!(pns->IsPersonal() || pns->IsProfessional())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictTsInetExplorer(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Available on personal and professional only. // if (!(pns->IsPersonal() || pns->IsProfessional())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictTsModem(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Available on server only. // if (!pns->IsServer()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictTsSharing(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Available on server only. // if (!pns->IsServer()) { hr = S_OK; // restricted. } return hr; } bool ShellKeyExists(SHELLKEY skey, LPCWSTR pszRegName) { TCHAR szValue[MAX_PATH]; DWORD cbValue = sizeof(szValue); return SUCCEEDED(SKGetValue(skey, pszRegName, NULL, NULL, szValue, &cbValue)); } HRESULT RestrictBackupData(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Not available if the 'backuppath' shell key is missing. // This logic is the same as that used by the "Tools" page // in a volume property sheet. // if (!ShellKeyExists(SHELLKEY_HKLM_EXPLORER, TEXT("MyComputer\\BackupPath"))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictDefrag(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; // // Not available if the 'defragpath' shell key is missing. // This logic is the same as that used by the "Tools" page // in a volume property sheet. // if (!ShellKeyExists(SHELLKEY_HKLM_EXPLORER, TEXT("MyComputer\\DefragPath"))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictCleanUpDisk(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Not available if the 'cleanuppath' shell key is missing. // if (!ShellKeyExists(SHELLKEY_HKLM_EXPLORER, TEXT("MyComputer\\CleanupPath"))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictSystemRestore(ICplNamespace *pns) { HRESULT hr = S_FALSE; // // Available only on x86. // if (!pns->IsX86() || pns->IsServer() || CPL::IsSystemRestoreRestricted()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictServerUserManager(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || pns->UsePersonalUserManager()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictFolderOptions(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; if (SHRestricted(REST_NOFOLDEROPTIONS) || !IsAppletEnabled(NULL, MAKEINTRESOURCEW(IDS_LOCALGDN_NS_FOLDEROPTIONS))) { hr = S_OK; } return hr; } HRESULT RestrictIfNoAppletsInCplCategory(ICplNamespace *pns, eCPCAT eCategory) { int cCplApplets = 0; HRESULT hr = THR(CplNamespace_GetCategoryAppletCount(pns, eCategory, &cCplApplets)); if (SUCCEEDED(hr)) { if (0 == cCplApplets) { hr = S_OK; // 0 applets means we don't show the link. } else { hr = S_FALSE; } } return hr; } // // If there are no CPL applets categorized under "Other", // we hide the "Other CPL Options" link in the UI. // HRESULT RestrictOtherCplOptions(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!CPL::CategoryViewIsActive() || S_OK == RestrictIfNoAppletsInCplCategory(pns, eCPCAT_OTHER)) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictWindowsUpdate(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; // // First check the shell's restriction for the "Windows Update" // item in the start menu. If the admin doesn't want access from // the start menu, they most likely don't want it from Control Panel either. // if (SHRestricted(REST_NOUPDATEWINDOWS)) { hr = S_OK; } if (S_FALSE == hr) { // // Not restricted in start menu. // How about the global "Disable Windows Update" policy? // DWORD dwType; DWORD dwData; DWORD cbData = sizeof(dwData); if (ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\WindowsUpdate", L"DisableWindowsUpdateAccess", &dwType, &dwData, &cbData)) { if (REG_DWORD == dwType && 1 == dwData) { hr = S_OK; // restricted. } } } return hr; } HRESULT RestrictAddLanguage(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->IsUserAdmin() || !IsAppletEnabled(L"intl.cpl", MAKEINTRESOURCEW(IDS_CPL_REGIONALOPTIONS))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictAccountsCreate(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager() || !(pns->IsUserOwner() || pns->IsUserStandard())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictAccountsCreate2(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || pns->UsePersonalUserManager() || !(pns->IsUserOwner() || pns->IsUserStandard())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictAccountsChange(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager() || !(pns->IsUserOwner() || pns->IsUserStandard())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictAccountsPicture(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictLearnAboutAccounts(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager()) { hr = S_OK; } return hr; } HRESULT RestrictLearnAboutAccountTypes(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager() || !IsUserAdmin()) // topic is for non-admins only. { hr = S_OK; // restricted. } return hr; } HRESULT RestrictLearnAboutChangeName(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager() || !(pns->IsUserLimited() || pns->IsUserGuest())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictLearnAboutCreateAccount(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager() || !(pns->IsUserLimited() || pns->IsUserGuest())) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictLearnAboutFUS(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->AllowUserManager() || !pns->UsePersonalUserManager()) { hr = S_OK; } return hr; } HRESULT RestrictHardwareWizard(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->IsUserAdmin() || !IsAppletEnabled(L"hdwwiz.cpl", MAKEINTRESOURCEW(IDS_CPL_ADDHARDWARE))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictVpnConnections(ICplNamespace *pns) { HRESULT hr = S_FALSE; if (!pns->IsUserAdmin()) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictArp(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; // // Why we don't check SHRestricted(REST_ARP_NOARP)? // // 1. We don't hide category links for any reason. // 2. If that policy is enabled and appwiz.cpl is allowed, // (remember, those are different policies) // we'll display the ARP category page and it will still // show the ARP applet icon. Since there is at least one // task link or icon, we don't display the "content disabled // by your admin" barricade. Then the user will click on the // applet icon and get ARP's "I've been disabled" messagebox. // // By not checking this policy, clicking on the category link // will invoke ARP and ARP will display it's message. // I think this is a better user experience. // if (!IsAppletEnabled(L"appwiz.cpl", MAKEINTRESOURCEW(IDS_CPL_ADDREMOVEPROGRAMS))) { hr = S_OK; // restricted. } return hr; } // // The ARP category (and it's tasks) are displayed only when there // are 2+ applets registered for that category (ARP and one or more // other applets). Unlike RestrictArp() above, we DO want to consider // SHRestricted(REST_ARP_NOARP). This way if ARP is restricted in // ANY way, it's related tasks will not appear. // HRESULT RestrictArpAddProgram(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; if (SHRestricted(REST_ARP_NOARP) || SHRestricted(REST_ARP_NOADDPAGE) || !IsAppletEnabled(L"appwiz.cpl", MAKEINTRESOURCEW(IDS_CPL_ADDREMOVEPROGRAMS))) { hr = S_OK; // restricted. } return hr; } HRESULT RestrictArpRemoveProgram(ICplNamespace *pns) { UNREFERENCED_PARAMETER(pns); HRESULT hr = S_FALSE; if (SHRestricted(REST_ARP_NOARP) || SHRestricted(REST_ARP_NOREMOVEPAGE) || !IsAppletEnabled(L"appwiz.cpl", MAKEINTRESOURCEW(IDS_CPL_ADDREMOVEPROGRAMS))) { hr = S_OK; // restricted. } return hr; } //----------------------------------------------------------------------------- // Restriction objects (alphabetical order please) //----------------------------------------------------------------------------- // // To restrict an action, create a restriction object and associate it with the // action in the Action object declarations below. // const CRestrictFunc g_Restrict32CtrlPanel (Restrict32CtrlPanel); const CRestrictApplet g_RestrictAccessibility (L"access.cpl", MAKEINTRESOURCEW(IDS_CPL_ACCESSIBILITYOPTIONS)); const CRestrictApplet g_RestrictAccessWizard (L"accwiz.exe", NULL); const CRestrictFunc g_RestrictAccountsCreate (RestrictAccountsCreate); const CRestrictFunc g_RestrictAccountsCreate2 (RestrictAccountsCreate2); const CRestrictFunc g_RestrictAccountsChange (RestrictAccountsChange); const CRestrictFunc g_RestrictAccountsPicture (RestrictAccountsPicture); const CRestrictFunc g_RestrictAccountsServer (RestrictServerUserManager); const CRestrictFunc g_RestrictAddLanguage (RestrictAddLanguage); const CRestrictFunc g_RestrictAddPrinter (RestrictAddPrinter); const CRestrictApplet g_RestrictAdminTools (NULL, MAKEINTRESOURCEW(IDS_LOCALGDN_NS_ADMIN_TOOLS)); const CRestrictFunc g_RestrictAlways (RestrictAlways); const CRestrictFunc g_RestrictArp (RestrictArp); const CRestrictFunc g_RestrictArpAddProgram (RestrictArpAddProgram); const CRestrictFunc g_RestrictArpRemoveProgram (RestrictArpRemoveProgram); const CRestrictFunc g_RestrictBackupData (RestrictBackupData); const CRestrictFunc g_RestrictCleanUpDisk (RestrictCleanUpDisk); const CRestrictApplet g_RestrictDateTime (L"timedate.cpl", MAKEINTRESOURCEW(IDS_CPL_DATETIME)); const CRestrictFunc g_RestrictDefrag (RestrictDefrag); const CRestrictFunc g_RestrictDisplayCpl (RestrictDisplayCpl); const CRestrictFunc g_RestrictFolderOptions (RestrictFolderOptions); const CRestrictApplet g_RestrictFontsFolder (NULL, MAKEINTRESOURCEW(IDS_LOCALGDN_NS_FONTS)); const CRestrictFunc g_RestrictHomeNetwork (RestrictHomeNetwork); const CRestrictFunc g_RestrictHardwareWizard (RestrictHardwareWizard); const CRestrictApplet g_RestrictInternational (L"intl.cpl", MAKEINTRESOURCEW(IDS_CPL_REGIONALOPTIONS)); const CRestrictFunc g_RestrictLearnAboutAccounts (RestrictLearnAboutAccounts); const CRestrictFunc g_RestrictLearnAboutAccountTypes (RestrictLearnAboutAccountTypes); const CRestrictFunc g_RestrictLearnAboutChangeName (RestrictLearnAboutChangeName); const CRestrictFunc g_RestrictLearnAboutCreateAccount(RestrictLearnAboutCreateAccount); const CRestrictFunc g_RestrictLearnAboutFUS (RestrictLearnAboutFUS); const CRestrictApplet g_RestrictMousePointers (L"main.cpl", MAKEINTRESOURCEW(IDS_CPL_MOUSE)); const CRestrictApplet g_RestrictNetConnections (L"inetcpl.cpl", MAKEINTRESOURCEW(IDS_CPL_INTERNETOPTIONS)); const CRestrictFunc g_RestrictOtherCplOptions (RestrictOtherCplOptions); const CRestrictApplet g_RestrictPhoneModemCpl (L"telephon.cpl", MAKEINTRESOURCEW(IDS_CPL_PHONEANDMODEMOPTIONS)); const CRestrictApplet g_RestrictPowerOptions (L"powercfg.cpl", MAKEINTRESOURCEW(IDS_CPL_POWEROPTIONS)); const CRestrictApplet g_RestrictPrinters (NULL, MAKEINTRESOURCEW(IDS_PRNANDFAXFOLDER)); const CRestrictFunc g_RestrictRemoteDesktop (RestrictRemoteDesktop); const CRestrictFunc g_RestrictResolution (RestrictResolution); const CRestrictApplet g_RestrictScannersCameras (NULL, MAKEINTRESOURCEW(IDS_CPL_SCANNERSANDCAMERAS)); const CRestrictFunc g_RestrictScreenSaver (RestrictScreenSaver); const CRestrictApplet g_RestrictScheduledTasks (NULL, MAKEINTRESOURCEW(IDS_LOCALGDN_LNK_SCHEDULED_TASKS)); const CRestrictApplet g_RestrictSounds (L"mmsys.cpl", MAKEINTRESOURCEW(IDS_CPL_SOUNDSANDAUDIO)); const CRestrictApplet g_RestrictSystemCpl (L"sysdm.cpl", MAKEINTRESOURCEW(IDS_CPL_SYSTEM)); const CRestrictFunc g_RestrictSystemRestore (RestrictSystemRestore); const CRestrictApplet g_RestrictTaskbarProps (NULL, MAKEINTRESOURCEW(IDS_CP_TASKBARANDSTARTMENU)); const CRestrictFunc g_RestrictThemes (RestrictThemes); const CRestrictFunc g_RestrictTsModem (RestrictTsModem); const CRestrictFunc g_RestrictTsInetExplorer (RestrictTsInetExplorer); const CRestrictFunc g_RestrictTsNetworking (RestrictTsNetworking); const CRestrictFunc g_RestrictTsSharing (RestrictTsSharing); const CRestrictApplet g_RestrictUserManager (L"nusrmgr.cpl", MAKEINTRESOURCEW(IDS_CPL_USERACCOUNTS)); const CRestrictFunc g_RestrictVpnConnections (RestrictVpnConnections); const CRestrictFunc g_RestrictWallpaper (RestrictWallpaper); const CRestrictFunc g_RestrictWindowsUpdate (RestrictWindowsUpdate); //----------------------------------------------------------------------------- // Resource functions //----------------------------------------------------------------------------- // // The tooltip for the accounts manager varies based upon the capabilities // of the application used. On Personal we provide the ability to associate // a user's picture with their account. The tooltip mentions this. On server // this capability is not present. Therefore, the tooltip must not mention // this. // LPCWSTR GetCatAccountsInfotip(ICplNamespace *pns) { if (pns->AllowUserManager() && pns->UsePersonalUserManager()) { return MAKEINTRESOURCEW(IDS_CPCAT_ACCOUNTS_INFOTIP); } else { // // Personal user manager is restricted. Display the // infotip without the term "picture". // return MAKEINTRESOURCEW(IDS_CPCAT_ACCOUNTS_INFOTIP2); } } LPCWSTR GetAccountsInfotip(ICplNamespace *pns) { if (pns->AllowUserManager() && pns->UsePersonalUserManager()) { return MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSMANAGE_INFOTIP); } else { // // Personal user manager is restricted. Display the // infotip without the term "picture". // return MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSMANAGE_INFOTIP2); } } LPCWSTR GetTsNetworkTitle(ICplNamespace *pns) { if ((pns->IsPersonal() || pns->IsProfessional()) && !pns->IsOnDomain()) { return MAKEINTRESOURCE(IDS_CPTASK_TSHOMENETWORKING_TITLE); } else { return MAKEINTRESOURCE(IDS_CPTASK_TSNETWORK_TITLE); } } //----------------------------------------------------------------------------- // Action objects (alphabetical order please) //----------------------------------------------------------------------------- // // Each object represents some action taken when a link in Control Panel is // selected. Actions are associated with links in the g_Link_XXXX declarations below. // const CShellExecute g_LinkAction_32CtrlPanel (L"%SystemRoot%\\SysWOW64\\explorer.exe", L"/N,/SEPARATE,\"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\"", &g_Restrict32CtrlPanel); const CShellExecuteSysDir g_LinkAction_AccessWizard (L"accwiz.exe", NULL, &g_RestrictAccessWizard); const COpenUserMgrApplet g_LinkAction_Accounts (&g_RestrictUserManager); const COpenCplAppletSysDir g_LinkAction_AccountsChange (L"nusrmgr.cpl ,initialTask=ChangeAccount", &g_RestrictAccountsChange); const COpenCplAppletSysDir g_LinkAction_AccountsCreate (L"nusrmgr.cpl ,initialTask=CreateAccount", &g_RestrictAccountsCreate); const COpenCplAppletSysDir g_LinkAction_AccountsCreate2 (L"nusrmgr.cpl", &g_RestrictAccountsCreate2); const COpenCplAppletSysDir g_LinkAction_AccountsPict (L"nusrmgr.cpl ,initialTask=ChangePicture", &g_RestrictAccountsPicture); const CAddPrinter g_LinkAction_AddPrinter (&g_RestrictAddPrinter); const COpenCplAppletSysDir g_LinkAction_AddProgram (L"appwiz.cpl ,1", &g_RestrictArpAddProgram); const COpenCplAppletSysDir g_LinkAction_Arp (L"appwiz.cpl", &g_RestrictArp); const COpenCplAppletSysDir g_LinkAction_AutoUpdate (L"sysdm.cpl ,@wuaueng.dll,10000", &g_RestrictSystemCpl); const CExecDiskUtil g_LinkAction_BackupData (eDISKUTIL_BACKUP, &g_RestrictBackupData); const COpenCplCategory g_LinkAction_CatAccessibility (eCPCAT_ACCESSIBILITY); const COpenCplCategory2 g_LinkAction_CatAccounts (eCPCAT_ACCOUNTS, &g_LinkAction_Accounts); const COpenCplCategory g_LinkAction_CatAppearance (eCPCAT_APPEARANCE); const COpenCplCategory2 g_LinkAction_CatArp (eCPCAT_ARP, &g_LinkAction_Arp); const COpenCplCategory g_LinkAction_CatHardware (eCPCAT_HARDWARE); const COpenCplCategory g_LinkAction_CatNetwork (eCPCAT_NETWORK); const COpenCplCategory g_LinkAction_CatOther (eCPCAT_OTHER, &g_RestrictAlways); const COpenCplCategory g_LinkAction_CatPerfMaint (eCPCAT_PERFMAINT); const COpenCplCategory g_LinkAction_CatRegional (eCPCAT_REGIONAL); const COpenCplCategory g_LinkAction_CatSound (eCPCAT_SOUND); const CExecDiskUtil g_LinkAction_CleanUpDisk (eDISKUTIL_CLEANUP, &g_RestrictCleanUpDisk); const COpenCplAppletSysDir g_LinkAction_DateTime (L"timedate.cpl", &g_RestrictDateTime); const CExecDiskUtil g_LinkAction_Defrag (eDISKUTIL_DEFRAG, &g_RestrictDefrag); const COpenCplAppletSysDir g_LinkAction_DisplayCpl (L"desk.cpl", &g_RestrictDisplayCpl); const COpenDeskCpl g_LinkAction_DisplayRes (CPLTAB_DESK_SETTINGS, &g_RestrictResolution); const COpenCplAppletSysDir g_LinkAction_DisplayTheme (L"desk.cpl", &g_RestrictThemes); const CRunDll32 g_LinkAction_FolderOptions (L"shell32.dll,Options_RunDLL 0", &g_RestrictFolderOptions); const CNavigateURL g_LinkAction_FontsFolder (L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D20EA4E1-3957-11d2-A40B-0C5020524152}", &g_RestrictFontsFolder); const COpenCplAppletSysDir g_LinkAction_HardwareWizard (L"hdwwiz.cpl", &g_RestrictHardwareWizard); const CTrayCommand g_LinkAction_HelpAndSupport (IDM_HELPSEARCH); const COpenCplAppletSysDir g_LinkAction_HighContrast (L"access.cpl ,3", &g_RestrictAccessibility); const CRunDll32 g_LinkAction_HomeNetWizard (L"hnetwiz.dll,HomeNetWizardRunDll", &g_RestrictHomeNetwork); const CShellExecuteSysDir g_LinkAction_Magnifier (L"magnify.exe"); const COpenCplAppletSysDir g_LinkAction_Language (L"intl.cpl ,1", &g_RestrictAddLanguage); const CNavigateURL g_LinkAction_LearnAccounts (L"ms-its:%windir%\\help\\nusrmgr.chm::/HelpWindowsAccounts.htm", &g_RestrictLearnAboutAccounts); const CNavigateURL g_LinkAction_LearnAccountsTypes (L"ms-its:%windir%\\help\\nusrmgr.chm::/HelpAccountTypes.htm", &g_RestrictLearnAboutAccountTypes); const CNavigateURL g_LinkAction_LearnAccountsChangeName (L"ms-its:%windir%\\help\\nusrmgr.chm::/HelpChangeNonAdmin.htm", &g_RestrictLearnAboutChangeName); const CNavigateURL g_LinkAction_LearnAccountsCreate (L"ms-its:%windir%\\help\\nusrmgr.chm::/HelpCreateAccount.htm", &g_RestrictLearnAboutCreateAccount); const CNavigateURL g_LinkAction_LearnSwitchUsers (L"ms-its:%windir%\\help\\nusrmgr.chm::/HelpFUS.htm", &g_RestrictLearnAboutFUS); const COpenCplAppletSysDir g_LinkAction_MousePointers (L"main.cpl ,2", &g_RestrictMousePointers); const CNavigateURL g_LinkAction_MyComputer (L"shell:DriveFolder"); const CNavigateURL g_LinkAction_MyNetPlaces (L"shell:::{208D2C60-3AEA-1069-A2D7-08002B30309D}"); const COpenCplAppletSysDir g_LinkAction_NetConnections (L"inetcpl.cpl ,4", &g_RestrictNetConnections); const CActionNYI g_LinkAction_NotYetImpl (L"Under construction"); const CShellExecuteSysDir g_LinkAction_OnScreenKbd (L"osk.exe"); const COpenCplCategory g_LinkAction_OtherCplOptions (eCPCAT_OTHER, &g_RestrictOtherCplOptions); const COpenCplAppletSysDir g_LinkAction_PhoneModemCpl (L"telephon.cpl", &g_RestrictPhoneModemCpl); const COpenCplAppletSysDir g_LinkAction_PowerCpl (L"powercfg.cpl", &g_RestrictPowerOptions); const COpenCplAppletSysDir g_LinkAction_Region (L"intl.cpl", &g_RestrictInternational); const COpenCplAppletSysDir g_LinkAction_RemoteDesktop (L"sysdm.cpl ,@remotepg.dll,10000", &g_RestrictRemoteDesktop); const COpenCplAppletSysDir g_LinkAction_RemoveProgram (L"appwiz.cpl ,0", &g_RestrictArpRemoveProgram); const CNavigateURL g_LinkAction_ScheduledTasks (L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{D6277990-4C6A-11CF-8D87-00AA0060F5BF}", &g_RestrictScheduledTasks); const COpenDeskCpl g_LinkAction_ScreenSaver (CPLTAB_DESK_SCREENSAVER, &g_RestrictScreenSaver); const COpenCplAppletSysDir g_LinkAction_SoundAccessibility(L"access.cpl ,2", &g_RestrictAccessibility); const COpenCplCategory g_LinkAction_Sounds (eCPCAT_SOUND); const COpenCplAppletSysDir g_LinkAction_SoundSchemes (L"mmsys.cpl ,1", &g_RestrictSounds); const COpenCplAppletSysDir g_LinkAction_SoundVolume (L"mmsys.cpl ,0", &g_RestrictSounds); const CShellExecuteSysDir g_LinkAction_SoundVolumeAdv (L"sndvol32.exe", NULL, &g_RestrictSounds); const COpenCplView g_LinkAction_SwToClassicView (eCPVIEWTYPE_CLASSIC); const COpenCplView g_LinkAction_SwToCategoryView (eCPVIEWTYPE_CATEGORY); const COpenCplAppletSysDir g_LinkAction_SystemCpl (L"sysdm.cpl ,@sysdm.cpl,10000", &g_RestrictSystemCpl); const CShellExecuteSysDir g_LinkAction_SystemRestore (L"restore\\rstrui.exe", NULL, &g_RestrictSystemRestore); const COpenTroubleshooter g_LinkAction_TsDisplay (L"tsdisp.htm"); const COpenTroubleshooter g_LinkAction_TsDvd (L"ts_dvd.htm"); const COpenTroubleshooter g_LinkAction_TsHardware (L"tshardw.htm"); const COpenTroubleshooter g_LinkAction_TsInetExplorer (L"tsie.htm", &g_RestrictTsInetExplorer); const COpenTroubleshooter g_LinkAction_TsModem (L"tsmodem.htm", &g_RestrictTsModem); const COpenTroubleshooter g_LinkAction_TsNetwork (L"tshomenet.htm", &g_RestrictTsNetworking); const CNavigateURL g_LinkAction_TsNetDiags (L"hcp://system/netdiag/dglogs.htm"); const COpenTroubleshooter g_LinkAction_TsPrinting (L"tsprint.htm"); const COpenTroubleshooter g_LinkAction_TsSharing (L"tsnetwrk.htm", &g_RestrictTsSharing); const COpenTroubleshooter g_LinkAction_TsStartup (L"tsstartup.htm"); const COpenTroubleshooter g_LinkAction_TsSound (L"tssound.htm"); const CNavigateURL g_LinkAction_ViewPrinters (L"shell:::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", &g_RestrictPrinters); const COpenCplAppletSysDir g_LinkAction_VisualPerf (L"sysdm.cpl ,-1", &g_RestrictSystemCpl); const CRunDll32 g_LinkAction_VpnConnections (L"netshell.dll,StartNCW 21010", &g_RestrictVpnConnections); const COpenDeskCpl g_LinkAction_Wallpaper (CPLTAB_DESK_BACKGROUND, &g_RestrictWallpaper); const CNavigateURL g_LinkAction_WindowsUpdate (L"http://www.microsoft.com/isapi/redir.dll?prd=Win2000&ar=WinUpdate", &g_RestrictWindowsUpdate); //----------------------------------------------------------------------------- // Link object initialization data (alphabetical order please) //----------------------------------------------------------------------------- // // Each g_Link_XXXX variable represents a link in the Control Panel namespace. // Note that if a particular link is displayed in multiple places in the Control Panel, // only one instance of a g_Link_XXXX variable is required. // // The 'S' and 'T' in g_SLink and g_TLink mean "Support" and "Task" respectively. // I've used the generic term "support" to refer to items that appear in one // of the webview lists in the left-hand pane. // We may have a link in a support list and in a category task list that essentially // do the same thing but they have different icons and titles. The 'S' and 'T' // help differentiate. // const CResSrcStatic g_SLinkRes_32CtrlPanel_Icon(MAKEINTRESOURCEW(IDI_CPTASK_32CPLS)); const CResSrcStatic g_SLinkRes_32CtrlPanel_Title(MAKEINTRESOURCEW(IDS_CPTASK_32CPLS_TITLE)); const CResSrcStatic g_SLinkRes_32CtrlPanel_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_32CPLS_INFOTIP)); const CPLINK_DESC g_SLink_32CtrlPanel = { &g_SLinkRes_32CtrlPanel_Icon, &g_SLinkRes_32CtrlPanel_Title, &g_SLinkRes_32CtrlPanel_Infotip, &g_LinkAction_32CtrlPanel }; const CResSrcStatic g_TLinkRes_AccessWizard_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AccessWizard_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCESSWIZARD_TITLE)); const CResSrcStatic g_TLinkRes_AccessWizard_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ACCESSWIZARD_INFOTIP)); const CPLINK_DESC g_TLink_AccessWizard = { &g_TLinkRes_AccessWizard_Icon, &g_TLinkRes_AccessWizard_Title, &g_TLinkRes_AccessWizard_Infotip, &g_LinkAction_AccessWizard }; const CResSrcStatic g_TLinkRes_AccountsChange_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AccountsChange_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSMANAGE_TITLE)); const CResSrcFunc g_TLinkRes_AccountsChange_Infotip(GetAccountsInfotip); const CPLINK_DESC g_TLink_AccountsChange = { &g_TLinkRes_AccountsChange_Icon, &g_TLinkRes_AccountsChange_Title, &g_TLinkRes_AccountsChange_Infotip, &g_LinkAction_AccountsChange }; const CResSrcStatic g_TLinkRes_AccountsCreate_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AccountsCreate_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSCREATE_TITLE)); const CResSrcStatic g_TLinkRes_AccountsCreate_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSCREATE_INFOTIP)); const CPLINK_DESC g_TLink_AccountsCreate = { &g_TLinkRes_AccountsCreate_Icon, &g_TLinkRes_AccountsCreate_Title, &g_TLinkRes_AccountsCreate_Infotip, &g_LinkAction_AccountsCreate }; // // This link uses the same visual information as g_TLink_AccountsCreate above. // The difference is in the action performed on selection. // const CPLINK_DESC g_TLink_AccountsCreate2 = { &g_TLinkRes_AccountsCreate_Icon, &g_TLinkRes_AccountsCreate_Title, &g_TLinkRes_AccountsCreate_Infotip, &g_LinkAction_AccountsCreate2 }; const CResSrcStatic g_SLinkRes_AccountsPict_Icon(L"nusrmgr.cpl,-205"); const CResSrcStatic g_SLinkRes_AccountsPict_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSPICT_TITLE)); const CResSrcStatic g_SLinkRes_AccountsPict_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSPICT_INFOTIP)); const CPLINK_DESC g_SLink_AccountsPict = { &g_SLinkRes_AccountsPict_Icon, &g_SLinkRes_AccountsPict_Title, &g_SLinkRes_AccountsPict_Infotip, &g_LinkAction_AccountsPict }; const CResSrcStatic g_TLinkRes_AccountsPict_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AccountsPict_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSPICT2_TITLE)); const CResSrcStatic g_TLinkRes_AccountsPict_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSPICT2_INFOTIP)); const CPLINK_DESC g_TLink_AccountsPict = { &g_TLinkRes_AccountsPict_Icon, &g_TLinkRes_AccountsPict_Title, &g_TLinkRes_AccountsPict_Infotip, &g_LinkAction_AccountsPict }; const CResSrcStatic g_TLinkRes_Accounts_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_Accounts_Title(MAKEINTRESOURCEW(IDS_CPTASK_ACCOUNTSMANAGE_TITLE)); const CResSrcFunc g_TLinkRes_Accounts_Infotip(GetAccountsInfotip); const CPLINK_DESC g_TLink_Accounts = { &g_TLinkRes_Accounts_Icon, &g_TLinkRes_Accounts_Title, &g_TLinkRes_Accounts_Infotip, &g_LinkAction_Accounts }; const CResSrcStatic g_TLinkRes_AddPrinter_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AddPrinter_Title(MAKEINTRESOURCEW(IDS_CPTASK_ADDPRINTER_TITLE)); const CResSrcStatic g_TLinkRes_AddPrinter_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ADDPRINTER_INFOTIP)); const CPLINK_DESC g_TLink_AddPrinter = { &g_TLinkRes_AddPrinter_Icon, &g_TLinkRes_AddPrinter_Title, &g_TLinkRes_AddPrinter_Infotip, &g_LinkAction_AddPrinter }; const CResSrcStatic g_TLinkRes_AddProgram_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_AddProgram_Title(MAKEINTRESOURCEW(IDS_CPTASK_ADDPROGRAM_TITLE)); const CResSrcStatic g_TLinkRes_AddProgram_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ADDPROGRAM_INFOTIP)); const CPLINK_DESC g_TLink_AddProgram = { &g_TLinkRes_AddProgram_Icon, &g_TLinkRes_AddProgram_Title, &g_TLinkRes_AddProgram_Infotip, &g_LinkAction_AddProgram }; // // Note that the "Auto Updates" icon is the same as the "Windows Update" icon. // This is the way the Windows Update folks want it. // const CResSrcStatic g_SLinkRes_AutoUpdate_Icon(MAKEINTRESOURCEW(IDI_WINUPDATE)); const CResSrcStatic g_SLinkRes_AutoUpdate_Title(MAKEINTRESOURCEW(IDS_CPTASK_AUTOUPDATE_TITLE)); const CResSrcStatic g_SLinkRes_AutoUpdate_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_AUTOUPDATE_INFOTIP)); const CPLINK_DESC g_SLink_AutoUpdate = { &g_SLinkRes_AutoUpdate_Icon, &g_SLinkRes_AutoUpdate_Title, &g_SLinkRes_AutoUpdate_Infotip, &g_LinkAction_AutoUpdate }; const CResSrcStatic g_TLinkRes_BackupData_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_BackupData_Title(MAKEINTRESOURCEW(IDS_CPTASK_BACKUPDATA_TITLE)); const CResSrcStatic g_TLinkRes_BackupData_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_BACKUPDATA_INFOTIP)); const CPLINK_DESC g_TLink_BackupData = { &g_TLinkRes_BackupData_Icon, &g_TLinkRes_BackupData_Title, &g_TLinkRes_BackupData_Infotip, &g_LinkAction_BackupData }; const CResSrcStatic g_TLinkRes_CatAccessibility_Icon(MAKEINTRESOURCEW(IDI_CPCAT_ACCESSIBILITY)); const CResSrcStatic g_TLinkRes_CatAccessibility_Title(MAKEINTRESOURCEW(IDS_CPCAT_ACCESSIBILITY_TITLE)); const CResSrcStatic g_TLinkRes_CatAccessibility_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_ACCESSIBILITY_INFOTIP)); const CPLINK_DESC g_TLink_CatAccessibility = { &g_TLinkRes_CatAccessibility_Icon, &g_TLinkRes_CatAccessibility_Title, &g_TLinkRes_CatAccessibility_Infotip, &g_LinkAction_CatAccessibility }; const CResSrcStatic g_TLinkRes_CatAccounts_Icon(MAKEINTRESOURCEW(IDI_CPCAT_ACCOUNTS)); const CResSrcStatic g_TLinkRes_CatAccounts_Title(MAKEINTRESOURCEW(IDS_CPCAT_ACCOUNTS_TITLE)); const CResSrcFunc g_TLinkRes_CatAccounts_Infotip(GetCatAccountsInfotip); const CPLINK_DESC g_TLink_CatAccounts = { &g_TLinkRes_CatAccounts_Icon, &g_TLinkRes_CatAccounts_Title, &g_TLinkRes_CatAccounts_Infotip, &g_LinkAction_CatAccounts }; const CResSrcStatic g_TLinkRes_CatAppearance_Icon(MAKEINTRESOURCEW(IDI_CPCAT_APPEARANCE)); const CResSrcStatic g_TLinkRes_CatAppearance_Title(MAKEINTRESOURCEW(IDS_CPCAT_APPEARANCE_TITLE)); const CResSrcStatic g_TLinkRes_CatAppearance_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_APPEARANCE_INFOTIP)); const CPLINK_DESC g_TLink_CatAppearance = { &g_TLinkRes_CatAppearance_Icon, &g_TLinkRes_CatAppearance_Title, &g_TLinkRes_CatAppearance_Infotip, &g_LinkAction_CatAppearance }; const CResSrcStatic g_TLinkRes_CatArp_Icon(MAKEINTRESOURCEW(IDI_CPCAT_ARP)); const CResSrcStatic g_TLinkRes_CatArp_Title(MAKEINTRESOURCEW(IDS_CPCAT_ARP_TITLE)); const CResSrcStatic g_TLinkRes_CatArp_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_ARP_INFOTIP)); const CPLINK_DESC g_TLink_CatArp = { &g_TLinkRes_CatArp_Icon, &g_TLinkRes_CatArp_Title, &g_TLinkRes_CatArp_Infotip, &g_LinkAction_CatArp }; const CResSrcStatic g_TLinkRes_CatHardware_Icon(MAKEINTRESOURCEW(IDI_CPCAT_HARDWARE)); const CResSrcStatic g_TLinkRes_CatHardware_Title(MAKEINTRESOURCEW(IDS_CPCAT_HARDWARE_TITLE)); const CResSrcStatic g_TLinkRes_CatHardware_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_HARDWARE_INFOTIP)); const CPLINK_DESC g_TLink_CatHardware = { &g_TLinkRes_CatHardware_Icon, &g_TLinkRes_CatHardware_Title, &g_TLinkRes_CatHardware_Infotip, &g_LinkAction_CatHardware }; const CResSrcStatic g_TLinkRes_CatNetwork_Icon(MAKEINTRESOURCEW(IDI_CPCAT_NETWORK)); const CResSrcStatic g_TLinkRes_CatNetwork_Title(MAKEINTRESOURCEW(IDS_CPCAT_NETWORK_TITLE)); const CResSrcStatic g_TLinkRes_CatNetwork_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_NETWORK_INFOTIP)); const CPLINK_DESC g_TLink_CatNetwork = { &g_TLinkRes_CatNetwork_Icon, &g_TLinkRes_CatNetwork_Title, &g_TLinkRes_CatNetwork_Infotip, &g_LinkAction_CatNetwork }; const CResSrcStatic g_TLinkRes_CatOther_Icon(MAKEINTRESOURCEW(IDI_CPCAT_OTHERCPLS)); const CResSrcStatic g_TLinkRes_CatOther_Title(MAKEINTRESOURCEW(IDS_CPCAT_OTHERCPLS_TITLE)); const CResSrcStatic g_TLinkRes_CatOther_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_OTHERCPLS_INFOTIP)); const CPLINK_DESC g_TLink_CatOther = { &g_TLinkRes_CatOther_Icon, &g_TLinkRes_CatOther_Title, &g_TLinkRes_CatOther_Infotip, &g_LinkAction_CatOther }; const CResSrcStatic g_TLinkRes_CatPerfMaint_Icon(MAKEINTRESOURCEW(IDI_CPCAT_PERFMAINT)); const CResSrcStatic g_TLinkRes_CatPerfMaint_Title(MAKEINTRESOURCEW(IDS_CPCAT_PERFMAINT_TITLE)); const CResSrcStatic g_TLinkRes_CatPerfMaint_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_PERFMAINT_INFOTIP)); const CPLINK_DESC g_TLink_CatPerfMaint = { &g_TLinkRes_CatPerfMaint_Icon, &g_TLinkRes_CatPerfMaint_Title, &g_TLinkRes_CatPerfMaint_Infotip, &g_LinkAction_CatPerfMaint }; const CResSrcStatic g_TLinkRes_CatRegional_Icon(MAKEINTRESOURCEW(IDI_CPCAT_REGIONAL)); const CResSrcStatic g_TLinkRes_CatRegional_Title(MAKEINTRESOURCEW(IDS_CPCAT_REGIONAL_TITLE)); const CResSrcStatic g_TLinkRes_CatRegional_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_REGIONAL_INFOTIP)); const CPLINK_DESC g_TLink_CatRegional = { &g_TLinkRes_CatRegional_Icon, &g_TLinkRes_CatRegional_Title, &g_TLinkRes_CatRegional_Infotip, &g_LinkAction_CatRegional }; const CResSrcStatic g_TLinkRes_CatSound_Icon(MAKEINTRESOURCEW(IDI_CPCAT_SOUNDS)); const CResSrcStatic g_TLinkRes_CatSound_Title(MAKEINTRESOURCEW(IDS_CPCAT_SOUNDS_TITLE)); const CResSrcStatic g_TLinkRes_CatSound_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_SOUNDS_INFOTIP)); const CPLINK_DESC g_TLink_CatSound = { &g_TLinkRes_CatSound_Icon, &g_TLinkRes_CatSound_Title, &g_TLinkRes_CatSound_Infotip, &g_LinkAction_CatSound }; const CResSrcStatic g_TLinkRes_CleanUpDisk_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_CleanUpDisk_Title(MAKEINTRESOURCEW(IDS_CPTASK_CLEANUPDISK_TITLE)); const CResSrcStatic g_TLinkRes_CleanUpDisk_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_CLEANUPDISK_INFOTIP)); const CPLINK_DESC g_TLink_CleanUpDisk = { &g_TLinkRes_CleanUpDisk_Icon, &g_TLinkRes_CleanUpDisk_Title, &g_TLinkRes_CleanUpDisk_Infotip, &g_LinkAction_CleanUpDisk }; const CResSrcStatic g_TLinkRes_DateTime_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_DateTime_Title(MAKEINTRESOURCEW(IDS_CPTASK_DATETIME_TITLE)); const CResSrcStatic g_TLinkRes_DateTime_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_DATETIME_INFOTIP)); const CPLINK_DESC g_TLink_DateTime = { &g_TLinkRes_DateTime_Icon, &g_TLinkRes_DateTime_Title, &g_TLinkRes_DateTime_Infotip, &g_LinkAction_DateTime }; const CResSrcStatic g_TLinkRes_Defrag_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_Defrag_Title(MAKEINTRESOURCEW(IDS_CPTASK_DEFRAG_TITLE)); const CResSrcStatic g_TLinkRes_Defrag_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_DEFRAG_INFOTIP)); const CPLINK_DESC g_TLink_Defrag = { &g_TLinkRes_Defrag_Icon, &g_TLinkRes_Defrag_Title, &g_TLinkRes_Defrag_Infotip, &g_LinkAction_Defrag }; const CResSrcStatic g_SLinkRes_DisplayCpl_Icon(L"desk.cpl,0"); const CResSrcStatic g_SLinkRes_DisplayCpl_Title(MAKEINTRESOURCEW(IDS_CPTASK_DISPLAYCPL_TITLE)); const CResSrcStatic g_SLinkRes_DisplayCpl_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_DISPLAYCPL_INFOTIP)); const CPLINK_DESC g_SLink_DisplayCpl = { &g_SLinkRes_DisplayCpl_Icon, &g_SLinkRes_DisplayCpl_Title, &g_SLinkRes_DisplayCpl_Infotip, &g_LinkAction_DisplayCpl }; const CResSrcStatic g_TLinkRes_DisplayRes_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_DisplayRes_Title(MAKEINTRESOURCEW(IDS_CPTASK_RESOLUTION_TITLE)); const CResSrcStatic g_TLinkRes_DisplayRes_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_RESOLUTION_INFOTIP)); const CPLINK_DESC g_TLink_DisplayRes = { &g_TLinkRes_DisplayRes_Icon, &g_TLinkRes_DisplayRes_Title, &g_TLinkRes_DisplayRes_Infotip, &g_LinkAction_DisplayRes }; const CResSrcStatic g_TLinkRes_DisplayTheme_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_DisplayTheme_Title(MAKEINTRESOURCEW(IDS_CPTASK_THEME_TITLE)); const CResSrcStatic g_TLinkRes_DisplayTheme_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_THEME_INFOTIP)); const CPLINK_DESC g_TLink_DisplayTheme = { &g_TLinkRes_DisplayTheme_Icon, &g_TLinkRes_DisplayTheme_Title, &g_TLinkRes_DisplayTheme_Infotip, &g_LinkAction_DisplayTheme }; const CResSrcStatic g_SLinkRes_FileTypes_Icon(MAKEINTRESOURCEW(IDI_FOLDEROPTIONS)); const CResSrcStatic g_SLinkRes_FileTypes_Title(MAKEINTRESOURCEW(IDS_CPTASK_FILETYPES_TITLE)); const CResSrcStatic g_SLinkRes_FileTypes_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_FILETYPES_INFOTIP)); const CPLINK_DESC g_SLink_FileTypes = { &g_SLinkRes_FileTypes_Icon, &g_SLinkRes_FileTypes_Title, &g_SLinkRes_FileTypes_Infotip, &g_LinkAction_FolderOptions }; const CResSrcStatic g_TLinkRes_FolderOptions_Icon(MAKEINTRESOURCEW(IDI_FOLDEROPTIONS)); const CResSrcStatic g_TLinkRes_FolderOptions_Title(MAKEINTRESOURCEW(IDS_CPTASK_FOLDEROPTIONS_TITLE)); const CResSrcStatic g_TLinkRes_FolderOptions_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_FOLDEROPTIONS_INFOTIP)); const CPLINK_DESC g_SLink_FolderOptions = { &g_TLinkRes_FolderOptions_Icon, &g_TLinkRes_FolderOptions_Title, &g_TLinkRes_FolderOptions_Infotip, &g_LinkAction_FolderOptions }; const CResSrcStatic g_SLinkRes_FontsFolder_Icon(MAKEINTRESOURCEW(IDI_STFONTS)); const CResSrcStatic g_SLinkRes_FontsFolder_Title(MAKEINTRESOURCEW(IDS_CPTASK_FONTS_TITLE)); const CResSrcStatic g_SLinkRes_FontsFolder_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_FONTS_INFOTIP)); const CPLINK_DESC g_SLink_FontsFolder = { &g_SLinkRes_FontsFolder_Icon, &g_SLinkRes_FontsFolder_Title, &g_SLinkRes_FontsFolder_Infotip, &g_LinkAction_FontsFolder }; const CResSrcStatic g_SLinkRes_Hardware_Icon(MAKEINTRESOURCEW(IDI_CPCAT_HARDWARE)); const CResSrcStatic g_SLinkRes_Hardware_Title(MAKEINTRESOURCEW(IDS_CPCAT_HARDWARE_TITLE)); const CResSrcStatic g_SLinkRes_Hardware_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_HARDWARE_INFOTIP)); const CPLINK_DESC g_SLink_Hardware = { &g_SLinkRes_Hardware_Icon, &g_SLinkRes_Hardware_Title, &g_SLinkRes_Hardware_Infotip, &g_LinkAction_CatHardware }; const CResSrcStatic g_SLinkRes_HardwareWizard_Icon(L"hdwwiz.cpl,0"); const CResSrcStatic g_SLinkRes_HardwareWizard_Title(MAKEINTRESOURCEW(IDS_CPTASK_HARDWAREWIZ_TITLE)); const CResSrcStatic g_SLinkRes_HardwareWizard_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_HARDWAREWIZ_INFOTIP)); const CPLINK_DESC g_SLink_HardwareWizard = { &g_SLinkRes_HardwareWizard_Icon, &g_SLinkRes_HardwareWizard_Title, &g_SLinkRes_HardwareWizard_Infotip, &g_LinkAction_HardwareWizard }; const CResSrcStatic g_SLinkRes_HelpAndSupport_Icon(MAKEINTRESOURCEW(IDI_STHELP)); const CResSrcStatic g_SLinkRes_HelpAndSupport_Title(MAKEINTRESOURCEW(IDS_CPTASK_HELPANDSUPPORT_TITLE)); const CResSrcStatic g_SLinkRes_HelpAndSupport_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_HELPANDSUPPORT_INFOTIP)); const CPLINK_DESC g_SLink_HelpAndSupport = { &g_SLinkRes_HelpAndSupport_Icon, &g_SLinkRes_HelpAndSupport_Title, &g_SLinkRes_HelpAndSupport_Infotip, &g_LinkAction_HelpAndSupport }; const CResSrcStatic g_SLinkRes_HighContrast_Icon(MAKEINTRESOURCEW(IDI_CPTASK_HIGHCONTRAST)); const CResSrcStatic g_SLinkRes_HighContrast_Title(MAKEINTRESOURCEW(IDS_CPTASK_HIGHCONTRAST_TITLE)); const CResSrcStatic g_SLinkRes_HighContrast_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_HIGHCONTRAST_INFOTIP)); const CPLINK_DESC g_SLink_HighContrast = { &g_SLinkRes_HighContrast_Icon, &g_SLinkRes_HighContrast_Title, &g_SLinkRes_HighContrast_Infotip, &g_LinkAction_HighContrast }; const CResSrcStatic g_TLinkRes_HighContrast_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_HighContrast_Title(MAKEINTRESOURCEW(IDS_CPTASK_TURNONHIGHCONTRAST_TITLE)); const CResSrcStatic g_TLinkRes_HighContrast_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TURNONHIGHCONTRAST_INFOTIP)); const CPLINK_DESC g_TLink_HighContrast = { &g_TLinkRes_HighContrast_Icon, &g_TLinkRes_HighContrast_Title, &g_TLinkRes_HighContrast_Infotip, &g_LinkAction_HighContrast }; const CResSrcStatic g_TLinkRes_HomeNetWizard_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_HomeNetWizard_Title(MAKEINTRESOURCEW(IDS_CPTASK_HOMENETWORK_TITLE)); const CResSrcStatic g_TLinkRes_HomeNetWizard_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_HOMENETWORK_INFOTIP)); const CPLINK_DESC g_TLink_HomeNetWizard = { &g_TLinkRes_HomeNetWizard_Icon, &g_TLinkRes_HomeNetWizard_Title, &g_TLinkRes_HomeNetWizard_Infotip, &g_LinkAction_HomeNetWizard }; const CResSrcStatic g_TLinkRes_Language_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_Language_Title(MAKEINTRESOURCEW(IDS_CPTASK_LANGUAGE_TITLE)); const CResSrcStatic g_TLinkRes_Language_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_LANGUAGE_INFOTIP)); const CPLINK_DESC g_TLink_Language = { &g_TLinkRes_Language_Icon, &g_TLinkRes_Language_Title, &g_TLinkRes_Language_Infotip, &g_LinkAction_Language }; // // Learn-about topics use a standard icon and have no infotip. // const CResSrcStatic g_SLinkRes_LearnAbout_Icon(MAKEINTRESOURCE(IDI_CPTASK_LEARNABOUT)); const CResSrcNone g_SLinkRes_LearnAbout_Infotip; const CResSrcStatic g_SLinkRes_LearnAccounts_Title(MAKEINTRESOURCE(IDS_CPTASK_LEARNACCOUNTS_TITLE)); const CPLINK_DESC g_SLink_LearnAccounts = { &g_SLinkRes_LearnAbout_Icon, &g_SLinkRes_LearnAccounts_Title, &g_SLinkRes_LearnAbout_Infotip, &g_LinkAction_LearnAccounts }; const CResSrcStatic g_SLinkRes_LearnAccountsTypes_Title(MAKEINTRESOURCE(IDS_CPTASK_LEARNACCOUNTSTYPES_TITLE)); const CPLINK_DESC g_SLink_LearnAccountsTypes = { &g_SLinkRes_LearnAbout_Icon, &g_SLinkRes_LearnAccountsTypes_Title, &g_SLinkRes_LearnAbout_Infotip, &g_LinkAction_LearnAccountsTypes }; const CResSrcStatic g_SLinkRes_LearnAccountsChangeName_Title(MAKEINTRESOURCE(IDS_CPTASK_LEARNACCOUNTSCHANGENAME_TITLE)); const CPLINK_DESC g_SLink_LearnAccountsChangeName = { &g_SLinkRes_LearnAbout_Icon, &g_SLinkRes_LearnAccountsChangeName_Title, &g_SLinkRes_LearnAbout_Infotip, &g_LinkAction_LearnAccountsChangeName }; const CResSrcStatic g_SLinkRes_LearnAccountsCreate_Title(MAKEINTRESOURCE(IDS_CPTASK_LEARNACCOUNTSCREATE_TITLE)); const CPLINK_DESC g_SLink_LearnAccountsCreate = { &g_SLinkRes_LearnAbout_Icon, &g_SLinkRes_LearnAccountsCreate_Title, &g_SLinkRes_LearnAbout_Infotip, &g_LinkAction_LearnAccountsCreate }; const CResSrcStatic g_SLinkRes_LearnSwitchUsers_Title(MAKEINTRESOURCE(IDS_CPTASK_LEARNSWITCHUSERS_TITLE)); const CPLINK_DESC g_SLink_LearnSwitchUsers = { &g_SLinkRes_LearnAbout_Icon, &g_SLinkRes_LearnSwitchUsers_Title, &g_SLinkRes_LearnAbout_Infotip, &g_LinkAction_LearnSwitchUsers }; const CResSrcStatic g_SLinkRes_Magnifier_Icon(MAKEINTRESOURCEW(IDI_CPTASK_MAGNIFIER)); const CResSrcStatic g_SLinkRes_Magnifier_Title(MAKEINTRESOURCEW(IDS_CPTASK_MAGNIFIER_TITLE)); const CResSrcStatic g_SLinkRes_Magnifier_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_MAGNIFIER_INFOTIP)); const CPLINK_DESC g_SLink_Magnifier = { &g_SLinkRes_Magnifier_Icon, &g_SLinkRes_Magnifier_Title, &g_SLinkRes_Magnifier_Infotip, &g_LinkAction_Magnifier }; const CResSrcStatic g_SLinkRes_MousePointers_Icon(L"main.cpl,0"); const CResSrcStatic g_SLinkRes_MousePointers_Title(MAKEINTRESOURCEW(IDS_CPTASK_MOUSEPOINTERS_TITLE)); const CResSrcStatic g_SLinkRes_MousePointers_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_MOUSEPOINTERS_INFOTIP)); const CPLINK_DESC g_SLink_MousePointers = { &g_SLinkRes_MousePointers_Icon, &g_SLinkRes_MousePointers_Title, &g_SLinkRes_MousePointers_Infotip, &g_LinkAction_MousePointers }; const CResSrcStatic g_SLinkRes_MyComputer_Icon(L"explorer.exe,0"); const CResSrcStatic g_SLinkRes_MyComputer_Title(MAKEINTRESOURCEW(IDS_CPTASK_MYCOMPUTER_TITLE)); const CResSrcStatic g_SLinkRes_MyComputer_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_MYCOMPUTER_INFOTIP)); const CPLINK_DESC g_SLink_MyComputer = { &g_SLinkRes_MyComputer_Icon, &g_SLinkRes_MyComputer_Title, &g_SLinkRes_MyComputer_Infotip, &g_LinkAction_MyComputer }; const CResSrcStatic g_SLinkRes_MyNetPlaces_Icon(MAKEINTRESOURCEW(IDI_NETCONNECT)); const CResSrcStatic g_SLinkRes_MyNetPlaces_Title(MAKEINTRESOURCEW(IDS_CPTASK_MYNETPLACES_TITLE)); const CResSrcStatic g_SLinkRes_MyNetPlaces_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_MYNETPLACES_INFOTIP)); const CPLINK_DESC g_SLink_MyNetPlaces = { &g_SLinkRes_MyNetPlaces_Icon, &g_SLinkRes_MyNetPlaces_Title, &g_SLinkRes_MyNetPlaces_Infotip, &g_LinkAction_MyNetPlaces }; const CResSrcStatic g_TLinkRes_NetConnections_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_NetConnections_Title(MAKEINTRESOURCEW(IDS_CPTASK_NETCONNECTION_TITLE)); const CResSrcStatic g_TLinkRes_NetConnections_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_NETCONNECTION_INFOTIP)); const CPLINK_DESC g_TLink_NetConnections = { &g_TLinkRes_NetConnections_Icon, &g_TLinkRes_NetConnections_Title, &g_TLinkRes_NetConnections_Infotip, &g_LinkAction_NetConnections }; const CResSrcStatic g_SLinkRes_OnScreenKbd_Icon(MAKEINTRESOURCEW(IDI_CPTASK_ONSCREENKBD)); const CResSrcStatic g_SLinkRes_OnScreenKbd_Title(MAKEINTRESOURCEW(IDS_CPTASK_ONSCREENKBD_TITLE)); const CResSrcStatic g_SLinkRes_OnScreenKbd_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_ONSCREENKBD_INFOTIP)); const CPLINK_DESC g_SLink_OnScreenKbd = { &g_SLinkRes_OnScreenKbd_Icon, &g_SLinkRes_OnScreenKbd_Title, &g_SLinkRes_OnScreenKbd_Infotip, &g_LinkAction_OnScreenKbd }; const CResSrcStatic g_SLinkRes_OtherCplOptions_Icon(MAKEINTRESOURCEW(IDI_CPCAT_OTHERCPLS)); const CResSrcStatic g_SLinkRes_OtherCplOptions_Title(MAKEINTRESOURCEW(IDS_CPCAT_OTHERCPLS_TITLE)); const CResSrcStatic g_SLinkRes_OtherCplOptions_Infotip(MAKEINTRESOURCEW(IDS_CPCAT_OTHERCPLS_INFOTIP)); const CPLINK_DESC g_SLink_OtherCplOptions = { &g_SLinkRes_OtherCplOptions_Icon, &g_SLinkRes_OtherCplOptions_Title, &g_SLinkRes_OtherCplOptions_Infotip, &g_LinkAction_OtherCplOptions }; const CResSrcStatic g_SLinkRes_PhoneModemCpl_Icon(L"telephon.cpl,0"); const CResSrcStatic g_SLinkRes_PhoneModemCpl_Title(MAKEINTRESOURCEW(IDS_CPTASK_PHONEMODEMCPL_TITLE)); const CResSrcStatic g_SLinkRes_PhoneModemCpl_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_PHONEMODEMCPL_INFOTIP)); const CPLINK_DESC g_SLink_PhoneModemCpl = { &g_SLinkRes_PhoneModemCpl_Icon, &g_SLinkRes_PhoneModemCpl_Title, &g_SLinkRes_PhoneModemCpl_Infotip, &g_LinkAction_PhoneModemCpl }; const CResSrcStatic g_SLinkRes_PowerCpl_Icon(L"powercfg.cpl,-202"); const CResSrcStatic g_SLinkRes_PowerCpl_Title(MAKEINTRESOURCEW(IDS_CPTASK_POWERCPL_TITLE)); const CResSrcStatic g_SLinkRes_PowerCpl_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_POWERCPL_INFOTIP)); const CPLINK_DESC g_SLink_PowerCpl = { &g_SLinkRes_PowerCpl_Icon, &g_SLinkRes_PowerCpl_Title, &g_SLinkRes_PowerCpl_Infotip, &g_LinkAction_PowerCpl }; const CResSrcStatic g_TLinkRes_Region_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_Region_Title(MAKEINTRESOURCEW(IDS_CPTASK_CHANGEREGION_TITLE)); const CResSrcStatic g_TLinkRes_Region_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_CHANGEREGION_INFOTIP)); const CPLINK_DESC g_TLink_Region = { &g_TLinkRes_Region_Icon, &g_TLinkRes_Region_Title, &g_TLinkRes_Region_Infotip, &g_LinkAction_Region }; const CResSrcStatic g_SLinkRes_RemoteDesktop_Icon(L"remotepg.dll,0"); const CResSrcStatic g_SLinkRes_RemoteDesktop_Title(MAKEINTRESOURCEW(IDS_CPTASK_REMOTEDESKTOP_TITLE)); const CResSrcStatic g_SLinkRes_RemoteDesktop_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_REMOTEDESKTOP_INFOTIP)); const CPLINK_DESC g_SLink_RemoteDesktop = { &g_SLinkRes_RemoteDesktop_Icon, &g_SLinkRes_RemoteDesktop_Title, &g_SLinkRes_RemoteDesktop_Infotip, &g_LinkAction_RemoteDesktop }; const CResSrcStatic g_TLinkRes_RemoveProgram_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_RemoveProgram_Title(MAKEINTRESOURCEW(IDS_CPTASK_REMOVEPROGRAM_TITLE)); const CResSrcStatic g_TLinkRes_RemoveProgram_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_REMOVEPROGRAM_INFOTIP)); const CPLINK_DESC g_TLink_RemoveProgram = { &g_TLinkRes_RemoveProgram_Icon, &g_TLinkRes_RemoveProgram_Title, &g_TLinkRes_RemoveProgram_Infotip, &g_LinkAction_RemoveProgram }; const CResSrcStatic g_TLinkRes_ScreenSaver_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_ScreenSaver_Title(MAKEINTRESOURCE(IDS_CPTASK_SCREENSAVER_TITLE)); const CResSrcStatic g_TLinkRes_ScreenSaver_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SCREENSAVER_INFOTIP)); const CPLINK_DESC g_TLink_ScreenSaver = { &g_TLinkRes_ScreenSaver_Icon, &g_TLinkRes_ScreenSaver_Title, &g_TLinkRes_ScreenSaver_Infotip, &g_LinkAction_ScreenSaver }; const CResSrcStatic g_SLinkRes_ScheduledTasks_Icon(L"mstask.dll,-100"); const CResSrcStatic g_SLinkRes_ScheduledTasks_Title(MAKEINTRESOURCEW(IDS_CPTASK_SCHEDULEDTASKS_TITLE)); const CResSrcStatic g_SLinkRes_ScheduledTasks_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SCHEDULEDTASKS_INFOTIP)); const CPLINK_DESC g_SLink_ScheduledTasks = { &g_SLinkRes_ScheduledTasks_Icon, &g_SLinkRes_ScheduledTasks_Title, &g_SLinkRes_ScheduledTasks_Infotip, &g_LinkAction_ScheduledTasks }; const CResSrcStatic g_SLinkRes_Sounds_Icon(L"mmsys.cpl,0"); const CResSrcStatic g_SLinkRes_Sounds_Title(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDSCPL_TITLE)); const CResSrcStatic g_SLinkRes_Sounds_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDSCPL_INFOTIP)); const CPLINK_DESC g_SLink_Sounds = { &g_SLinkRes_Sounds_Icon, &g_SLinkRes_Sounds_Title, &g_SLinkRes_Sounds_Infotip, &g_LinkAction_Sounds }; const CResSrcStatic g_SLinkRes_SoundAccessibility_Icon(L"mmsys.cpl,0"); const CResSrcStatic g_SLinkRes_SoundAccessibility_Title(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDACCESSIBILITY_TITLE)); const CResSrcStatic g_SLinkRes_SoundAccessibility_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDACCESSIBILITY_INFOTIP)); const CPLINK_DESC g_SLink_SoundAccessibility = { &g_SLinkRes_SoundAccessibility_Icon, &g_SLinkRes_SoundAccessibility_Title, &g_SLinkRes_SoundAccessibility_Infotip, &g_LinkAction_SoundAccessibility }; const CResSrcStatic g_TLinkRes_SoundSchemes_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_SoundSchemes_Title(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDSCHEMES_TITLE)); const CResSrcStatic g_TLinkRes_SoundSchemes_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDSCHEMES_INFOTIP)); const CPLINK_DESC g_TLink_SoundSchemes = { &g_TLinkRes_SoundSchemes_Icon, &g_TLinkRes_SoundSchemes_Title, &g_TLinkRes_SoundSchemes_Infotip, &g_LinkAction_SoundSchemes }; const CResSrcStatic g_TLinkRes_SoundVolume_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_SoundVolume_Title(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDVOLUME_TITLE)); const CResSrcStatic g_TLinkRes_SoundVolume_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDVOLUME_INFOTIP)); const CPLINK_DESC g_TLink_SoundVolume = { &g_TLinkRes_SoundVolume_Icon, &g_TLinkRes_SoundVolume_Title, &g_TLinkRes_SoundVolume_Infotip, &g_LinkAction_SoundVolume }; const CResSrcStatic g_SLinkRes_SoundVolumeAdv_Icon(L"sndvol32.exe,-300"); const CResSrcStatic g_SLinkRes_SoundVolumeAdv_Title(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDVOLUMEADV_TITLE)); const CResSrcStatic g_SLinkRes_SoundVolumeAdv_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SOUNDVOLUMEADV_INFOTIP)); const CPLINK_DESC g_SLink_SoundVolumeAdv = { &g_SLinkRes_SoundVolumeAdv_Icon, &g_SLinkRes_SoundVolumeAdv_Title, &g_SLinkRes_SoundVolumeAdv_Infotip, &g_LinkAction_SoundVolumeAdv }; const CResSrcStatic g_TLinkRes_SpeakerSettings_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_SpeakerSettings_Title(MAKEINTRESOURCEW(IDS_CPTASK_SPEAKERSETTINGS_TITLE)); const CResSrcStatic g_TLinkRes_SpeakerSettings_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SPEAKERSETTINGS_INFOTIP)); const CPLINK_DESC g_TLink_SpeakerSettings = { &g_TLinkRes_SpeakerSettings_Icon, &g_TLinkRes_SpeakerSettings_Title, &g_TLinkRes_SpeakerSettings_Infotip, &g_LinkAction_SoundVolume }; const CResSrcStatic g_SLinkRes_SystemCpl_Icon(L"sysdm.cpl,0"); const CResSrcStatic g_SLinkRes_SystemCpl_Title(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMCPL_TITLE)); const CResSrcStatic g_SLinkRes_SystemCpl_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMCPL_INFOTIP)); const CPLINK_DESC g_SLink_SystemCpl = { &g_SLinkRes_SystemCpl_Icon, &g_SLinkRes_SystemCpl_Title, &g_SLinkRes_SystemCpl_Infotip, &g_LinkAction_SystemCpl }; const CResSrcStatic g_TLinkRes_SystemCpl_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_SystemCpl_Title(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMCPL_TITLE2)); const CResSrcStatic g_TLinkRes_SystemCpl_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMCPL_INFOTIP2)); const CPLINK_DESC g_TLink_SystemCpl = { &g_TLinkRes_SystemCpl_Icon, &g_TLinkRes_SystemCpl_Title, &g_TLinkRes_SystemCpl_Infotip, &g_LinkAction_SystemCpl }; const CResSrcStatic g_SLinkRes_SystemRestore_Icon(L"%systemroot%\\system32\\restore\\rstrui.exe,0"); const CResSrcStatic g_SLinkRes_SystemRestore_Title(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMRESTORE_TITLE)); const CResSrcStatic g_SLinkRes_SystemRestore_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SYSTEMRESTORE_INFOTIP)); const CPLINK_DESC g_SLink_SystemRestore = { &g_SLinkRes_SystemRestore_Icon, &g_SLinkRes_SystemRestore_Title, &g_SLinkRes_SystemRestore_Infotip, &g_LinkAction_SystemRestore }; const CResSrcStatic g_SLinkRes_SwToCategoryView_Icon(MAKEINTRESOURCEW(IDI_CPLFLD)); const CResSrcStatic g_SLinkRes_SwToCategoryView_Title(MAKEINTRESOURCEW(IDS_CPTASK_SWITCHTOCATEGORYVIEW_TITLE)); const CResSrcStatic g_SLinkRes_SwToCategoryView_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SWITCHTOCATEGORYVIEW_INFOTIP)); const CPLINK_DESC g_SLink_SwToCategoryView = { &g_SLinkRes_SwToCategoryView_Icon, &g_SLinkRes_SwToCategoryView_Title, &g_SLinkRes_SwToCategoryView_Infotip, &g_LinkAction_SwToCategoryView }; const CResSrcStatic g_SLinkRes_SwToClassicView_Icon(MAKEINTRESOURCEW(IDI_CPLFLD)); const CResSrcStatic g_SLinkRes_SwToClassicView_Title(MAKEINTRESOURCEW(IDS_CPTASK_SWITCHTOCLASSICVIEW_TITLE)); const CResSrcStatic g_SLinkRes_SwToClassicView_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_SWITCHTOCLASSICVIEW_INFOTIP)); const CPLINK_DESC g_SLink_SwToClassicView = { &g_SLinkRes_SwToClassicView_Icon, &g_SLinkRes_SwToClassicView_Title, &g_SLinkRes_SwToClassicView_Infotip, &g_LinkAction_SwToClassicView }; const CResSrcStatic g_SLinkRes_TsDisplay_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsDisplay_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSDISPLAY_TITLE)); const CResSrcStatic g_SLinkRes_TsDisplay_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSDISPLAY_INFOTIP)); const CPLINK_DESC g_SLink_TsDisplay = { &g_SLinkRes_TsDisplay_Icon, &g_SLinkRes_TsDisplay_Title, &g_SLinkRes_TsDisplay_Infotip, &g_LinkAction_TsDisplay }; const CResSrcStatic g_SLinkRes_TsDvd_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsDvd_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSDVD_TITLE)); const CResSrcStatic g_SLinkRes_TsDvd_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSDVD_INFOTIP)); const CPLINK_DESC g_SLink_TsDvd = { &g_SLinkRes_TsDvd_Icon, &g_SLinkRes_TsDvd_Title, &g_SLinkRes_TsDvd_Infotip, &g_LinkAction_TsDvd }; const CResSrcStatic g_SLinkRes_TsHardware_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsHardware_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSHARDWARE_TITLE)); const CResSrcStatic g_SLinkRes_TsHardware_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSHARDWARE_INFOTIP)); const CPLINK_DESC g_SLink_TsHardware = { &g_SLinkRes_TsHardware_Icon, &g_SLinkRes_TsHardware_Title, &g_SLinkRes_TsHardware_Infotip, &g_LinkAction_TsHardware }; const CResSrcStatic g_SLinkRes_TsInetExplorer_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsInetExplorer_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSINETEXPLORER_TITLE)); const CResSrcStatic g_SLinkRes_TsInetExplorer_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSINETEXPLORER_INFOTIP)); const CPLINK_DESC g_SLink_TsInetExplorer = { &g_SLinkRes_TsInetExplorer_Icon, &g_SLinkRes_TsInetExplorer_Title, &g_SLinkRes_TsInetExplorer_Infotip, &g_LinkAction_TsInetExplorer }; const CResSrcStatic g_SLinkRes_TsModem_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsModem_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSMODEM_TITLE)); const CResSrcStatic g_SLinkRes_TsModem_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSMODEM_INFOTIP)); const CPLINK_DESC g_SLink_TsModem = { &g_SLinkRes_TsModem_Icon, &g_SLinkRes_TsModem_Title, &g_SLinkRes_TsModem_Infotip, &g_LinkAction_TsModem }; const CResSrcStatic g_SLinkRes_TsNetDiags_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsNetDiags_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSNETDIAGS_TITLE)); const CResSrcStatic g_SLinkRes_TsNetDiags_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSNETDIAGS_INFOTIP)); const CPLINK_DESC g_SLink_TsNetDiags = { &g_SLinkRes_TsNetDiags_Icon, &g_SLinkRes_TsNetDiags_Title, &g_SLinkRes_TsNetDiags_Infotip, &g_LinkAction_TsNetDiags }; const CResSrcStatic g_SLinkRes_TsNetwork_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcFunc g_SLinkRes_TsNetwork_Title(GetTsNetworkTitle); const CResSrcStatic g_SLinkRes_TsNetwork_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSNETWORK_INFOTIP)); const CPLINK_DESC g_SLink_TsNetwork = { &g_SLinkRes_TsNetwork_Icon, &g_SLinkRes_TsNetwork_Title, &g_SLinkRes_TsNetwork_Infotip, &g_LinkAction_TsNetwork }; const CResSrcStatic g_SLinkRes_TsPrinting_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsPrinting_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSPRINTING_TITLE)); const CResSrcStatic g_SLinkRes_TsPrinting_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSPRINTING_INFOTIP)); const CPLINK_DESC g_SLink_TsPrinting = { &g_SLinkRes_TsPrinting_Icon, &g_SLinkRes_TsPrinting_Title, &g_SLinkRes_TsPrinting_Infotip, &g_LinkAction_TsPrinting }; const CResSrcStatic g_SLinkRes_TsSharing_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsSharing_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSFILESHARING_TITLE)); const CResSrcStatic g_SLinkRes_TsSharing_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSFILESHARING_INFOTIP)); const CPLINK_DESC g_SLink_TsSharing = { &g_SLinkRes_TsSharing_Icon, &g_SLinkRes_TsSharing_Title, &g_SLinkRes_TsSharing_Infotip, &g_LinkAction_TsSharing }; const CResSrcStatic g_SLinkRes_TsSound_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsSound_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSSOUND_TITLE)); const CResSrcStatic g_SLinkRes_TsSound_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSSOUND_INFOTIP)); const CPLINK_DESC g_SLink_TsSound = { &g_SLinkRes_TsSound_Icon, &g_SLinkRes_TsSound_Title, &g_SLinkRes_TsSound_Infotip, &g_LinkAction_TsSound }; const CResSrcStatic g_SLinkRes_TsStartup_Icon(MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER)); const CResSrcStatic g_SLinkRes_TsStartup_Title(MAKEINTRESOURCEW(IDS_CPTASK_TSSTARTUP_TITLE)); const CResSrcStatic g_SLinkRes_TsStartup_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_TSSTARTUP_INFOTIP)); const CPLINK_DESC g_SLink_TsStartup = { &g_SLinkRes_TsStartup_Icon, &g_SLinkRes_TsStartup_Title, &g_SLinkRes_TsStartup_Infotip, &g_LinkAction_TsStartup }; const CResSrcStatic g_TLinkRes_ViewPrinters_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_ViewPrinters_Title(MAKEINTRESOURCEW(IDS_CPTASK_VIEWPRINTERS_TITLE)); const CResSrcStatic g_TLinkRes_ViewPrinters_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_VIEWPRINTERS_INFOTIP)); const CPLINK_DESC g_TLink_ViewPrinters = { &g_TLinkRes_ViewPrinters_Icon, &g_TLinkRes_ViewPrinters_Title, &g_TLinkRes_ViewPrinters_Infotip, &g_LinkAction_ViewPrinters }; const CResSrcStatic g_TLinkRes_VisualPerf_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_VisualPerf_Title(MAKEINTRESOURCEW(IDS_CPTASK_VISUALPERF_TITLE)); const CResSrcStatic g_TLinkRes_VisualPerf_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_VISUALPERF_INFOTIP)); const CPLINK_DESC g_TLink_VisualPerf = { &g_TLinkRes_VisualPerf_Icon, &g_TLinkRes_VisualPerf_Title, &g_TLinkRes_VisualPerf_Infotip, &g_LinkAction_VisualPerf }; const CResSrcStatic g_TLinkRes_VpnConnections_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_VpnConnections_Title(MAKEINTRESOURCEW(IDS_CPTASK_VPNCONNECTION_TITLE)); const CResSrcStatic g_TLinkRes_VpnConnections_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_VPNCONNECTION_INFOTIP)); const CPLINK_DESC g_TLink_VpnConnections = { &g_TLinkRes_VpnConnections_Icon, &g_TLinkRes_VpnConnections_Title, &g_TLinkRes_VpnConnections_Infotip, &g_LinkAction_VpnConnections }; const CResSrcStatic g_TLinkRes_Wallpaper_Icon(MAKEINTRESOURCEW(IDI_CP_CATEGORYTASK)); const CResSrcStatic g_TLinkRes_Wallpaper_Title(MAKEINTRESOURCEW(IDS_CPTASK_WALLPAPER_TITLE)); const CResSrcStatic g_TLinkRes_Wallpaper_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_WALLPAPER_INFOTIP)); const CPLINK_DESC g_TLink_Wallpaper = { &g_TLinkRes_Wallpaper_Icon, &g_TLinkRes_Wallpaper_Title, &g_TLinkRes_Wallpaper_Infotip, &g_LinkAction_Wallpaper }; const CResSrcStatic g_SLinkRes_WindowsUpdate_Icon(MAKEINTRESOURCEW(IDI_WINUPDATE)); const CResSrcStatic g_SLinkRes_WindowsUpdate_Title(MAKEINTRESOURCEW(IDS_CPTASK_WINDOWSUPDATE_TITLE)); const CResSrcStatic g_SLinkRes_WindowsUpdate_Infotip(MAKEINTRESOURCEW(IDS_CPTASK_WINDOWSUPDATE_INFOTIP)); const CPLINK_DESC g_SLink_WindowsUpdate = { &g_SLinkRes_WindowsUpdate_Icon, &g_SLinkRes_WindowsUpdate_Title, &g_SLinkRes_WindowsUpdate_Infotip, &g_LinkAction_WindowsUpdate }; //----------------------------------------------------------------------------- // View page definitions. //----------------------------------------------------------------------------- // // Main Control Panel page. // const CPLINK_DESC *g_rgpLink_Cpl_SeeAlso[] = { &g_SLink_WindowsUpdate, &g_SLink_HelpAndSupport, &g_SLink_32CtrlPanel, &g_SLink_OtherCplOptions, NULL }; const CPLINK_DESC *g_rgpLink_Cpl_SwToClassicView[] = { &g_SLink_SwToClassicView, NULL }; const CPLINK_DESC *g_rgpLink_Cpl_SwToCategoryView[] = { &g_SLink_SwToCategoryView, NULL }; // // Accounts category // const CPLINK_DESC *g_rgpLink_Accounts_Tasks[] = { &g_TLink_AccountsChange, &g_TLink_AccountsCreate, // Active on non-server SKU &g_TLink_AccountsCreate2, // Active on server SKU &g_TLink_AccountsPict, NULL }; const CPLINK_DESC *g_rgpLink_Accounts_SeeAlso[] = { &g_TLink_CatAppearance, NULL }; const CPLINK_DESC *g_rgpLink_Accounts_LearnAbout[] = { &g_SLink_LearnAccounts, &g_SLink_LearnAccountsTypes, &g_SLink_LearnAccountsChangeName, &g_SLink_LearnAccountsCreate, &g_SLink_LearnSwitchUsers, NULL }; const CPCAT_DESC g_Category_Accounts = { eCPCAT_ACCOUNTS, L"Security_and_User_Accounts", &g_TLink_CatAccounts, g_rgpLink_Accounts_Tasks, { g_rgpLink_Accounts_SeeAlso, NULL, g_rgpLink_Accounts_LearnAbout } }; // // Accessibility category // const CPLINK_DESC *g_rgpLink_Accessibility_Tasks[] = { &g_TLink_HighContrast, &g_TLink_AccessWizard, NULL }; const CPLINK_DESC *g_rgpLink_Accessibility_SeeAlso[] = { &g_SLink_Magnifier, &g_SLink_OnScreenKbd, NULL }; const CPCAT_DESC g_Category_Accessibility = { eCPCAT_ACCESSIBILITY, L"Accessibility", &g_TLink_CatAccessibility, g_rgpLink_Accessibility_Tasks, { g_rgpLink_Accessibility_SeeAlso, NULL, NULL }, }; // // Appearance category // const CPLINK_DESC *g_rgpLink_Appearance_Tasks[] = { &g_TLink_DisplayTheme, &g_TLink_Wallpaper, &g_TLink_ScreenSaver, &g_TLink_DisplayRes, NULL }; const CPLINK_DESC *g_rgpLink_Appearance_SeeAlso[] = { &g_SLink_FontsFolder, &g_SLink_MousePointers, &g_SLink_HighContrast, &g_SLink_AccountsPict, NULL }; const CPLINK_DESC *g_rgpLink_Appearance_Troubleshoot[] = { &g_SLink_TsDisplay, &g_SLink_TsSound, NULL }; const CPCAT_DESC g_Category_Appearance = { eCPCAT_APPEARANCE, L"Appearance_and_Themes", &g_TLink_CatAppearance, g_rgpLink_Appearance_Tasks, { g_rgpLink_Appearance_SeeAlso, g_rgpLink_Appearance_Troubleshoot, NULL } }; // // Add/Remove Programs (aka ARP) category // const CPLINK_DESC *g_rgpLink_Arp_SeeAlso[] = { &g_SLink_WindowsUpdate, &g_SLink_AutoUpdate, NULL }; const CPLINK_DESC *g_rgpLink_Arp_Tasks[] = { &g_TLink_AddProgram, &g_TLink_RemoveProgram, NULL }; const CPCAT_DESC g_Category_Arp = { eCPCAT_ARP, L"Add_or_Remove_Programs", &g_TLink_CatArp, g_rgpLink_Arp_Tasks, { g_rgpLink_Arp_SeeAlso, NULL, NULL }, }; // // Hardware category // const CPLINK_DESC *g_rgpLink_Hardware_Tasks[] = { &g_TLink_ViewPrinters, &g_TLink_AddPrinter, NULL }; const CPLINK_DESC *g_rgpLink_Hardware_SeeAlso[] = { &g_SLink_HardwareWizard, &g_SLink_DisplayCpl, &g_SLink_Sounds, &g_SLink_PowerCpl, &g_SLink_SystemCpl, NULL }; const CPLINK_DESC *g_rgpLink_Hardware_Troubleshoot[] = { &g_SLink_TsHardware, &g_SLink_TsPrinting, &g_SLink_TsNetwork, NULL }; const CPCAT_DESC g_Category_Hardware = { eCPCAT_HARDWARE, L"Printers_and_Other_Hardware", &g_TLink_CatHardware, g_rgpLink_Hardware_Tasks, { g_rgpLink_Hardware_SeeAlso, g_rgpLink_Hardware_Troubleshoot, NULL } }; // // Network category // const CPLINK_DESC *g_rgpLink_Network_Tasks[] = { &g_TLink_NetConnections, &g_TLink_VpnConnections, &g_TLink_HomeNetWizard, NULL }; const CPLINK_DESC *g_rgpLink_Network_SeeAlso[] = { &g_SLink_MyNetPlaces, &g_SLink_Hardware, &g_SLink_RemoteDesktop, &g_SLink_PhoneModemCpl, NULL }; const CPLINK_DESC *g_rgpLink_Network_Troubleshoot[] = { &g_SLink_TsNetwork, // Pro/Personal only. &g_SLink_TsInetExplorer, // Pro/Personal only. &g_SLink_TsSharing, // Server only. &g_SLink_TsModem, // Server only. &g_SLink_TsNetDiags, // All SKUs. NULL }; const CPCAT_DESC g_Category_Network = { eCPCAT_NETWORK, L"Network_Connections", &g_TLink_CatNetwork, g_rgpLink_Network_Tasks, { g_rgpLink_Network_SeeAlso, g_rgpLink_Network_Troubleshoot, NULL } }; // // Other CPLs category // const CPLINK_DESC *g_rgpLink_Other_SeeAlso[] = { &g_SLink_WindowsUpdate, &g_SLink_HelpAndSupport, NULL }; const CPCAT_DESC g_Category_Other = { eCPCAT_OTHER, NULL, // "Other" uses std Control Panel help topic. &g_TLink_CatOther, NULL, { g_rgpLink_Other_SeeAlso, NULL, NULL } }; // // PerfMaint category // const CPLINK_DESC *g_rgpLink_PerfMaint_Tasks[] = { &g_TLink_SystemCpl, &g_TLink_VisualPerf, &g_TLink_CleanUpDisk, &g_TLink_BackupData, &g_TLink_Defrag, NULL }; const CPLINK_DESC *g_rgpLink_PerfMaint_SeeAlso[] = { &g_SLink_FileTypes, &g_SLink_SystemRestore, NULL }; const CPLINK_DESC *g_rgpLink_PerfMaint_Troubleshoot[] = { &g_SLink_TsStartup, NULL }; const CPCAT_DESC g_Category_PerfMaint = { eCPCAT_PERFMAINT, L"Performance_and_Maintenance", &g_TLink_CatPerfMaint, g_rgpLink_PerfMaint_Tasks, { g_rgpLink_PerfMaint_SeeAlso, g_rgpLink_PerfMaint_Troubleshoot, NULL }, }; // // Regional category // const CPLINK_DESC *g_rgpLink_Regional_Tasks[] = { &g_TLink_DateTime, &g_TLink_Region, &g_TLink_Language, NULL }; const CPLINK_DESC *g_rgpLink_Regional_SeeAlso[] = { &g_SLink_ScheduledTasks, NULL }; const CPCAT_DESC g_Category_Regional = { eCPCAT_REGIONAL, L"Date__Time__Language_and_Regional_Settings", &g_TLink_CatRegional, g_rgpLink_Regional_Tasks, { g_rgpLink_Regional_SeeAlso, NULL, NULL }, }; // // Sound category // const CPLINK_DESC *g_rgpLink_Sound_Tasks[] = { &g_TLink_SoundVolume, &g_TLink_SoundSchemes, &g_TLink_SpeakerSettings, NULL }; const CPLINK_DESC *g_rgpLink_Sound_SeeAlso[] = { &g_SLink_SoundAccessibility, &g_SLink_SoundVolumeAdv, NULL }; const CPLINK_DESC *g_rgpLink_Sound_Troubleshoot[] = { &g_SLink_TsSound, &g_SLink_TsDvd, NULL }; const CPCAT_DESC g_Category_Sound = { eCPCAT_SOUND, L"Sounds__Speech_and_Audio_Devices", &g_TLink_CatSound, g_rgpLink_Sound_Tasks, { g_rgpLink_Sound_SeeAlso, g_rgpLink_Sound_Troubleshoot, NULL } }; // // ********* IMPORTANT ********** // // The order of these entries MUST match up with the category ID // values in the cCPCAT enumeration. These IDs also map directly // to the SCID_CONTROLPANELCATEGORY value stored for each CPL // applet in the registry. // // Code using a category ID will map directly to this array. // Order of display in the Category selection view is handled // by the function CCplView::_DisplayIndexToCategoryIndex in // cpview.cpp. // const CPCAT_DESC *g_rgpCplCatInfo[] = { &g_Category_Other, &g_Category_Appearance, &g_Category_Hardware, &g_Category_Network, &g_Category_Sound, &g_Category_PerfMaint, &g_Category_Regional, &g_Category_Accessibility, &g_Category_Arp, &g_Category_Accounts, NULL, }; //----------------------------------------------------------------------------- // Helper functions used in support of the namespace. //----------------------------------------------------------------------------- // // Copy one DPA of IUICommand ptrs to another. // Returns: // S_OK - All items copied. // Error - Something failed. // HRESULT CplNamespace_CopyCommandArray( const CDpaUiCommand& rgFrom, CDpaUiCommand *prgTo ) { ASSERT(NULL != prgTo); ASSERT(0 == prgTo->Count()); HRESULT hr = S_OK; const int cCommands = rgFrom.Count(); for (int i = 0; i < cCommands && SUCCEEDED(hr); i++) { IUICommand *pc = const_cast(rgFrom.Get(i)); ASSERT(NULL != pc); if (-1 != prgTo->Append(pc)) { pc->AddRef(); } else { hr = E_OUTOFMEMORY; } } return THR(hr); } // // Create a new IUICommand object from a CPLINK_DESC structure. // HRESULT CplNamespace_CreateUiCommand( IUnknown *punkSite, const CPLINK_DESC& ld, IUICommand **ppc ) { ASSERT(NULL != ppc); ASSERT(!IsBadWritePtr(ppc, sizeof(*ppc))); *ppc = NULL; ICplNamespace *pns; HRESULT hr = IUnknown_QueryService(punkSite, SID_SControlPanelView, IID_ICplNamespace, (void **)&pns); if (SUCCEEDED(hr)) { hr = CPL::Create_CplUiCommand(ld.prsrcName->GetResource(pns), ld.prsrcInfotip->GetResource(pns), ld.prsrcIcon->GetResource(pns), ld.pAction, IID_IUICommand, (void **)ppc); pns->Release(); } return THR(hr); } // // Create a new IUIElement object for a given webview type. // The returned IUIElement object represents the header for // the requested webview menu. // HRESULT CplNamespace_CreateWebViewHeaderElement( eCPWVTYPE eType, IUIElement **ppele ) { ASSERT(0 <= eType && eCPWVTYPE_NUMTYPES > eType); ASSERT(NULL != ppele); ASSERT(!IsBadWritePtr(ppele, sizeof(*ppele))); static const struct { LPCWSTR pszName; LPCWSTR pszInfotip; LPCWSTR pszIcon; } rgHeaderInfo[] = { // // eCPWVTYPE_CPANEL // { MAKEINTRESOURCEW(IDS_CONTROLPANEL), MAKEINTRESOURCEW(IDS_CPTASK_CONTROLPANEL_INFOTIP), MAKEINTRESOURCEW(IDI_CPLFLD) }, // // eCPWVTYPE_SEEALSO // { MAKEINTRESOURCEW(IDS_CPTASK_SEEALSO_TITLE), MAKEINTRESOURCEW(IDS_CPTASK_SEEALSO_INFOTIP), MAKEINTRESOURCEW(IDI_CPTASK_SEEALSO) }, // // eCPWVTYPE_TROUBLESHOOTER // { MAKEINTRESOURCEW(IDS_CPTASK_TROUBLESHOOTER_TITLE), MAKEINTRESOURCEW(IDS_CPTASK_TROUBLESHOOTER_INFOTIP), MAKEINTRESOURCEW(IDI_CPTASK_TROUBLESHOOTER) }, // // eCPWVTYPE_LEARNABOUT // { MAKEINTRESOURCEW(IDS_CPTASK_LEARNABOUT_TITLE), MAKEINTRESOURCEW(IDS_CPTASK_LEARNABOUT_INFOTIP), MAKEINTRESOURCEW(IDI_CPTASK_LEARNABOUT) } }; *ppele = NULL; HRESULT hr = Create_CplUiElement(rgHeaderInfo[eType].pszName, rgHeaderInfo[eType].pszInfotip, rgHeaderInfo[eType].pszIcon, IID_IUIElement, (void **)ppele); return THR(hr); } //----------------------------------------------------------------------------- // UI Command Enumeration //----------------------------------------------------------------------------- class IEnumCommandBase { public: virtual ~IEnumCommandBase() { } virtual HRESULT Next(IUnknown *punkSite, IUICommand **ppc) = 0; virtual HRESULT Skip(ULONG n) = 0; virtual HRESULT Reset(void) = 0; virtual HRESULT Clone(IEnumCommandBase **ppEnum) = 0; }; // // Used to enumerate UI Command objects that originate from static // initialization information in the CPL namespace. // class CEnumCommand_LinkDesc : public IEnumCommandBase { public: CEnumCommand_LinkDesc(const CPLINK_DESC **ppld); ~CEnumCommand_LinkDesc(void); HRESULT Next(IUnknown *punkSite, IUICommand **ppc); HRESULT Skip(ULONG n); HRESULT Reset(void); HRESULT Clone(IEnumCommandBase **ppEnum); private: const CPLINK_DESC ** const m_ppldFirst; // First item in descriptor array. const CPLINK_DESC **m_ppldCurrent; // 'Current' item referenced. }; // // Used to enumerate UI Command objects that already exist in // a DPA of IUICommand pointers. In particular, this is used // to enumerate the UICommand objects that represent CPL applets // in the user interface. // class CEnumCommand_Array : public IEnumCommandBase { public: CEnumCommand_Array(void); ~CEnumCommand_Array(void); HRESULT Next(IUnknown *punkSite, IUICommand **ppc); HRESULT Skip(ULONG n); HRESULT Reset(void); HRESULT Clone(IEnumCommandBase **ppEnum); HRESULT Initialize(const CDpaUiCommand& rgCommands); private: CDpaUiCommand m_rgCommands; // DPA of IUICommand ptrs. int m_iCurrent; // 'Current' item in enumeration. // // Prevent copy. // CEnumCommand_Array(const CEnumCommand_Array& rhs); // not implemented. CEnumCommand_Array& operator = (const CEnumCommand_Array& rhs); // not implemented. }; //----------------------------------------------------------------------------- // CEnumCommand_LinkDesc implementation. //----------------------------------------------------------------------------- CEnumCommand_LinkDesc::CEnumCommand_LinkDesc( const CPLINK_DESC **ppld ) : m_ppldFirst(ppld), m_ppldCurrent(ppld) { TraceMsg(TF_LIFE, "CEnumCommand_LinkDesc::CEnumCommand_LinkDesc, this = 0x%x", this); } CEnumCommand_LinkDesc::~CEnumCommand_LinkDesc( void ) { TraceMsg(TF_LIFE, "CEnumCommand_LinkDesc::~CEnumCommand_LinkDesc, this = 0x%x", this); } HRESULT CEnumCommand_LinkDesc::Next( IUnknown *punkSite, IUICommand **ppc ) { ASSERT(NULL != ppc); ASSERT(!IsBadWritePtr(ppc, sizeof(*ppc))); HRESULT hr = S_FALSE; if (NULL != m_ppldCurrent && NULL != *m_ppldCurrent) { hr = CplNamespace_CreateUiCommand(punkSite, **m_ppldCurrent, ppc); m_ppldCurrent++; } return THR(hr); } HRESULT CEnumCommand_LinkDesc::Reset( void ) { m_ppldCurrent = m_ppldFirst; return S_OK; } HRESULT CEnumCommand_LinkDesc::Skip( ULONG n ) { if (NULL != m_ppldCurrent) { while(0 < n-- && NULL != *m_ppldCurrent) { m_ppldCurrent++; } } return 0 == n ? S_OK : S_FALSE; } HRESULT CEnumCommand_LinkDesc::Clone( IEnumCommandBase **ppenum ) { ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); HRESULT hr = E_OUTOFMEMORY; *ppenum = new CEnumCommand_LinkDesc(m_ppldFirst); if (NULL != *ppenum) { hr = S_OK; } return THR(hr); } //----------------------------------------------------------------------------- // CEnumCommand_Array implementation. //----------------------------------------------------------------------------- CEnumCommand_Array::CEnumCommand_Array( void ) : m_iCurrent(0) { TraceMsg(TF_LIFE, "CEnumCommand_Array::CEnumCommand_Array, this = 0x%x", this); } CEnumCommand_Array::~CEnumCommand_Array( void ) { TraceMsg(TF_LIFE, "CEnumCommand_Array::~CEnumCommand_Array, this = 0x%x", this); } HRESULT CEnumCommand_Array::Initialize( const CDpaUiCommand& rgCommands ) { ASSERT(0 == m_rgCommands.Count()); ASSERT(0 == m_iCurrent); HRESULT hr = CplNamespace_CopyCommandArray(rgCommands, &m_rgCommands); return THR(hr); } HRESULT CEnumCommand_Array::Next( IUnknown *punkSite, IUICommand **ppc ) { ASSERT(NULL != ppc); ASSERT(!IsBadWritePtr(ppc, sizeof(*ppc))); UNREFERENCED_PARAMETER(punkSite); HRESULT hr = S_FALSE; if (m_iCurrent < m_rgCommands.Count()) { *ppc = m_rgCommands.Get(m_iCurrent++); ASSERT(NULL != *ppc); (*ppc)->AddRef(); hr = S_OK; } return THR(hr); } HRESULT CEnumCommand_Array::Reset( void ) { m_iCurrent = 0; return S_OK; } HRESULT CEnumCommand_Array::Skip( ULONG n ) { while(0 < n-- && m_iCurrent < m_rgCommands.Count()) { m_iCurrent++; } return 0 == n ? S_OK : S_FALSE; } HRESULT CEnumCommand_Array::Clone( IEnumCommandBase **ppenum ) { ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); HRESULT hr = E_OUTOFMEMORY; *ppenum = new CEnumCommand_Array(); if (NULL != *ppenum) { hr = static_cast(*ppenum)->Initialize(m_rgCommands); if (FAILED(hr)) { delete *ppenum; *ppenum = NULL; } } return THR(hr); } //----------------------------------------------------------------------------- // CEnumCommand //----------------------------------------------------------------------------- // // Enumerates IUICommand pointers for UICommand objects in the // Control Panel namespace. // class CEnumCommand : public CObjectWithSite, public IEnumUICommand { public: ~CEnumCommand(void); // // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // // IEnumUICommand // STDMETHOD(Next)(ULONG celt, IUICommand **pUICommand, ULONG *pceltFetched); STDMETHOD(Skip)(ULONG celt); STDMETHOD(Reset)(void); STDMETHOD(Clone)(IEnumUICommand **ppenum); static HRESULT CreateInstance(IUnknown *punkSite, const CPLINK_DESC **ppld, REFIID riid, void **ppvEnum); static HRESULT CreateInstance(IUnknown *punkSite, const CDpaUiCommand& rgCommands, REFIID riid, void **ppvEnum); private: LONG m_cRef; IEnumCommandBase *m_pImpl; // Ptr to actual implementation. CEnumCommand(void); // // Prevent copy. // CEnumCommand(const CEnumCommand& rhs); // not implemented. CEnumCommand& operator = (const CEnumCommand& rhs); // not implemented. bool _IsRestricted(IUICommand *puic); }; CEnumCommand::CEnumCommand( void ) : m_cRef(1), m_pImpl(NULL) { TraceMsg(TF_LIFE, "CEnumCommand::CEnumCommand, this = 0x%x", this); } CEnumCommand::~CEnumCommand( void ) { TraceMsg(TF_LIFE, "CEnumCommand::~CEnumCommand, this = 0x%x", this); delete m_pImpl; } // // Creates a command enumerator from an array of link descriptions // in the CPL namespace. // HRESULT CEnumCommand::CreateInstance( IUnknown *punkSite, const CPLINK_DESC **ppld, REFIID riid, void **ppvOut ) { // // Note that ppld can be NULL. It simply results in an // empty enumerator. // ASSERT(NULL != punkSite); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CEnumCommand *pec = new CEnumCommand(); if (NULL != pec) { pec->m_pImpl = new CEnumCommand_LinkDesc(ppld); if (NULL != pec->m_pImpl) { hr = pec->QueryInterface(riid, ppvOut); if (SUCCEEDED(hr)) { hr = IUnknown_SetSite(static_cast(*ppvOut), punkSite); } } pec->Release(); } return THR(hr); } // // Creates a command enumerator from a DPA of IUICommand ptrs. // HRESULT CEnumCommand::CreateInstance( IUnknown *punkSite, const CDpaUiCommand& rgCommands, REFIID riid, void **ppvOut ) { ASSERT(NULL != punkSite); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CEnumCommand *pec = new CEnumCommand(); if (NULL != pec) { pec->m_pImpl = new CEnumCommand_Array(); if (NULL != pec->m_pImpl) { hr = static_cast(pec->m_pImpl)->Initialize(rgCommands); if (SUCCEEDED(hr)) { hr = pec->QueryInterface(riid, ppvOut); if (SUCCEEDED(hr)) { hr = IUnknown_SetSite(static_cast(*ppvOut), punkSite); } } } pec->Release(); } return THR(hr); } STDMETHODIMP CEnumCommand::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv))); static const QITAB qit[] = { QITABENT(CEnumCommand, IEnumUICommand), QITABENT(CEnumCommand, IObjectWithSite), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); return E_NOINTERFACE == hr ? hr : THR(hr); } STDMETHODIMP_(ULONG) CEnumCommand::AddRef( void ) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CEnumCommand::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CEnumCommand::Next( ULONG celt, IUICommand **ppUICommand, ULONG *pceltFetched ) { ASSERT(NULL != ppUICommand); ASSERT(!IsBadWritePtr(ppUICommand, sizeof(*ppUICommand) * celt)); ASSERT(NULL != m_pImpl); HRESULT hr = S_OK; ULONG celtFetched = 0; while(S_OK == hr && 0 < celt) { ASSERT(NULL != CObjectWithSite::_punkSite); IUICommand *puic; // // This is a little weird. I pass the site ptr to the // Next() method but then also set the returned object's // site when it's returned by Next(). Why not just set // the site in the Next() implementation? Next() needs the site // ptr to pass through to any IResSrc::GetResource implementation // when retrieving the resources for any given UI command object. // This is because the resource used can vary depending upon state // information stored in the namespace. However, to simplify // lifetime management, I want to 'set' the site on the returned // objects in only one place; this place. That way, the derived // enumerator instance attached to m_pImpl doesn't need to worry // about setting the site. We do it in one place for all // implementations. [brianau - 3/16/01] // hr = m_pImpl->Next(CObjectWithSite::_punkSite, &puic); if (S_OK == hr) { // // It's important that we set the object's 'site' before // checking the restriction. The restriction checking // code requires access to the CplNamespace which is obtained // through the site. // hr = IUnknown_SetSite(puic, CObjectWithSite::_punkSite); if (SUCCEEDED(hr)) { if (!_IsRestricted(puic)) { celt--; celtFetched++; (*ppUICommand++ = puic)->AddRef(); } } puic->Release(); } } if (NULL != pceltFetched) { *pceltFetched = celtFetched; } return THR(hr); } STDMETHODIMP CEnumCommand::Skip( ULONG celt ) { ASSERT(NULL != m_pImpl); HRESULT hr = m_pImpl->Skip(celt); return THR(hr); } STDMETHODIMP CEnumCommand::Reset( void ) { ASSERT(NULL != m_pImpl); HRESULT hr = m_pImpl->Reset(); return THR(hr); } STDMETHODIMP CEnumCommand::Clone( IEnumUICommand **ppenum ) { ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); ASSERT(NULL != m_pImpl); *ppenum = NULL; HRESULT hr = E_OUTOFMEMORY; CEnumCommand *pe = new CEnumCommand(); if (NULL != pe) { hr = m_pImpl->Clone(&(pe->m_pImpl)); if (SUCCEEDED(hr)) { hr = pe->QueryInterface(IID_IEnumUICommand, (void **)ppenum); } pe->Release(); } return THR(hr); } bool CEnumCommand::_IsRestricted( IUICommand *puic ) { ASSERT(NULL != puic); bool bRestricted = false; UISTATE uis; HRESULT hr = puic->get_State(NULL, TRUE, &uis); if (SUCCEEDED(hr)) { if (UIS_HIDDEN == uis) { bRestricted = true; } } return bRestricted; } //----------------------------------------------------------------------------- // CCplWebViewInfo //----------------------------------------------------------------------------- class CCplWebViewInfo : public ICplWebViewInfo { public: ~CCplWebViewInfo(void); // // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // // IEnumCplWebViewInfo // STDMETHOD(get_Header)(IUIElement **ppele); STDMETHOD(get_Style)(DWORD *pdwFlags); STDMETHOD(EnumTasks)(IEnumUICommand **ppenum); static HRESULT CreateInstance(IUIElement *peHeader, IEnumUICommand *penum, DWORD dwStyle, REFIID riid, void **ppvOut); private: LONG m_cRef; IUIElement *m_peHeader; // The webview menu header. IEnumUICommand *m_penumUiCommand; // The webview menu tasks. DWORD m_dwStyle; // Style flags. CCplWebViewInfo(void); }; CCplWebViewInfo::CCplWebViewInfo( void ) : m_cRef(1), m_peHeader(NULL), m_penumUiCommand(NULL), m_dwStyle(0) { TraceMsg(TF_LIFE, "CCplWebViewInfo::CCplWebViewInfo, this = 0x%x", this); } CCplWebViewInfo::~CCplWebViewInfo( void ) { TraceMsg(TF_LIFE, "CCplWebViewInfo::~CCplWebViewInfo, this = 0x%x", this); ATOMICRELEASE(m_peHeader); ATOMICRELEASE(m_penumUiCommand); } HRESULT CCplWebViewInfo::CreateInstance( // [static] IUIElement *peHeader, IEnumUICommand *penum, DWORD dwStyle, REFIID riid, void **ppvOut ) { ASSERT(NULL != peHeader); ASSERT(NULL != penum); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CCplWebViewInfo *pwvi = new CCplWebViewInfo(); if (NULL != pwvi) { hr = pwvi->QueryInterface(riid, ppvOut); if (SUCCEEDED(hr)) { (pwvi->m_peHeader = peHeader)->AddRef(); (pwvi->m_penumUiCommand = penum)->AddRef(); pwvi->m_dwStyle = dwStyle; } pwvi->Release(); } return THR(hr); } STDMETHODIMP CCplWebViewInfo::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv))); static const QITAB qit[] = { QITABENT(CCplWebViewInfo, ICplWebViewInfo), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); return E_NOINTERFACE == hr ? hr : THR(hr); } STDMETHODIMP_(ULONG) CCplWebViewInfo::AddRef( void ) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CCplWebViewInfo::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CCplWebViewInfo::get_Header( IUIElement **ppele ) { ASSERT(NULL != ppele); ASSERT(!IsBadWritePtr(ppele, sizeof(*ppele))); HRESULT hr = S_OK; (*ppele = m_peHeader)->AddRef(); return THR(hr); } STDMETHODIMP CCplWebViewInfo::get_Style( DWORD *pdwStyle ) { ASSERT(NULL != pdwStyle); ASSERT(!IsBadWritePtr(pdwStyle, sizeof(*pdwStyle))); *pdwStyle = m_dwStyle; return S_OK; } STDMETHODIMP CCplWebViewInfo::EnumTasks( IEnumUICommand **ppenum ) { ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); HRESULT hr = S_OK; (*ppenum = m_penumUiCommand)->AddRef(); return THR(hr); } //----------------------------------------------------------------------------- // CEnumCplWebViewInfo //----------------------------------------------------------------------------- struct ECWVI_ITEM { eCPWVTYPE eType; const CPLINK_DESC **rgpDesc; // Ptr to nul-term array of link desc ptrs. bool bRestricted; // Is item restricted from usage? bool bEnhancedMenu; // Render as a 'special' list in webview? }; class CEnumCplWebViewInfo : public CObjectWithSite, public IEnumCplWebViewInfo { public: ~CEnumCplWebViewInfo(void); // // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // // IEnumCplWebViewInfo // STDMETHOD(Next)(ULONG celt, ICplWebViewInfo **ppwvi, ULONG *pceltFetched); STDMETHOD(Skip)(ULONG celt); STDMETHOD(Reset)(void); STDMETHOD(Clone)(IEnumCplWebViewInfo **ppenum); static HRESULT CreateInstance(IUnknown *punkSite, const ECWVI_ITEM *prgwvi, UINT cItems, REFIID riid, void **ppvOut); private: LONG m_cRef; int m_iCurrent; CDpa > m_rgwvi; CEnumCplWebViewInfo(void); HRESULT _Initialize(IUnknown *punkSite, const ECWVI_ITEM *prgwvi, UINT cItems); // // Prevent copy. // CEnumCplWebViewInfo(const CEnumCplWebViewInfo& rhs); // not implemented. CEnumCplWebViewInfo& operator = (const CEnumCplWebViewInfo& rhs); // not implemented. }; CEnumCplWebViewInfo::CEnumCplWebViewInfo( void ) : m_cRef(1), m_iCurrent(0) { TraceMsg(TF_LIFE, "CEnumCplWebViewInfo::CEnumCplWebViewInfo, this = 0x%x", this); } CEnumCplWebViewInfo::~CEnumCplWebViewInfo( void ) { TraceMsg(TF_LIFE, "CEnumCplWebViewInfo::~CEnumCplWebViewInfo, this = 0x%x", this); } HRESULT CEnumCplWebViewInfo::CreateInstance( IUnknown *punkSite, const ECWVI_ITEM *prgwvi, UINT cItems, REFIID riid, void **ppvOut ) { ASSERT(NULL != punkSite); ASSERT(NULL != prgwvi); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CEnumCplWebViewInfo *pewvi = new CEnumCplWebViewInfo(); if (NULL != pewvi) { hr = pewvi->_Initialize(punkSite, prgwvi, cItems); if (SUCCEEDED(hr)) { hr = pewvi->QueryInterface(riid, ppvOut); } pewvi->Release(); } return THR(hr); } STDMETHODIMP CEnumCplWebViewInfo::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv))); static const QITAB qit[] = { QITABENT(CEnumCplWebViewInfo, IEnumCplWebViewInfo), QITABENT(CEnumCplWebViewInfo, IObjectWithSite), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); return E_NOINTERFACE == hr ? hr : THR(hr); } STDMETHODIMP_(ULONG) CEnumCplWebViewInfo::AddRef( void ) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CEnumCplWebViewInfo::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CEnumCplWebViewInfo::Next( ULONG celt, ICplWebViewInfo **ppwvi, ULONG *pceltFetched ) { ASSERT(NULL != ppwvi); ASSERT(!IsBadWritePtr(ppwvi, sizeof(*ppwvi) * celt)); ULONG celtFetched = 0; while(m_iCurrent < m_rgwvi.Count() && 0 < celt) { *ppwvi = m_rgwvi.Get(m_iCurrent++); ASSERT(NULL != *ppwvi); (*ppwvi)->AddRef(); celt--; celtFetched++; ppwvi++; } if (NULL != pceltFetched) { *pceltFetched = celtFetched; } return 0 == celt ? S_OK : S_FALSE; } STDMETHODIMP CEnumCplWebViewInfo::Reset( void ) { m_iCurrent = 0; return S_OK; } STDMETHODIMP CEnumCplWebViewInfo::Skip( ULONG n ) { while(0 < n-- && m_iCurrent < m_rgwvi.Count()) { m_iCurrent++; } return 0 == n ? S_OK : S_FALSE; } STDMETHODIMP CEnumCplWebViewInfo::Clone( IEnumCplWebViewInfo **ppenum ) { ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); *ppenum = NULL; HRESULT hr = E_OUTOFMEMORY; CEnumCplWebViewInfo *penum = new CEnumCplWebViewInfo(); if (NULL != *ppenum) { for (int i = 0; SUCCEEDED(hr) && i < m_rgwvi.Count(); i++) { ICplWebViewInfo *pwvi = m_rgwvi.Get(i); ASSERT(NULL != pwvi); if (-1 != penum->m_rgwvi.Append(pwvi)) { pwvi->AddRef(); } else { hr = E_OUTOFMEMORY; } } if (SUCCEEDED(hr)) { hr = penum->QueryInterface(IID_IEnumCplWebViewInfo, (void **)ppenum); } penum->Release(); } return THR(hr); } HRESULT CEnumCplWebViewInfo::_Initialize( IUnknown *punkSite, const ECWVI_ITEM *prgwvi, UINT cItems ) { ASSERT(NULL != punkSite); ASSERT(NULL != prgwvi); IUnknown *punk; HRESULT hr = QueryInterface(IID_IUnknown, (void **)&punk); if (SUCCEEDED(hr)) { hr = IUnknown_SetSite(punk, punkSite); if (SUCCEEDED(hr)) { for (UINT i = 0; i < cItems; i++) { if (!prgwvi[i].bRestricted) { IEnumUICommand *penum; hr = CEnumCommand::CreateInstance(CObjectWithSite::_punkSite, prgwvi[i].rgpDesc, IID_IEnumUICommand, (void **)&penum); if (SUCCEEDED(hr)) { IUIElement *peHeader; hr = CplNamespace_CreateWebViewHeaderElement(prgwvi[i].eType, &peHeader); if (SUCCEEDED(hr)) { DWORD dwStyle = 0; if (prgwvi[i].bEnhancedMenu) { dwStyle |= SFVMWVF_SPECIALTASK; } ICplWebViewInfo *pwvi; hr = CCplWebViewInfo::CreateInstance(peHeader, penum, dwStyle, IID_ICplWebViewInfo, (void **)&pwvi); if (SUCCEEDED(hr)) { if (-1 == m_rgwvi.Append(pwvi)) { pwvi->Release(); hr = E_OUTOFMEMORY; } } peHeader->Release(); } penum->Release(); } } } } punk->Release(); } return THR(hr); } //----------------------------------------------------------------------------- // CCplCategory //----------------------------------------------------------------------------- class CCplCategory : public CObjectWithSite, public ICplCategory { public: ~CCplCategory(void); // // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // // ICplCategory // STDMETHOD(GetCategoryID)(eCPCAT *pID); STDMETHOD(GetUiCommand)(IUICommand **ppele); STDMETHOD(EnumTasks)(IEnumUICommand **ppenum); STDMETHOD(EnumCplApplets)(IEnumUICommand **ppenum); STDMETHOD(EnumWebViewInfo)(DWORD dwFlags, IEnumCplWebViewInfo **ppenum); STDMETHOD(GetHelpURL)(LPWSTR pszURL, UINT cchURL); static HRESULT CreateInstance(const CPCAT_DESC *pDesc, const CDpaUiCommand& rgCplApplets, REFIID riid, void **ppvOut); private: LONG m_cRef; const CPCAT_DESC *m_pDesc; // Initialization data. CDpaUiCommand m_rgCplApplets; // Cached list of CPL applet links. CCplCategory(void); // // Prevent copy. // CCplCategory(const CCplCategory& rhs); // not implemented. CCplCategory& operator = (const CCplCategory& rhs); // not implemented. HRESULT _Initialize(const CPCAT_DESC *pDesc, const CDpaUiCommand& rgCplApplets); bool _CplAppletsLoaded(void) const; }; CCplCategory::CCplCategory( void ) : m_cRef(1), m_pDesc(NULL) { TraceMsg(TF_LIFE, "CCplCategory::CCplCategory, this = 0x%x", this); } CCplCategory::~CCplCategory( void ) { TraceMsg(TF_LIFE, "CCplCategory::~CCplCategory, this = 0x%x", this); } HRESULT CCplCategory::CreateInstance( const CPCAT_DESC *pDesc, const CDpaUiCommand& rgCplApplets, REFIID riid, void **ppvOut ) { ASSERT(NULL != pDesc); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CCplCategory *pc = new CCplCategory(); if (NULL != pc) { hr = pc->_Initialize(pDesc, rgCplApplets); if (SUCCEEDED(hr)) { hr = pc->QueryInterface(riid, ppvOut); } pc->Release(); } return THR(hr); } STDMETHODIMP CCplCategory::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv))); static const QITAB qit[] = { QITABENT(CCplCategory, ICplCategory), QITABENT(CCplCategory, IObjectWithSite), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); return E_NOINTERFACE == hr ? hr : THR(hr); } STDMETHODIMP_(ULONG) CCplCategory::AddRef( void ) { return InterlockedIncrement(&m_cRef); } STDMETHODIMP_(ULONG) CCplCategory::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CCplCategory::GetUiCommand( IUICommand **ppc ) { DBG_ENTER(FTF_CPANEL, "CCplCategory::GetUiCommand"); ASSERT(NULL != m_pDesc); ASSERT(NULL != m_pDesc->pLink); ASSERT(NULL != ppc); ASSERT(!IsBadWritePtr(ppc, sizeof(*ppc))); HRESULT hr = CplNamespace_CreateUiCommand(CObjectWithSite::_punkSite, *(m_pDesc->pLink), ppc); if (SUCCEEDED(hr)) { hr = IUnknown_SetSite(*ppc, CObjectWithSite::_punkSite); } DBG_EXIT_HRES(FTF_CPANEL, "CCplCategory::GetUiCommand", hr); return THR(hr); } STDMETHODIMP CCplCategory::EnumWebViewInfo( DWORD dwFlags, IEnumCplWebViewInfo **ppenum ) { DBG_ENTER(FTF_CPANEL, "CCplCategory::EnumWebViewInfo"); ASSERT(NULL != m_pDesc); ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); UNREFERENCED_PARAMETER(dwFlags); const ECWVI_ITEM rgItems[] = { { eCPWVTYPE_SEEALSO, m_pDesc->slinks.ppSeeAlsoLinks, false, false }, { eCPWVTYPE_TROUBLESHOOT, m_pDesc->slinks.ppTroubleshootLinks, false, false }, { eCPWVTYPE_LEARNABOUT, m_pDesc->slinks.ppLearnAboutLinks, false, false } }; HRESULT hr = CEnumCplWebViewInfo::CreateInstance(CObjectWithSite::_punkSite, rgItems, ARRAYSIZE(rgItems), IID_IEnumCplWebViewInfo, (void **)ppenum); DBG_EXIT_HRES(FTF_CPANEL, "CCplCategory::EnumWebViewInfo", hr); return THR(hr); } STDMETHODIMP CCplCategory::EnumTasks( IEnumUICommand **ppenum ) { DBG_ENTER(FTF_CPANEL, "CCplCategory::EnumTasks"); ASSERT(NULL != m_pDesc); ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); HRESULT hr = CEnumCommand::CreateInstance(CObjectWithSite::_punkSite, m_pDesc->ppTaskLinks, IID_IEnumUICommand, (void **)ppenum); DBG_EXIT_HRES(FTF_CPANEL, "CCplCategory::EnumTasks", hr); return THR(hr); } STDMETHODIMP CCplCategory::EnumCplApplets( IEnumUICommand **ppenum ) { DBG_ENTER(FTF_CPANEL, "CCplCategory::EnumCplApplets"); ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); HRESULT hr = CEnumCommand::CreateInstance(CObjectWithSite::_punkSite, m_rgCplApplets, IID_IEnumUICommand, (void **)ppenum); DBG_EXIT_HRES(FTF_CPANEL, "CCplCategory::EnumCplApplets", hr); return THR(hr); } STDMETHODIMP CCplCategory::GetCategoryID( eCPCAT *pID ) { ASSERT(NULL != pID); ASSERT(!IsBadWritePtr(pID, sizeof(*pID))); *pID = m_pDesc->idCategory; return S_OK; } STDMETHODIMP CCplCategory::GetHelpURL( LPWSTR pszURL, UINT cchURL ) { ASSERT(NULL != pszURL); ASSERT(!IsBadWritePtr(pszURL, cchURL * sizeof(*pszURL))); return CPL::BuildHssHelpURL(m_pDesc->pszHelpSelection, pszURL, cchURL); } HRESULT CCplCategory::_Initialize( const CPCAT_DESC *pDesc, const CDpaUiCommand& rgCplApplets ) { ASSERT(NULL != pDesc); ASSERT(NULL == m_pDesc); m_pDesc = pDesc; HRESULT hr = CplNamespace_CopyCommandArray(rgCplApplets, &m_rgCplApplets); return THR(hr); } //----------------------------------------------------------------------------- // CTriState // This is a trivial class to allow representation of a uninitialized boolean // value. Used by CCplNamespace for it's storage of cached 'restriction' // values. Internally, -1 == 'uninitialized, 0 == false and 1 == true. //----------------------------------------------------------------------------- class CTriState { public: CTriState(void) : m_iVal(-1) { } operator bool() const { ASSERT(!_Invalid()); return (!_Invalid() ? !!m_iVal : false); } CTriState& operator = (bool bValue) { m_iVal = bValue ? 1 : 0; return *this; } bool IsInvalid(void) const { return _Invalid(); } private: int m_iVal; void _Set(bool bValue) { m_iVal = bValue ? 1 : 0; } bool _Invalid(void) const { return (-1 == m_iVal); } }; //----------------------------------------------------------------------------- // CCplNamespace //----------------------------------------------------------------------------- class CCplNamespace : public CObjectWithSite, public ICplNamespace { public: ~CCplNamespace(void); // // IUnknown // STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(void); STDMETHOD_(ULONG, Release)(void); // // ICplNamespace // STDMETHOD(GetCategory)(eCPCAT eCategory, ICplCategory **ppcat); STDMETHOD(EnumWebViewInfo)(DWORD dwFlags, IEnumCplWebViewInfo **ppenum); STDMETHOD(EnumClassicWebViewInfo)(DWORD dwFlags, IEnumCplWebViewInfo **ppenum); STDMETHOD(RefreshIDs)(IEnumIDList *penumIDs); STDMETHOD_(BOOL, IsServer)(void); STDMETHOD_(BOOL, IsProfessional)(void); STDMETHOD_(BOOL, IsPersonal)(void); STDMETHOD_(BOOL, IsUserAdmin)(void); STDMETHOD_(BOOL, IsUserOwner)(void); STDMETHOD_(BOOL, IsUserStandard)(void); STDMETHOD_(BOOL, IsUserLimited)(void); STDMETHOD_(BOOL, IsUserGuest)(void); STDMETHOD_(BOOL, IsOnDomain)(void); STDMETHOD_(BOOL, IsX86)(void); STDMETHOD_(BOOL, AllowUserManager)(void); STDMETHOD_(BOOL, UsePersonalUserManager)(void); STDMETHOD_(BOOL, AllowDeskCpl)(void); STDMETHOD_(BOOL, AllowDeskCplTab_Background)(void); STDMETHOD_(BOOL, AllowDeskCplTab_Screensaver)(void); STDMETHOD_(BOOL, AllowDeskCplTab_Appearance)(void); STDMETHOD_(BOOL, AllowDeskCplTab_Settings)(void); static HRESULT CreateInstance(IEnumIDList *penumIDs, REFIID riid, void **ppvOut); private: LONG m_cRef; ICplCategory *m_rgpCategories[eCPCAT_NUMCATEGORIES]; CDpaUiCommand m_rgCplApplets[eCPCAT_NUMCATEGORIES]; IEnumIDList *m_penumIDs; CTriState m_SkuSvr; CTriState m_SkuPro; CTriState m_SkuPer; CTriState m_Admin; CTriState m_UserOwner; CTriState m_UserStandard; CTriState m_UserLimited; CTriState m_UserGuest; CTriState m_Domain; CTriState m_AllowUserManager; CTriState m_PersonalUserManager; CTriState m_AllowDeskCpl; CTriState m_rgAllowDeskCplTabs[CPLTAB_DESK_MAX]; CCplNamespace(void); // // Prevent copy. // CCplNamespace(const CCplNamespace& rhs); // not implemented. CCplNamespace& operator = (const CCplNamespace& rhs); // not implemented. HRESULT _Initialize(IEnumIDList *penumIDs); HRESULT _SetIDList(IEnumIDList *penumIDs); HRESULT _IsValidCategoryID(int iCategory) const; HRESULT _CategorizeCplApplets(void); HRESULT _LoadSeeAlsoLinks(void); HRESULT _AddSeeAlso(IUICommand *pc); HRESULT _CategorizeCplApplet(IShellFolder2 *psf2Cpanel, LPCITEMIDLIST pidlItem); BOOL _UserAcctType(CTriState *pts); void _GetUserAccountType(void); BOOL _AllowDeskCplTab(eDESKCPLTAB eTab); void _DestroyCategories(void); void _ClearCplApplets(void); }; CCplNamespace::CCplNamespace( void ) : m_cRef(1), m_penumIDs(NULL) { TraceMsg(TF_LIFE, "CCplNamespace::CCplNamespace, this = 0x%x", this); ZeroMemory(m_rgpCategories, sizeof(m_rgpCategories)); } CCplNamespace::~CCplNamespace( void ) { TraceMsg(TF_LIFE, "CCplNamespace::~CCplNamespace, this = 0x%x", this); _DestroyCategories(); ATOMICRELEASE(m_penumIDs); } HRESULT CCplNamespace::CreateInstance( IEnumIDList *penumIDs, REFIID riid, void **ppvOut ) { ASSERT(NULL != penumIDs); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); *ppvOut = NULL; HRESULT hr = E_OUTOFMEMORY; CCplNamespace *pns = new CCplNamespace(); if (NULL != pns) { hr = pns->_Initialize(penumIDs); if (SUCCEEDED(hr)) { hr = pns->QueryInterface(riid, ppvOut); } pns->Release(); } return THR(hr); } STDMETHODIMP CCplNamespace::QueryInterface( REFIID riid, void **ppv ) { ASSERT(NULL != ppv); ASSERT(!IsBadWritePtr(ppv, sizeof(*ppv))); static const QITAB qit[] = { QITABENT(CCplNamespace, ICplNamespace), QITABENT(CCplNamespace, IObjectWithSite), { 0 }, }; HRESULT hr = QISearch(this, qit, riid, ppv); return E_NOINTERFACE == hr ? hr : THR(hr); } STDMETHODIMP_(ULONG) CCplNamespace::AddRef( void ) { ULONG cRef = InterlockedIncrement(&m_cRef); TraceMsg(TF_LIFE, "CCplNamespace::AddRef %d->%d", cRef - 1, cRef); return cRef; } STDMETHODIMP_(ULONG) CCplNamespace::Release( void ) { ASSERT( 0 != m_cRef ); ULONG cRef = InterlockedDecrement(&m_cRef); TraceMsg(TF_LIFE, "CCplNamespace::Release %d<-%d", cRef, cRef+1); if ( 0 == cRef ) { delete this; } return cRef; } STDMETHODIMP CCplNamespace::EnumWebViewInfo( DWORD dwFlags, IEnumCplWebViewInfo **ppenum ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::EnumWebViewInfo"); ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); const bool bNoViewSwitch = (0 != (CPVIEW_EF_NOVIEWSWITCH & dwFlags)); const ECWVI_ITEM rgItems[] = { { eCPWVTYPE_CPANEL, g_rgpLink_Cpl_SwToClassicView, bNoViewSwitch, true }, { eCPWVTYPE_SEEALSO, g_rgpLink_Cpl_SeeAlso, false, false } }; HRESULT hr = CEnumCplWebViewInfo::CreateInstance(CObjectWithSite::_punkSite, rgItems, ARRAYSIZE(rgItems), IID_IEnumCplWebViewInfo, (void **)ppenum); DBG_EXIT_HRES(FTF_CPANEL, "CCplNamespace::EnumWebViewInfo", hr); return THR(hr); } STDMETHODIMP CCplNamespace::EnumClassicWebViewInfo( DWORD dwFlags, IEnumCplWebViewInfo **ppenum ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::EnumClassicWebViewInfo"); ASSERT(NULL != ppenum); ASSERT(!IsBadWritePtr(ppenum, sizeof(*ppenum))); const bool bNoViewSwitch = (0 != (CPVIEW_EF_NOVIEWSWITCH & dwFlags)); const ECWVI_ITEM rgItems[] = { { eCPWVTYPE_CPANEL, g_rgpLink_Cpl_SwToCategoryView, bNoViewSwitch, true }, { eCPWVTYPE_SEEALSO, g_rgpLink_Cpl_SeeAlso, false, false } }; HRESULT hr = CEnumCplWebViewInfo::CreateInstance(CObjectWithSite::_punkSite, rgItems, ARRAYSIZE(rgItems), IID_IEnumCplWebViewInfo, (void **)ppenum); DBG_EXIT_HRES(FTF_CPANEL, "CCplNamespace::EnumClassicWebViewInfo", hr); return THR(hr); } STDMETHODIMP CCplNamespace::GetCategory( eCPCAT eCategory, ICplCategory **ppcat ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::GetCategory"); TraceMsg(FTF_CPANEL, "Category ID = %d", eCategory); ASSERT(S_OK == _IsValidCategoryID(eCategory)); ASSERT(NULL != ppcat); ASSERT(!IsBadWritePtr(ppcat, sizeof(*ppcat))); HRESULT hr = S_OK; *ppcat = NULL; if (NULL == m_rgpCategories[eCategory]) { hr = CCplCategory::CreateInstance(g_rgpCplCatInfo[eCategory], m_rgCplApplets[eCategory], IID_ICplCategory, (void **)&m_rgpCategories[eCategory]); if (SUCCEEDED(hr)) { ASSERT(NULL != CObjectWithSite::_punkSite); hr = IUnknown_SetSite(m_rgpCategories[eCategory], CObjectWithSite::_punkSite); } } if (SUCCEEDED(hr)) { *ppcat = m_rgpCategories[eCategory]; (*ppcat)->AddRef(); } DBG_EXIT_HRES(FTF_CPANEL, "CCplNamespace::GetCategory", hr); return THR(hr); } STDMETHODIMP CCplNamespace::RefreshIDs( IEnumIDList *penumIDs ) { return _SetIDList(penumIDs); } BOOL CCplNamespace::IsX86(void) { #ifdef _X86_ return true; #else return false; #endif } BOOL CCplNamespace::IsServer(void) { if (m_SkuSvr.IsInvalid()) { m_SkuSvr = !!IsOsServer(); } return m_SkuSvr; } BOOL CCplNamespace::IsPersonal(void) { if (m_SkuPer.IsInvalid()) { m_SkuPer = !!IsOsPersonal(); } return m_SkuPer; } BOOL CCplNamespace::IsProfessional(void) { if (m_SkuPro.IsInvalid()) { m_SkuPro = !!IsOsProfessional(); } return m_SkuPro; } BOOL CCplNamespace::IsOnDomain(void) { if (m_Domain.IsInvalid()) { m_Domain = !!IsConnectedToDomain(); } return m_Domain; } BOOL CCplNamespace::IsUserAdmin(void) { if (m_Admin.IsInvalid()) { m_Admin = !!CPL::IsUserAdmin(); } return m_Admin; } BOOL CCplNamespace::IsUserOwner(void) { return _UserAcctType(&m_UserOwner); } BOOL CCplNamespace::IsUserStandard(void) { return _UserAcctType(&m_UserStandard); } BOOL CCplNamespace::IsUserLimited(void) { return _UserAcctType(&m_UserLimited); } BOOL CCplNamespace::IsUserGuest(void) { return _UserAcctType(&m_UserGuest); } BOOL CCplNamespace::UsePersonalUserManager(void) { if (m_PersonalUserManager.IsInvalid()) { m_PersonalUserManager = (IsX86() && (IsPersonal() || (IsProfessional() && !IsOnDomain()))); } return m_PersonalUserManager; } BOOL CCplNamespace::AllowUserManager(void) { if (m_AllowUserManager.IsInvalid()) { m_AllowUserManager = IsAppletEnabled(L"nusrmgr.cpl", MAKEINTRESOURCEW(IDS_CPL_USERACCOUNTS)); } return m_AllowUserManager; } BOOL CCplNamespace::_AllowDeskCplTab(eDESKCPLTAB eTab) { if (m_rgAllowDeskCplTabs[eTab].IsInvalid()) { m_rgAllowDeskCplTabs[eTab] = DeskCPL_IsTabPresent(eTab); } return m_rgAllowDeskCplTabs[eTab]; } BOOL CCplNamespace::AllowDeskCplTab_Background(void) { return _AllowDeskCplTab(CPLTAB_DESK_BACKGROUND); } BOOL CCplNamespace::AllowDeskCplTab_Screensaver(void) { return _AllowDeskCplTab(CPLTAB_DESK_SCREENSAVER); } BOOL CCplNamespace::AllowDeskCplTab_Appearance(void) { return _AllowDeskCplTab(CPLTAB_DESK_APPEARANCE); } BOOL CCplNamespace::AllowDeskCplTab_Settings(void) { return _AllowDeskCplTab(CPLTAB_DESK_SETTINGS); } BOOL CCplNamespace::AllowDeskCpl(void) { if (m_AllowDeskCpl.IsInvalid()) { m_AllowDeskCpl = IsAppletEnabled(L"desk.cpl", MAKEINTRESOURCEW(IDS_CPL_DISPLAY)); } return m_AllowDeskCpl; } // // Retrieves the account type for the current user and updates // the cached account type members accordingly. // void CCplNamespace::_GetUserAccountType(void) { eACCOUNTTYPE eType; if (SUCCEEDED(THR(CPL::GetUserAccountType(&eType)))) { m_UserLimited = (eACCOUNTTYPE_LIMITED == eType); m_UserStandard = (eACCOUNTTYPE_STANDARD == eType); m_UserGuest = (eACCOUNTTYPE_GUEST == eType); m_UserOwner = (eACCOUNTTYPE_OWNER == eType); } } // // Determins the state of a given account type member. // BOOL CCplNamespace::_UserAcctType(CTriState *pts) { if (pts->IsInvalid()) { _GetUserAccountType(); } return *pts; } HRESULT CCplNamespace::_IsValidCategoryID( int iCategory ) const { HRESULT hr = E_FAIL; if (0 <= iCategory && ARRAYSIZE(m_rgpCategories) > iCategory) { hr = S_OK; } return THR(hr); } HRESULT CCplNamespace::_Initialize( IEnumIDList *penumIDs ) { ASSERT(NULL != penumIDs); HRESULT hr = _SetIDList(penumIDs); return THR(hr); } HRESULT CCplNamespace::_SetIDList( IEnumIDList *penumIDs ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::_SetIDList"); ASSERT(NULL != penumIDs); ATOMICRELEASE(m_penumIDs); (m_penumIDs = penumIDs)->AddRef(); // // We have a new set of IDs so we need to re-categorize them. // HRESULT hr = _CategorizeCplApplets(); DBG_EXIT(FTF_CPANEL, "CCplNamespace::_SetIDList"); return THR(hr); } // // Destroy all category objects in our array of categories. // void CCplNamespace::_DestroyCategories( void ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::_DestroyCategories"); for (int i = 0; i < ARRAYSIZE(m_rgpCategories); i++) { ATOMICRELEASE(m_rgpCategories[i]); } DBG_EXIT(FTF_CPANEL, "CCplNamespace::_DestroyCategories"); } void CCplNamespace::_ClearCplApplets( void ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::_ClearCplApplets"); for (int i = 0; i < ARRAYSIZE(m_rgCplApplets); i++) { m_rgCplApplets[i].Clear(); } DBG_EXIT(FTF_CPANEL, "CCplNamespace::_ClearCplApplets"); } // // Load and categorize all of the CPL applets in the Control Panel folder. // HRESULT CCplNamespace::_CategorizeCplApplets( void ) { DBG_ENTER(FTF_CPANEL, "CCplNamespace::_CategorizeCplApplets"); // // Destroy any existing categories and CPL applets that we have // already categorized. // _DestroyCategories(); _ClearCplApplets(); LPITEMIDLIST pidlFolder; HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_CONTROLS, &pidlFolder); if (SUCCEEDED(hr)) { IShellFolder *psfDesktop; hr = SHGetDesktopFolder(&psfDesktop); if (SUCCEEDED(hr)) { IShellFolder2 *psf2Cpanel; hr = psfDesktop->BindToObject(pidlFolder, NULL, IID_IShellFolder2, (void **)&psf2Cpanel); if (SUCCEEDED(hr)) { LPITEMIDLIST pidlItem; ULONG celt = 0; while(S_OK == (hr = m_penumIDs->Next(1, &pidlItem, &celt))) { // // Note that we continue the enumeration if loading a // particular applet fails. // _CategorizeCplApplet(psf2Cpanel, pidlItem); ILFree(pidlItem); } psf2Cpanel->Release(); } psfDesktop->Release(); } ILFree(pidlFolder); } DBG_EXIT_HRES(FTF_CPANEL, "CCplNamespace::_CategorizeCplApplets", hr); return THR(hr); } // // Load one CPL applet into the category's DPA of associated CPL applets. // HRESULT CCplNamespace::_CategorizeCplApplet( IShellFolder2 *psf2Cpanel, LPCITEMIDLIST pidlItem ) { ASSERT(NULL != psf2Cpanel); ASSERT(NULL != pidlItem); SHCOLUMNID scid = SCID_CONTROLPANELCATEGORY; VARIANT var; VariantInit(&var); DWORD dwCategoryID = 0; // The default. 0 == "other CPLs" category HRESULT hr = psf2Cpanel->GetDetailsEx(pidlItem, &scid, &var); if (SUCCEEDED(hr)) { dwCategoryID = var.lVal; } // // -1 is a special category ID meaning "don't categorize". // if (DWORD(-1) != dwCategoryID) { IUICommand *pc; hr = Create_CplUiCommandOnPidl(pidlItem, IID_IUICommand, (void **)&pc); if (SUCCEEDED(hr)) { if (-1 == m_rgCplApplets[dwCategoryID].Append(pc)) { pc->Release(); hr = E_OUTOFMEMORY; } } } VariantClear(&var); return THR(hr); } HRESULT CPL::CplNamespace_CreateInstance( IEnumIDList *penumIDs, REFIID riid, void **ppvOut ) { ASSERT(NULL != penumIDs); ASSERT(NULL != ppvOut); ASSERT(!IsBadWritePtr(ppvOut, sizeof(*ppvOut))); HRESULT hr = CCplNamespace::CreateInstance(penumIDs, riid, ppvOut); return THR(hr); } HRESULT CPL::CplNamespace_GetCategoryAppletCount( ICplNamespace *pns, eCPCAT eCategory, int *pcApplets ) { ASSERT(NULL != pns); ASSERT(NULL != pcApplets); ASSERT(!IsBadWritePtr(pcApplets, sizeof(*pcApplets))); *pcApplets = 0; ICplCategory *pCategory; HRESULT hr = pns->GetCategory(eCategory, &pCategory); if (SUCCEEDED(hr)) { IEnumUICommand *peuic; hr = pCategory->EnumCplApplets(&peuic); if (SUCCEEDED(hr)) { IUICommand *puic; while(S_OK == (hr = peuic->Next(1, &puic, NULL))) { puic->Release(); (*pcApplets)++; } peuic->Release(); } pCategory->Release(); } return hr; } } // namespace CPL