windows-nt/Source/XPSP1/NT/net/config/shell/folder/cmdtable.cpp
2020-09-26 16:20:57 +08:00

1753 lines
66 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: C M D T A B L E . C P P
//
// Contents: Command-table code -- determines which menu options are
// available by the selection count, among other criteria
//
// Notes:
//
// Author: jeffspr 28 Jan 1998
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "foldinc.h" // Standard shell\folder includes
#include "foldres.h" // Folder resource IDs
#include "nsres.h" // Netshell strings
#include "cmdtable.h" // Header for this file
#include "ncperms.h" // For checking User's rights on actions/menu items
#include "cfutils.h"
#include "hnetcfg.h"
#include "lm.h"
//---[ Constants ]------------------------------------------------------------
const DWORD NCCF_ALL = 0xffffffff; // NCCF_ALL - For all Characteristics
const DWORD S_REMOVE = 2;
#define TRACESTRLEN 65535
// Active must be a subset of Visible (Opening connections folder using a CHK DLL asserts integrity of table).
// DO NOT use NCM_ and NCS_ flags in this table!!! You should use NBM_ and NBS_ flags over here.
COMMANDENTRY g_cteCommandMatrix[] =
{
//iCommandId dwDefaultPriority dwFlags HrEnableDisableCB HrCustomMenuStringCB
// | | dwValidWhen | | |
// | | | | dwMediaTypeVisible | | dwMediaTypeActive
// | | | | dwStatusVisible | | dwStatusActive
// | | | | dwCharacteristicsVisible | | dwCharacteristicsActive
// | | | | (VISIBLE) | | (ACTIVE... (NOT REMOVED))
// v v v v | v v |
// v v
{ CMIDM_HOMENET_WIZARD, 5, NCWHEN_ANYSELECT, NB_REMOVE_TOPLEVEL_ITEM,HrIsHomeNewWizardSupported, NULL,
NBM_HNW_WIZARD, NBM_HNW_WIZARD, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_NET_TROUBLESHOOT, 5, NCWHEN_TOPLEVEL, NB_REMOVE_TOPLEVEL_ITEM,HrIsTroubleShootSupported, NULL,
NBM_NOMEDIATYPE, NBM_NOMEDIATYPE, // Media Type
NBS_NONE, NBS_NONE, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_CONMENU_ADVANCED_CONFIG,
5, NCWHEN_TOPLEVEL, NB_NO_FLAGS, NULL, NULL,
NBM_NOMEDIATYPE, NBM_NOMEDIATYPE, // Media Type
NBS_NONE, NBS_NONE, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_CONMENU_DIALUP_PREFS,
5, NCWHEN_TOPLEVEL,
NB_NO_FLAGS, NULL, NULL,
NBM_NOMEDIATYPE, NBM_NOMEDIATYPE, // Media Type
NBS_NONE, NBS_NONE, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_NEW_CONNECTION, 5, NCWHEN_ANYSELECT, NB_VERB, HrIsNCWSupported, NULL,
NBM_MNC_WIZARD, NBM_MNC_WIZARD, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_CONNECT, 3, NCWHEN_ONESELECT, NB_VERB, NULL, NULL,
NBM_SHAREDACCESSHOST_RAS | NBM_ISRASTYPE, NBM_SHAREDACCESSHOST_RAS | NBM_ISRASTYPE, // Media Type
NBS_HW_ISSUE | NBS_DISCONNECTED | NBS_CONNECTING, NBS_DISCONNECTED, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_DISCONNECT, 0, NCWHEN_ONESELECT, NB_VERB, NULL, NULL,
NBM_SHAREDACCESSHOST_RAS|NBM_ISRASTYPE,NBM_SHAREDACCESSHOST_RAS|NBM_ISRASTYPE, // Media Type
NBS_IS_CONNECTED | NBS_DISCONNECTING, NBS_IS_CONNECTED, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_ENABLE, 3, NCWHEN_ONESELECT, NB_VERB, NULL, NULL,
NBM_SHAREDACCESSHOST_LAN|NBM_ISLANTYPE,NBM_SHAREDACCESSHOST_LAN|NBM_ISLANTYPE, // Media Type
NBS_HW_ISSUE | NBS_DISCONNECTED | NBS_CONNECTING, NBS_DISCONNECTED, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_DISABLE, 0, NCWHEN_ONESELECT, NB_VERB, NULL, NULL,
NBM_SHAREDACCESSHOST_LAN|NBM_ISLANTYPE,NBM_SHAREDACCESSHOST_LAN|NBM_ISLANTYPE, // Media Type
NBS_DISCONNECTING | NBS_IS_CONNECTED | NBS_MEDIA_DISCONNECTED | NBS_INVALID_ADDRESS, NBS_NOT_DISCONNECT, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_WZCDLG_SHOW, 4, NCWHEN_ONESELECT, NB_VERB, HrIsMediaWireless, NULL,
NBM_LAN, NBM_LAN, // Media Type
NBS_NOT_DISCONNECT, NBS_NOT_DISCONNECT, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_STATUS, 5, NCWHEN_ONESELECT, NB_VERB, NULL, NULL,
NBM_INCOMING | NBM_SHAREDACCESSHOST_LAN|NBM_SHAREDACCESSHOST_RAS|NBM_ISCONNECTIONTYPE, NBM_INCOMING | NBM_SHAREDACCESSHOST_LAN|NBM_SHAREDACCESSHOST_RAS|NBM_ISCONNECTIONTYPE,
NBS_ANY, NBS_IS_CONNECTED | NBS_INVALID_ADDRESS, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_FIX, 0, NCWHEN_SOMESELECT, NB_NO_FLAGS, NULL, NULL,
NBM_ISLANTYPE, NBM_ISLANTYPE, // Media Type
NBS_IS_CONNECTED | NBS_DISCONNECTING| NBS_MEDIA_DISCONNECTED| NBS_INVALID_ADDRESS, NBS_INVALID_ADDRESS | NBS_IS_CONNECTED, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_SEPARATOR, 0,0,0,0,0, 0,0, 0,0, 0,0 },
{ CMIDM_SET_DEFAULT, 0, NCWHEN_ONESELECT, NB_NEGATE_CHAR_MATCH, NULL, NULL,
NBM_INCOMING | NBM_ISRASTYPE, NBM_INCOMING | NBM_ISRASTYPE, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_INCOMING_ONLY | NCCF_DEFAULT, NCCF_INCOMING_ONLY | NCCF_DEFAULT}, // Characteristics
{ CMIDM_UNSET_DEFAULT, 0, NCWHEN_ONESELECT, NB_NO_FLAGS, NULL, NULL,
NBM_INCOMING | NBM_ISRASTYPE, NBM_INCOMING | NBM_ISRASTYPE, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_DEFAULT, NCCF_DEFAULT}, // Characteristics
{ CMIDM_SEPARATOR, 0,0,0,0,0, 0,0, 0,0, 0,0 },
{ CMIDM_CREATE_BRIDGE, 0, NCWHEN_ANYSELECT, NB_NO_FLAGS, HrIsBridgeSupported, NULL,
NBM_LAN, NBM_LAN, // Media Type
NBS_IS_CONNECTED | NBS_DISCONNECTING| NBS_MEDIA_DISCONNECTED| NBS_INVALID_ADDRESS, NBS_DISCONNECTING|NBS_IS_CONNECTED|NBS_MEDIA_DISCONNECTED|NBS_INVALID_ADDRESS, // Status
NCCF_ALL, NCCF_ALL }, // Characteristics
{ CMIDM_CONMENU_CREATE_BRIDGE,0, NCWHEN_TOPLEVEL,NB_REMOVE_TOPLEVEL_ITEM,HrIsBridgeSupported, NULL,
NBM_NOMEDIATYPE, NBM_NOMEDIATYPE, // Media Type
NBS_NONE, NBS_NONE, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
{ CMIDM_ADD_TO_BRIDGE, 0, NCWHEN_SOMESELECT, NB_NEGATE_CHAR_MATCH, HrIsBridgeSupported, NULL,
NBM_LAN, NBM_LAN, // Media Type
NBS_IS_CONNECTED | NBS_DISCONNECTING| NBS_MEDIA_DISCONNECTED| NBS_INVALID_ADDRESS, NBS_DISCONNECTING|NBS_IS_CONNECTED|NBS_MEDIA_DISCONNECTED|NBS_INVALID_ADDRESS, // Status
NCCF_BRIDGED | NCCF_FIREWALLED | NCCF_SHARED, NCCF_BRIDGED | NCCF_FIREWALLED | NCCF_SHARED }, // Characteristics
{ CMIDM_REMOVE_FROM_BRIDGE, 0, NCWHEN_SOMESELECT,NB_NO_FLAGS, HrIsBridgeSupported, NULL,
NBM_LAN, NBM_LAN, // Media Type
NBS_IS_CONNECTED | NBS_DISCONNECTING| NBS_MEDIA_DISCONNECTED| NBS_INVALID_ADDRESS, NBS_DISCONNECTING|NBS_IS_CONNECTED|NBS_MEDIA_DISCONNECTED|NBS_INVALID_ADDRESS, // Status
NCCF_BRIDGED, NCCF_BRIDGED }, // Characteristics
{ CMIDM_SEPARATOR, 0,0,0,0,0, 0,0, 0,0, 0,0 },
{ CMIDM_CREATE_COPY, 0, NCWHEN_ONESELECT, NB_NEGATE_VIS_CHAR_MATCH, NULL, NULL,
NBM_INCOMING | NBM_SHAREDACCESSHOST_RAS | NBM_ISRASTYPE, NBM_INCOMING | NBM_SHAREDACCESSHOST_RAS | NBM_ISRASTYPE, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_INCOMING_ONLY, NCCF_ALLOW_DUPLICATION}, // Characteristics
{ CMIDM_SEPARATOR, 0,0,0,0,0, 0,0, 0,0, 0,0 },
{ CMIDM_CREATE_SHORTCUT, 0, NCWHEN_ONESELECT, NB_NEGATE_CHAR_MATCH, NULL, NULL,
NBM_ANY, NBM_ANY, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_INCOMING_ONLY, NCCF_INCOMING_ONLY}, // Characteristics
{ CMIDM_DELETE, 0, NCWHEN_SOMESELECT, NB_NO_FLAGS, NULL, NULL,
NBM_NOTWIZARD, NBM_NOTWIZARD, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_ALL, NCCF_ALLOW_REMOVAL}, // Characteristics
{ CMIDM_RENAME, 0, NCWHEN_ONESELECT, NB_NO_FLAGS, HrCanRenameConnection, NULL,
NBM_NOTWIZARD, NBM_NOTWIZARD, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_ALL, NCCF_ALLOW_RENAME}, // Characteristics
{ CMIDM_SEPARATOR, 0,0,0,0,0, 0,0, 0,0, 0,0 },
{ CMIDM_PROPERTIES, 2, NCWHEN_ONESELECT, NB_NO_FLAGS, HrCanShowProperties, NULL,
NBM_INCOMING|NBM_SHAREDACCESSHOST_LAN|NBM_SHAREDACCESSHOST_RAS|NBM_ISCONNECTIONTYPE, NBM_INCOMING|NBM_SHAREDACCESSHOST_LAN|NBM_SHAREDACCESSHOST_RAS|NBM_ISCONNECTIONTYPE, // Media Type
NBS_ANY, NBS_ANY, // Status
NCCF_ALL, NCCF_ALL}, // Characteristics
};
// What is the difference between NCCF_INCOMING_ONLY, ~NCCF_INCOMING_ONLY and NCCF_INCOMING_ONLY + NB_NEGATE_CHAR_MATCH?
// NCCF_INCOMING_ONLY | NCCF_ALLOW_REMOVAL means: NCCF_INCOMING_ONLY or NCCF_ALLOW_REMOVAL or BOTH should be set.
// ~NCCF_INCOMING_ONLY means: One or flag (irrespective of NCCF_INCOMING_ONLY flag) should be set.
// NB_NEGATE_CHAR_MATCH + NCCF_INCOMING_ONLY means: Check that NCCF_INCOMING_ONLY is not set.
const DWORD g_cteCommandMatrixCount = celems(g_cteCommandMatrix);
COMMANDPERMISSIONSENTRY g_cteCommandPermissionsMatrix[] =
{
{ CMIDM_NEW_CONNECTION, NBM_ANY, NCCF_ALL, NB_TOPLEVEL_PERM | NB_REMOVE_IF_NOT_MATCH,NBPERM_NewConnectionWizard, APPLY_TO_ALL_USERS },
{ CMIDM_CONNECT, NBM_ISRASTYPE, NCCF_ALL, NB_NO_FLAGS, NBPERM_RasConnect, APPLY_TO_ALL_USERS },
{ CMIDM_CONNECT, NBM_SHAREDACCESSHOST_RAS, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_ALL_USERS },
{ CMIDM_DISCONNECT, NBM_ISRASTYPE, NCCF_INCOMING_ONLY, NB_NEGATE_CHAR_MATCH,NBPERM_RasConnect, APPLY_TO_ALL_USERS },
{ CMIDM_DISCONNECT, NBM_ISRASTYPE, NCCF_INCOMING_ONLY, NB_NO_FLAGS, NBPERM_RasConnect, APPLY_TO_ADMIN },
{ CMIDM_DISCONNECT, NBM_SHAREDACCESSHOST_RAS, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_ALL_USERS },
{ CMIDM_ENABLE, NBM_LAN, NCCF_ALL, NB_NO_FLAGS, NBPERM_LanConnect, APPLY_TO_ALL_USERS },
{ CMIDM_ENABLE, NBM_SHAREDACCESSHOST_LAN, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_ALL_USERS },
{ CMIDM_ENABLE, NBM_BRIDGE, NCCF_ALL, NB_NO_FLAGS, NBPERM_AllowNetBridge_NLA, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_DISABLE, NBM_LAN, NCCF_ALL, NB_NO_FLAGS, NBPERM_LanConnect, APPLY_TO_ALL_USERS },
{ CMIDM_DISABLE, NBM_SHAREDACCESSHOST_LAN, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_ALL_USERS },
{ CMIDM_DISABLE, NBM_BRIDGE, NCCF_ALL, NB_NO_FLAGS, NBPERM_AllowNetBridge_NLA, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_STATUS, NBM_ANY, NCCF_INCOMING_ONLY, NB_NEGATE_CHAR_MATCH,NBPERM_Statistics, APPLY_TO_ALL_USERS },
{ CMIDM_STATUS, NBM_ANY, NCCF_INCOMING_ONLY, NB_NO_FLAGS, NBPERM_Statistics, APPLY_TO_ADMIN },
{ CMIDM_CREATE_BRIDGE, NBM_ANY, NCCF_ALL, NB_NO_FLAGS, NBPERM_AllowNetBridge_NLA, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_ADD_TO_BRIDGE, NBM_ANY, NCCF_ALL, NB_NO_FLAGS, NBPERM_AllowNetBridge_NLA, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_REMOVE_FROM_BRIDGE, NBM_ANY, NCCF_ALL, NB_NO_FLAGS, NBPERM_AllowNetBridge_NLA, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_CREATE_COPY, NBM_ANY, NCCF_ALL_USERS, NB_NO_FLAGS, NBPERM_NewConnectionWizard | NBPERM_RasAllUserProperties, APPLY_TO_ALL_USERS },
{ CMIDM_CREATE_COPY, NBM_ANY, NCCF_ALL_USERS, NB_NEGATE_CHAR_MATCH,NBPERM_NewConnectionWizard, APPLY_TO_ALL_USERS },
{ CMIDM_FIX, NBM_ANY, NCCF_ALL, NB_NO_FLAGS, NBPERM_Repair, APPLY_TO_POWERUSERSPLUS },
{ CMIDM_DELETE, NBM_ANY, NCCF_ALL_USERS, NB_NO_FLAGS, NBPERM_DeleteConnection | NBPERM_DeleteAllUserConnection, APPLY_TO_ALL_USERS },
{ CMIDM_DELETE, NBM_ANY, NCCF_ALL_USERS, NB_NEGATE_CHAR_MATCH,NBPERM_DeleteConnection, APPLY_TO_ALL_USERS },
{ CMIDM_SET_DEFAULT, NBM_INCOMING |
NBM_ISRASTYPE, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_UNSET_DEFAULT, NBM_INCOMING |
NBM_ISRASTYPE, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_OPS_OR_ADMIN },
{ CMIDM_CONMENU_ADVANCED_CONFIG,
NBM_ANY, NCCF_ALL_USERS, NB_TOPLEVEL_PERM, NBPERM_AdvancedSettings, APPLY_TO_ADMIN },
{ CMIDM_CONMENU_DIALUP_PREFS,
NBM_ANY, NCCF_ALL_USERS, NB_TOPLEVEL_PERM, NBPERM_DialupPrefs, APPLY_TO_ALL_USERS },
{ CMIDM_PROPERTIES, NBM_INCOMING, NCCF_ALL, NB_NO_FLAGS, NBPERM_Always, APPLY_TO_ADMIN },
{ CMIDM_PROPERTIES, NBM_ISRASTYPE, NCCF_ALL_USERS, NB_NEGATE_CHAR_MATCH,NBPERM_RasMyProperties, APPLY_TO_ALL_USERS },
{ CMIDM_PROPERTIES, NBM_ISRASTYPE, NCCF_ALL_USERS, NB_NO_FLAGS, NBPERM_RasAllUserProperties, APPLY_TO_ALL_USERS },
{ CMIDM_PROPERTIES, NBM_LAN, NCCF_ALL, NB_NO_FLAGS, NBPERM_LanProperties, APPLY_TO_ALL_USERS }
};
const DWORD g_cteCommandPermissionsMatrixCount = celems(g_cteCommandPermissionsMatrix);
SFVCOMMANDMAP g_cteSFVCommandMap[] =
{
{ SFVIDM_FILE_DELETE, CMIDM_DELETE},
{ SFVIDM_FILE_LINK, CMIDM_CREATE_SHORTCUT},
{ SFVIDM_FILE_PROPERTIES, CMIDM_PROPERTIES},
{ SFVIDM_FILE_RENAME, CMIDM_RENAME}
};
const DWORD g_cteSFVCommandMapCount = celems(g_cteSFVCommandMap);
CMDCHKENTRY g_cceFolderChecks[] =
{
// command id
// currently checked
// | new check state
// | |
// v v
{ CMIDM_CONMENU_OPERATOR_ASSIST, false, false }
};
const DWORD g_nFolderCheckCount = celems(g_cceFolderChecks);
inline DWORD dwNegateIf(DWORD dwInput, DWORD dwFlags, DWORD dwNegateCondition)
{
if (dwFlags & dwNegateCondition)
{
return ~dwInput;
}
else
{
return dwInput;
}
}
inline BOOL bContains(DWORD dwContainee, DWORD dwContainer, DWORD dwFlags, DWORD dwContaineeNegateCondition, DWORD dwContainerNegateCondition)
{
dwContainer = dwNegateIf(dwContainer, dwFlags, dwContainerNegateCondition);
dwContainee = dwNegateIf(dwContainee, dwFlags, dwContaineeNegateCondition);
if ( (dwContainee & dwContainer) != dwContainee)
{
return FALSE;
}
else
{
return TRUE;
}
}
//+---------------------------------------------------------------------------
//
// Member: HrAssertIntegrityAgainstOldMatrix
//
// Purpose: Asserts the internal integrity of the Command Matrix
// Currently checks for:
// 1. No duplicate CMDIDs
// 2. Each NCWHEN flag at least specified NCWHEN_ONESELECT
//
// Arguments:
// none
//
// Returns:
// S_OK is succeeded
// E_FAIL if not
//
// Author: deonb 8 Feb 2001
//
// Notes: Asserts on failure
//
HRESULT HrAssertCommandMatrixIntegrity()
{
TraceFileFunc(ttidMenus);
HRESULT hr = S_OK;
LPSTR szErr = new CHAR[TRACESTRLEN];
for (DWORD x = 0; x < g_cteCommandMatrixCount; x++)
{
// Check that there isn't another entry with the same CommandID and Media Type.
const COMMANDENTRY& cte = g_cteCommandMatrix[x];
if (CMIDM_SEPARATOR == cte.iCommandId)
{
continue;
}
for (DWORD y = x + 1; y < g_cteCommandMatrixCount; y++)
{
const COMMANDENTRY& ctecmp = g_cteCommandMatrix[y];
if (cte.iCommandId == ctecmp.iCommandId)
{
sprintf(szErr, "Multiple lines (%d and %d) in the COMMANDENTRY table describe the same CmdID", x+1, y+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
}
if ( !bContains(cte.dwCharacteristicsActive, cte.dwCharacteristicsVisible, cte.dwFlags, NB_NEGATE_ACT_CHAR_MATCH, NB_NEGATE_VIS_CHAR_MATCH) )
{
sprintf(szErr, "Row %d. ACTIVE flags not a subset of VISIBLE flags for Characteristics? ", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
if ( !bContains(cte.dwStatusActive, cte.dwStatusVisible, cte.dwFlags, NB_NEGATE_ACT_NBS_MATCH, NB_NEGATE_VIS_NBS_MATCH) )
{
sprintf(szErr, "Row %d. ACTIVE flags not a subset of VISIBLE flags for Status... did you use NCS_ instead of NBM_? ", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
if ( !bContains(cte.dwMediaTypeActive, cte.dwMediaTypeVisible, cte.dwFlags, NB_NEGATE_ACT_NBM_MATCH, NB_NEGATE_VIS_NBM_MATCH) )
{
sprintf(szErr, "Row %d. ACTIVE flags not a subset of VISIBLE flags for MediaType... did you use NCM_ instead of NBM_? ", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
}
// Assert the permissions table
for (x = 0; x < g_cteCommandPermissionsMatrixCount; x++)
{
const COMMANDPERMISSIONSENTRY cpe = g_cteCommandPermissionsMatrix[x];
// Check that each CMD entry has a corresponding entry in the Command Table
BOOL bFound = FALSE;
for (DWORD y = 0; y < g_cteCommandMatrixCount; y++)
{
const COMMANDENTRY& ctecmp = g_cteCommandMatrix[y];
if (cpe.iCommandId == ctecmp.iCommandId)
{
bFound = TRUE;
if ( (cpe.dwMediaType != NBM_ANY) &&
((cpe.dwMediaType & ctecmp.dwMediaTypeActive) != cpe.dwMediaType) )
{
sprintf(szErr, "A permission has been specified in the Permissions table (row %d) for a MediaType that is not active in the Command Table (row %d)... did you use NCM_ instead of NBM_?", x+1, y+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
// if ( (cpe.dwCharacteristicsActive != NCCF_ALL) &&
// ((cpe.dwCharacteristicsActive & ctecmp.dwCharacteristicsActive) != cpe.dwCharacteristicsActive) )
// {
// sprintf(szErr, "A permission has been specified in the Permissions table (row %d) for a Characteristics that is not active in the Command Table (row %d)", x+1, y+1);
// AssertSz(FALSE, szErr);
// hr = E_FAIL;
// }
}
}
if (!bFound)
{
sprintf(szErr, "An entry has been found in the Permissions table (row %d) without a corresponding CMDID entry in the Command Table", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
// Check that no CmdId/MediaType/Characteristics has been duplicated
for (y = x + 1; y < g_cteCommandPermissionsMatrixCount; y++)
{
const COMMANDPERMISSIONSENTRY& cpecmp = g_cteCommandPermissionsMatrix[y];
if ( (cpe.iCommandId == cpecmp.iCommandId) &&
(dwNegateIf(cpe.dwMediaType, cpe.dwFlags, NB_NEGATE_NBM_MATCH) &
dwNegateIf(cpecmp.dwMediaType, cpecmp.dwFlags, NB_NEGATE_NBM_MATCH)) &&
(dwNegateIf(cpe.dwCharacteristicsActive, cpe.dwFlags, NB_NEGATE_CHAR_MATCH) &
dwNegateIf(cpecmp.dwCharacteristicsActive, cpecmp.dwFlags, NB_NEGATE_CHAR_MATCH)) )
{
sprintf(szErr, "Multiple lines (%d and %d) in the COMMANDENTRY table describe the same CmdID/MediaType/Characteristics combo", x+1, y+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
}
if (! ((APPLY_TO_NETCONFIGOPS & cpe.ncpAppliesTo) ||
(APPLY_TO_USER & cpe.ncpAppliesTo) ||
(APPLY_TO_ADMIN & cpe.ncpAppliesTo) ||
(APPLY_TO_POWERUSERS & cpe.ncpAppliesTo) ))
{
sprintf(szErr, "Lines (%d) in the Permissionstable - permissions must apply to someone", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
// !!(A & B) != !!(A & C) means: If either B or C is set in A, both B and C must be set (or neither). I hope...
// kill me... kill me now.
if ((!!(cpe.dwFlags & NB_NEGATE_VIS_NBM_MATCH) != !!(cpe.dwFlags & NB_NEGATE_ACT_NBM_MATCH)) ||
(!!(cpe.dwFlags & NB_NEGATE_VIS_NBS_MATCH) != !!(cpe.dwFlags & NB_NEGATE_ACT_NBS_MATCH)) ||
(!!(cpe.dwFlags & NB_NEGATE_VIS_CHAR_MATCH) != !!(cpe.dwFlags & NB_NEGATE_ACT_CHAR_MATCH)) ||
(!!(cpe.dwFlags & NB_NEGATE_VIS_PERMS_MATCH) != !!(cpe.dwFlags & NB_NEGATE_ACT_PERMS_MATCH)) )
{
sprintf(szErr, "Lines (%d) in the Permissionstable should use NB_NEGATE_xxx instead of NB_NEGATE_VIS_xxx or NB_NEGATE_ACT_xxx ", x+1);
AssertSz(FALSE, szErr);
hr = E_FAIL;
}
}
delete[] szErr;
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: HrAssertMenuStructuresValid
//
// Purpose: Runs various asserts to make sure the menu structures are intact
// Called on NetShell startup
//
// Arguments:
// [in] hwndOwner Owner window
//
// Returns:
// S_OK is succeeded
// E_FAIL if not
//
// Author: deonb 8 Feb 2001
//
// Notes: Asserts on failure
//
HRESULT HrAssertMenuStructuresValid(HWND hwndOwner)
{
#ifdef DBG
static fBeenHereDoneThat = FALSE;
if (fBeenHereDoneThat)
{
return S_OK;
}
else
{
fBeenHereDoneThat = TRUE;
}
TraceFileFunc(ttidMenus);
HRESULT hr;
hr = HrAssertCommandMatrixIntegrity();
return hr;
#else
return S_OK;
#endif
}
//+---------------------------------------------------------------------------
//
// Member: AdjustNCCS
//
// Purpose: Up-adjusts an NCCS_STATE flag. Will move ENABLED to DISABLED,
// and DISABLED to REMOVE but not backwards.
//
// Arguments:
// [in out] nccsCurrent NCCS to be adjusted
// [in] nccsNew New state
//
// Returns:
// none
//
// Author: deonb 8 Feb 2001
//
// Notes:
//
inline void AdjustNCCS(OUT IN NCCS_STATE& nccsCurrent, IN NCCS_STATE nccsNew)
{
if (nccsNew > nccsCurrent)
{
nccsCurrent = nccsNew;
}
}
inline BOOL fMatchFlags(IN DWORD dwFlagsMask, IN DWORD dwFlagsTest, IN DWORD dwNegateFlagMask, IN DWORD dwNegateFlagTest)
{
bool bMatch = FALSE;
if ( (0xffffffff == dwFlagsTest) || // Means always succeed.
(dwFlagsMask & dwFlagsTest) )
{
bMatch = TRUE;
}
else
{
bMatch = FALSE;
}
if ( (dwNegateFlagMask & dwNegateFlagTest) == dwNegateFlagTest) // Do a negative compare
{
return !bMatch;
}
else
{
return bMatch;
}
}
//+---------------------------------------------------------------------------
//
// Member: HrGetCommandStateFromCMDTABLEEntry
//
// Purpose: Get the command state for a given Connection Folder Entry,
// given the Command Table Entry entry that should be used.
//
// Arguments:
// [in] cfe Connection Folder Entry
// [in] cte Command Table Entry
// [in] fMultiSelect Was this part of a multi-selection?
// [out] nccs State that the item should be (NCCS_ENABLED/NCCS_DISABLED/NCCS_NOTSHOWN)
//
// Returns:
// none
//
// Author: deonb 8 Feb 2001
//
// Notes: This function uses Cached Permissions. YOU MUST CALL RefreshAllPermission before calling this function.
//
HRESULT HrGetCommandStateFromCMDTABLEEntry(IN const CConFoldEntry& cfe, IN const COMMANDENTRY& cte, IN BOOL fMultiSelect, OUT NCCS_STATE& nccs, OUT LPDWORD pdwResourceId)
{
TraceFileFunc(ttidMenus);
Assert(pdwResourceId);
HRESULT hr = S_OK;
nccs = NCCS_ENABLED;
DWORD dwNCMbm = (1 << cfe.GetNetConMediaType()); // Convert to bitmask
// If we're a wizard, add as Wizard media type.
if (cfe.GetWizard() == WIZARD_MNC)
{
dwNCMbm |= NBM_MNC_WIZARD;
dwNCMbm &= ~NBM_INCOMING; // clear the INCOMINGCONNECTIONS flag (old NCM_NONE) if we're a wizard.
}
else if (cfe.GetWizard() == WIZARD_HNW)
{
dwNCMbm |= NBM_HNW_WIZARD;
dwNCMbm &= ~NBM_INCOMING; // clear the INCOMINGCONNECTIONS flag (old NCM_NONE) if we're a wizard.
}
DWORD dwNCSbm = (1 << cfe.GetNetConStatus()); // Convert to bitmask
DWORD dwNCCF = cfe.GetCharacteristics(); // Already a bitmask
// Check if the command can participate in multi-select
if ( fMultiSelect &&
!(cte.dwValidWhen & NCWHEN_MULTISELECT) )
{
AdjustNCCS(nccs, NCCS_DISABLED);
}
// Check if the command should be visible
if (!((fMatchFlags(dwNCMbm, cte.dwMediaTypeVisible, cte.dwFlags, NB_NEGATE_VIS_NBM_MATCH)) &&
(fMatchFlags(dwNCSbm, cte.dwStatusVisible, cte.dwFlags, NB_NEGATE_VIS_NBS_MATCH)) &&
(fMatchFlags(dwNCCF , cte.dwCharacteristicsVisible,cte.dwFlags, NB_NEGATE_VIS_CHAR_MATCH)) ))
{
AdjustNCCS(nccs, NCCS_NOTSHOWN);
}
// Check if the command should be grayed out
if (!((fMatchFlags(dwNCMbm, cte.dwMediaTypeActive, cte.dwFlags, NB_NEGATE_ACT_NBM_MATCH)) &&
(fMatchFlags(dwNCSbm, cte.dwStatusActive, cte.dwFlags, NB_NEGATE_ACT_NBS_MATCH)) &&
(fMatchFlags(dwNCCF , cte.dwCharacteristicsActive, cte.dwFlags, NB_NEGATE_ACT_CHAR_MATCH)) ))
{
AdjustNCCS(nccs, NCCS_DISABLED);
}
// Check if the command should be grayed out based on permissions
for (DWORD x = 0; nccs == NCCS_ENABLED, x < g_cteCommandPermissionsMatrixCount; x++)// Permissions won't affect NOT_SHOWN or DISABLED
{
const COMMANDPERMISSIONSENTRY cpe = g_cteCommandPermissionsMatrix[x];
if ( (cpe.iCommandId == cte.iCommandId) &&
(fMatchFlags(dwNCMbm, cpe.dwMediaType, cpe.dwFlags, NB_NEGATE_NBM_MATCH)) &&
(fMatchFlags(dwNCCF, cpe.dwCharacteristicsActive, cpe.dwFlags, NB_NEGATE_CHAR_MATCH)) )
{
for (DWORD dwPerm = 0; dwPerm < sizeof(DWORD)*8; dwPerm++)
{
if (cpe.dwPermissionsActive & (1 << static_cast<DWORD64>(dwPerm)) )
{
if (!FHasPermissionFromCache(dwPerm))
{
if (cpe.dwFlags & NB_REMOVE_IF_NOT_MATCH)
{
AdjustNCCS(nccs, NCCS_NOTSHOWN);
}
else
{
AdjustNCCS(nccs, NCCS_DISABLED);
}
break; // will break anyway.
}
}
}
if (APPLY_TO_USER & cpe.ncpAppliesTo)
{
break;
}
if ( (APPLY_TO_POWERUSERS & cpe.ncpAppliesTo) && FIsUserPowerUser() )
{
break;
}
if ( (APPLY_TO_NETCONFIGOPS & cpe.ncpAppliesTo) && FIsUserNetworkConfigOps() )
{
break;
}
if ( (APPLY_TO_ADMIN & cpe.ncpAppliesTo) && FIsUserAdmin())
{
break;
}
// At this point all group access checks failed, so disable the connection.
AdjustNCCS(nccs, NCCS_DISABLED);
break;
}
}
// Check for callback
if ( (nccs != NCCS_NOTSHOWN) &&
(cte.pfnHrEnableDisableCB) )
{
HRESULT hrTmp;
NCCS_STATE nccsTemp;
hrTmp = (*cte.pfnHrEnableDisableCB)(cfe, fMultiSelect, cte.iCommandId, nccsTemp);
if (S_OK == hrTmp)
{
AdjustNCCS(nccs, nccsTemp);
}
else
{
if (FAILED(hrTmp))
{
AdjustNCCS(nccs, NCCS_NOTSHOWN);
}
} // If the function returns S_FALSE it's an indication it didn't change the state.
}
// Check for Resource String callback:
if ( (nccs != NCCS_NOTSHOWN) && // What's the point?
(0 == *pdwResourceId) && // Must not already have a resource Id
(cte.pfnHrCustomMenuStringCB) )
{
HRESULT hrTmp;
DWORD dwResourceIdTmp = *pdwResourceId;
hrTmp = (*cte.pfnHrCustomMenuStringCB)(cfe, cte.iCommandId, &dwResourceIdTmp);
if (S_OK == hr)
{
*pdwResourceId = dwResourceIdTmp;
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: HrGetCommandState
//
// Purpose: Get the command state for a given Connection Folder Entry,
// given the Command ID.
//
// Arguments:
// [in] cfpl List (0 or more) of PIDLs that are selected
// [in] dwCmdID Command ID
// [out] nccs State that the item should be (NCCS_ENABLED/NCCS_DISABLED/NCCS_NOTSHOWN)
//
// Returns:
// none
//
// Author: deonb 8 Feb 2001
//
// Notes:
//
HRESULT HrGetCommandState(IN const PCONFOLDPIDLVEC& cfpl, IN const DWORD dwCmdID, OUT NCCS_STATE& nccs, OUT LPDWORD pdwResourceId, IN DWORD cteHint, IN DWORD dwOverrideFlag)
{
TraceFileFunc(ttidMenus);
Assert(pdwResourceId);
if (!pdwResourceId)
{
return E_POINTER;
}
RefreshAllPermission();
HRESULT hr = S_OK;
BOOL bFound = FALSE;
DWORD dwNumItems = cfpl.size();
*pdwResourceId = 0;
if ( dwOverrideFlag & NB_FLAG_ON_TOPMENU )
{
for (DWORD x = 0; x < g_cteCommandMatrixCount; x++)
{
if ( (g_cteCommandMatrix[x].iCommandId == dwCmdID) )
{
bFound = TRUE;
const COMMANDENTRY& cte = g_cteCommandMatrix[x];
if ((cte.dwValidWhen == NCWHEN_TOPLEVEL) || // Toplevel-ONLY menu (doesn't matter if items).
((cte.dwValidWhen & NCWHEN_TOPLEVEL) &&
(!dwNumItems || (cte.dwValidWhen & NCWHEN_TOPLEVEL_DISREGARD_ITEM)) ) )
{ // Must be marked to allow incompatible selection,
nccs = NCCS_ENABLED; // Otherwise, we'll do the item check (below).
// Check for permissions
for (DWORD x = 0; nccs == NCCS_ENABLED, x < g_cteCommandPermissionsMatrixCount; x++)// Permissions won't affect NOT_SHOWN or DISABLED
{
const COMMANDPERMISSIONSENTRY cpe = g_cteCommandPermissionsMatrix[x];
if ( (cpe.iCommandId == cte.iCommandId) &&
(cpe.dwFlags & NB_TOPLEVEL_PERM) )
{
for (DWORD dwPerm = 0; dwPerm < sizeof(DWORD)*8; dwPerm++)
{
if (cpe.dwPermissionsActive & (1 << static_cast<DWORD64>(dwPerm)) )
{
if (!FHasPermissionFromCache(dwPerm))
{
if (cpe.dwFlags & NB_REMOVE_IF_NOT_MATCH)
{
AdjustNCCS(nccs, NCCS_NOTSHOWN);
}
else
{
AdjustNCCS(nccs, NCCS_DISABLED);
}
break; // will break anyway.
}
}
}
if (APPLY_TO_USER & cpe.ncpAppliesTo)
{
break;
}
if ( (APPLY_TO_NETCONFIGOPS & cpe.ncpAppliesTo) && FIsUserNetworkConfigOps() )
{
break;
}
if ( (APPLY_TO_ADMIN & cpe.ncpAppliesTo) && FIsUserAdmin())
{
break;
}
// At this point all group access checks failed, so disable the connection.
AdjustNCCS(nccs, NCCS_DISABLED);
break;
}
}
// Check for callback
if (cte.pfnHrEnableDisableCB)
{
HRESULT hrTmp;
NCCS_STATE nccsTemp;
CONFOLDENTRY cfe;
cfe.clear();
if (dwNumItems > 0)
{
hrTmp = cfpl[0].ConvertToConFoldEntry(cfe);
if (FAILED(hrTmp))
{
cfe.clear();
}
}
hrTmp = (*cte.pfnHrEnableDisableCB)(cfe, dwNumItems > 1, cte.iCommandId, nccsTemp);
if (S_OK == hrTmp)
{
AdjustNCCS(nccs, nccsTemp);
}
else
{
if (FAILED(hrTmp))
{
AdjustNCCS(nccs, NCCS_NOTSHOWN);
}
} // If the function returns S_FALSE it's an indication it didn't change the state.
}
if (!(NB_REMOVE_TOPLEVEL_ITEM & cte.dwFlags))
{
if (nccs == NCCS_NOTSHOWN)
{
nccs = NCCS_DISABLED;
}
}
return S_OK;
}
break; // we won't find another CMDID
}
}
if (!dwNumItems)
{
nccs = NCCS_DISABLED;
if (bFound)
{
return S_OK;
}
else
{
return E_FILE_NOT_FOUND;
}
}
}
AssertSz(dwNumItems, "You don't have any items selected, but you're not a top-level menu... how come?");
bFound = FALSE;
nccs = NCCS_ENABLED;
// This will effectively loop through all the selected PIDLs and apply the strictest
// nccs that applies to everything.
for (PCONFOLDPIDLVEC::const_iterator cfp = cfpl.begin(); cfp != cfpl.end(); cfp++)
{
CONFOLDENTRY cfe;
hr = cfp->ConvertToConFoldEntry(cfe);
if (FAILED(hr))
{
return E_FAIL;
}
DWORD dwPos = 0xffffffff;
// This is a O(n^(2+)) algorithm when called from HrBuildMenu.
// We pass a hint to check if we can quickly find the cte.
if ( (cteHint != 0xffffffff) &&
(g_cteCommandMatrix[cteHint].iCommandId == dwCmdID) )
{
dwPos = cteHint;
}
if (dwPos == 0xffffffff)
{
for (DWORD x = 0; x < g_cteCommandMatrixCount && SUCCEEDED(hr); x++)
{
if (g_cteCommandMatrix[x].iCommandId == dwCmdID)
{
dwPos = x;
break;
}
}
}
if (dwPos == 0xffffffff)
{
return E_FILE_NOT_FOUND;
}
else
{
bFound = TRUE;
NCCS_STATE nccsTmp;
hr = HrGetCommandStateFromCMDTABLEEntry(cfe, g_cteCommandMatrix[dwPos], dwNumItems != 1, nccsTmp, pdwResourceId);
if (FAILED(hr))
{
return hr;
}
AdjustNCCS(nccs, nccsTmp);
if ( (dwOverrideFlag & NB_FLAG_ON_TOPMENU) &&
(!(NB_REMOVE_TOPLEVEL_ITEM & g_cteCommandMatrix[dwPos].dwFlags)) &&
(nccs == NCCS_NOTSHOWN) )
{
nccs = NCCS_DISABLED;
}
}
}
if (!bFound)
{
return E_FILE_NOT_FOUND;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: HrGetCheckState
//
// Purpose: Get the check state for a given Connection Folder Entry,
// given the Command ID.
//
// Arguments:
// [in] cfpl List (0 or more) of PIDLs that are selected
// [in] dwCmdID Command ID
// [out] nccs State that the item should be (NCCS_CHECKED/NCCS_UNCHECKED)
//
// Returns:
// HRESULT
//
// Author: deonb 7 Mar 2001
//
// Notes:
//
HRESULT HrGetCheckState(IN const PCONFOLDPIDLVEC& cfpl, IN const DWORD dwCmdID, OUT NCCS_CHECKED_STATE& nccs)
{
HRESULT hr = S_FALSE;
DWORD dwLoop = 0;
nccs = NCCS_UNCHECKED;
for (; dwLoop < g_nFolderCheckCount; dwLoop++)
{
if (dwCmdID == g_cceFolderChecks[dwLoop].iCommandId)
{
switch(g_cceFolderChecks[dwLoop].iCommandId)
{
case CMIDM_CONMENU_OPERATOR_ASSIST:
hr = S_OK;
if (g_fOperatorAssistEnabled)
{
nccs = NCCS_CHECKED;
}
break;
default:
break;
}
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: NCCMDFromSFV
//
// Purpose: Return a NetShell CMDID for Shell Internal IDs
//
// Arguments:
// [in] iCmdID CMDID to map
//
// Returns:
// Returns iCmdID if not shell message, or a iCmdID mapping
//
// Author: deonb 8 Feb 2001
//
// Notes:
//
int NCCMDFromSFV(int iCmdID, DWORD idCmdFirst)
{
for (int x = 0; x < g_cteSFVCommandMapCount; x++)
{
if (g_cteSFVCommandMap[x].iSFVCommandId == iCmdID)
{
return g_cteSFVCommandMap[x].iCommandId + idCmdFirst;
}
}
return iCmdID;
}
//+---------------------------------------------------------------------------
//
// Function: HrUpdateMenuItemChecks
//
// Purpose: Walk through the list of checkmark-able commands and check if
// applicable.
//
// Arguments:
// None
//
// Returns:
//
// Author: deonb 7 Mar 2001
//
// Notes:
//
HRESULT HrUpdateMenuItemChecks(IN PCONFOLDPIDLVEC& cfpl, IN OUT HMENU hMenu, IN DWORD idCmdFirst)
{
HRESULT hr = S_FALSE;
DWORD dwLoop = 0;
Assert(hMenu)
if (!hMenu)
{
return E_INVALIDARG;
}
int cMenuItems = GetMenuItemCount(hMenu);
for (int x = 0; x < cMenuItems; x++)
{
UINT nMenuID = GetMenuItemID(hMenu, x);
NCCS_CHECKED_STATE nccs;
DWORD dwCustomResourceId = 0;
DWORD dwCmdId = NCCMDFromSFV(nMenuID, idCmdFirst) - idCmdFirst;
hr = HrGetCheckState(cfpl, dwCmdId, nccs);
if (S_OK == hr) // don't need to set if not supported on this item (S_FALSE)
{
CheckMenuItem(
hMenu,
x,
nccs == NCCS_CHECKED ?
MF_CHECKED | MF_BYPOSITION : // checked
MF_UNCHECKED | MF_BYPOSITION); // unchecked
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: HrBuildMenu
//
// Purpose: Build the context menu for for a given Connection Folder Entry..
//
// Arguments:
// [in out] hMenu Handle to menu which is to be updated
// [in] fVerbsOnly Should return Verbs only (shortcuts)
// [in] cfpl List (0 or more) of PIDLs that are selected
// [in] idCmdFirst Min value the handler can specify for a menu item
//
// Returns:
// none
//
// Author: deonb 8 Feb 2001
//
// Notes:
//
HRESULT HrBuildMenu(IN OUT HMENU &hMenu, IN BOOL fVerbsOnly, IN PCONFOLDPIDLVEC& cfpl, IN DWORD idCmdFirst)
{
TraceFileFunc(ttidMenus);
HRESULT hr = S_OK;
Assert(hMenu)
if (!hMenu)
{
return E_INVALIDARG;
}
DWORD dwCurrentDefaultPriority = 0;
BOOL fShouldAppendSeparator = FALSE;
DWORD dwInsertPos = 1;
for (DWORD x = 0; x < g_cteCommandMatrixCount && SUCCEEDED(hr); x++)
{
const COMMANDENTRY& cte = g_cteCommandMatrix[x];
if ( (fVerbsOnly) && !(cte.dwFlags & NB_VERB) )
{
continue;
}
if (CMIDM_SEPARATOR == cte.iCommandId)
{
fShouldAppendSeparator = TRUE;
}
else
{
NCCS_STATE nccs;
DWORD dwCustomResourceId = 0;
hr = HrGetCommandState(cfpl, cte.iCommandId, nccs, &dwCustomResourceId, x);
if (SUCCEEDED(hr))
{
if ( nccs != NCCS_NOTSHOWN )
{
if (fShouldAppendSeparator)
{
fShouldAppendSeparator = FALSE;
if (!InsertMenu(hMenu, dwInsertPos++, MF_BYPOSITION | MF_SEPARATOR, CMIDM_SEPARATOR, NULL))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
LPCWSTR szMenuString;
if (!dwCustomResourceId)
{
szMenuString = SzLoadIds(IDS_MENU_CMIDM_START + cte.iCommandId - CMIDM_FIRST);
}
else
{
szMenuString = SzLoadIds(dwCustomResourceId);
}
if (!InsertMenu(hMenu, dwInsertPos++, MF_BYPOSITION | MF_STRING | (nccs == NCCS_DISABLED ? MF_GRAYED : MF_ENABLED), idCmdFirst + cte.iCommandId - CMIDM_FIRST, szMenuString))
{
AssertSz(FALSE, "Couldn't append menu item");
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
if ( (nccs == NCCS_ENABLED) &&
(cte.dwDefaultPriority > dwCurrentDefaultPriority) ) // Not 0 is implied.
{
dwCurrentDefaultPriority = cte.dwDefaultPriority;
if (!SetMenuDefaultItem(hMenu, idCmdFirst + cte.iCommandId - CMIDM_FIRST, FALSE))
{
AssertSz(FALSE, "Couldn't set default menu item");
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
}
}
}
else
{
if (E_FILE_NOT_FOUND == hr)
{
AssertSz(FALSE, "Didn't find the CMDID inside CMDTABLE");
}
}
}
}
if (SUCCEEDED(hr))
{
hr = HrUpdateMenuItemChecks(cfpl, hMenu, idCmdFirst);
if (S_FALSE == hr)
{
hr = S_OK;
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: HrUpdateMenu
//
// Purpose: Update a menu for for a given Connection Folder Entry..
//
// Arguments:
// [in out] hMenu Handle to menu which is to be updated
// [in] cfpl List (0 or more) of PIDLs that are selected
// [in] idCmdFirst Min value the handler can specify for a menu item
//
// Returns:
// none
//
// Author: deonb 8 Feb 2001
//
// Notes:
//
HRESULT HrUpdateMenu(IN OUT HMENU &hMenu, IN PCONFOLDPIDLVEC& cfpl, IN DWORD idCmdFirst)
{
TraceFileFunc(ttidMenus);
HRESULT hr = S_OK;
Assert(hMenu)
if (!hMenu)
{
return E_INVALIDARG;
}
int cMenuItems = GetMenuItemCount(hMenu);
for (int x = 0; x < cMenuItems; x++)
{
UINT nMenuID = GetMenuItemID(hMenu, x);
// UINT uiState = GetMenuState(hMenu, nMenuID, MF_BYCOMMAND );
NCCS_STATE nccs;
DWORD dwCustomResourceId = 0;
DWORD dwCmdId = NCCMDFromSFV(nMenuID, idCmdFirst) - idCmdFirst;
hr = HrGetCommandState(cfpl, dwCmdId, nccs, &dwCustomResourceId, 0xffffffff, NB_FLAG_ON_TOPMENU);
if (SUCCEEDED(hr))
{
if (nccs == NCCS_NOTSHOWN)
{
#ifdef DBG
WCHAR szTemp[MAX_PATH];
GetMenuStringW(hMenu, x, szTemp, MAX_PATH, MF_BYPOSITION );
TraceTag(ttidMenus, "Received request to permanently remove menu item: '%S' for CMDID: %d MenuID: %d", szTemp, dwCmdId, nMenuID);
#endif
RemoveMenu(hMenu, x, MF_BYPOSITION);
}
else
{
EnableMenuItem(
hMenu,
x,
nccs == NCCS_ENABLED ?
MF_ENABLED | MF_BYPOSITION: // enable
MF_GRAYED | MF_BYPOSITION);
}
}
NCCS_CHECKED_STATE nccCheckedState;
hr = HrGetCheckState(cfpl, dwCmdId, nccCheckedState);
if (S_OK == hr) // don't need to set if not supported on this item (S_FALSE)
{
CheckMenuItem(
hMenu,
x,
nccCheckedState == NCCS_CHECKED ?
MF_CHECKED | MF_BYPOSITION : // checked
MF_UNCHECKED | MF_BYPOSITION); // unchecked
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: HasPermissionToRenameConnection
//
// Purpose: Checks if the Thread Local user has access to rename a given
// connection
//
// Arguments:
// [in] pcfp PIDL that wants to be renamed
//
// Returns:
// TRUE if has permissions
// FALSE if no permissions
//
// Author: deonb 8 Feb 2001
//
// Notes:
// ISSUE: Move out of this file
//
BOOL HasPermissionToRenameConnection(const PCONFOLDPIDL& pcfp)
{
TraceFileFunc(ttidMenus);
BOOL fPermission = FALSE;
// ISSUE: Due to a clarification in the spec this code is unreasonably complex.
// If possible clean it up in the future.
if (((!(pcfp->dwCharacteristics & NCCF_ALL_USERS) &&
FHasPermissionFromCache(NCPERM_RenameMyRasConnection))))
{
fPermission = TRUE;
}
else if (FIsPolicyConfigured(NCPERM_RenameConnection))
{
if (((!(pcfp->dwCharacteristics & NCCF_ALL_USERS) &&
FHasPermissionFromCache(NCPERM_RenameMyRasConnection))))
{
fPermission = TRUE;
}
else if ((pcfp->ncm != NCM_LAN) && (pcfp->dwCharacteristics & NCCF_ALL_USERS) &&
FHasPermissionFromCache(NCPERM_RenameConnection) ||
(pcfp->ncm == NCM_LAN) && FHasPermissionFromCache(NCPERM_RenameConnection))
{
fPermission = TRUE;
}
}
else if (((pcfp->ncm == NCM_LAN) && FHasPermissionFromCache(NCPERM_RenameLanConnection))
|| ((pcfp->ncm != NCM_LAN) && (pcfp->dwCharacteristics & NCCF_ALL_USERS) &&
FHasPermissionFromCache(NCPERM_RenameAllUserRasConnection)))
{
fPermission = TRUE;
}
return fPermission;
}
//+---------------------------------------------------------------------------
//
// Function: SetConnectMenuItem
//
// Purpose: This function goes in and modifies the first menu item so
// that it shows the correct test based on the connection
// state (enabled or not) or the connection type (LAN / WAN).
//
// Arguments:
// hmenu [in] Menu to operate on
// bLan [in] Whether or not this is a LAN connection
// idCmdFirst [in] Are commands are really an offset to this value
// bEnable [in] If the connection is enabled or not
//
// Returns:
//
// Author: mbend 8 Mar 2000
//
// Notes:
//
VOID SetConnectMenuItem(
HMENU hmenu,
BOOL bLan,
INT idCmdFirst,
BOOL bEnable)
{
// Different strings for WAN/LAN
INT iEnableString =
bLan ? IDS_DISABLE_MENUITEM : IDS_DISCONNECT_MENUITEM;
INT iDisableString =
bLan ? IDS_ENABLE_MENUITEM : IDS_CONNECT_MENUITEM;
INT iMenuString =
bEnable ? iEnableString : iDisableString;
PCWSTR pszMenuString = SzLoadIds(iMenuString);
MENUITEMINFO mii;
// Different commands for WAN/LAN
INT iConnect = bLan ? CMIDM_ENABLE : CMIDM_CONNECT;
INT iDisconnect = bLan ? CMIDM_DISABLE : CMIDM_DISCONNECT;
INT iOffset = bEnable ? iDisconnect : iConnect;
INT iNewCommand = idCmdFirst + iOffset;
Assert(pszMenuString);
// Set the menuitem fields
//
mii.cbSize = sizeof(MENUITEMINFO);
mii.fMask = MIIM_TYPE | MIIM_ID;
mii.fType = MFT_STRING;
mii.dwTypeData = (PWSTR) pszMenuString;
mii.wID = iNewCommand;
// This is assuming that we want to take out the first menu item.
if (!SetMenuItemInfo(hmenu, 0, TRUE, &mii))
{
TraceTag(ttidMenus, "SetMenuItemInfo returned: 0x%08x for CMIDM_DISCONNECT",
GetLastError());
}
}
//+---------------------------------------------------------------------------
//
// Function: HrSetConnectDisconnectMenuItem
//
// Purpose: Modify the menu item (if necessary) for connect/disconnect.
// We change this back and forth as needed since only one can be
// supported at a time, and those in charge don't want both
// appearing at any given time.
//
// Arguments:
// apidlSelected [in] List of selected objects
// cPidl [in] Count of selected objects
// hmenu [in] Our menu handle
//
// Returns:
//
// Author: jeffspr 1 May 1998
//
// Notes:
//
HRESULT HrSetConnectDisconnectMenuItem(
const PCONFOLDPIDLVEC& apidlSelected,
HMENU hmenu,
INT idCmdFirst)
{
HRESULT hr = S_OK;
if (apidlSelected.size() == 1)
{
Assert(!apidlSelected[0].empty() );
const PCONFOLDPIDL& pcfp = apidlSelected[0];
switch(pcfp->ncs)
{
case NCS_CONNECTED:
case NCS_DISCONNECTING:
case NCS_MEDIA_DISCONNECTED:
case NCS_INVALID_ADDRESS:
case NCS_AUTHENTICATING:
case NCS_AUTHENTICATION_FAILED:
case NCS_AUTHENTICATION_SUCCEEDED:
case NCS_CREDENTIALS_REQUIRED:
SetConnectMenuItem(hmenu, IsMediaLocalType(pcfp->ncm), idCmdFirst, TRUE);
break;
case NCS_DISCONNECTED:
case NCS_CONNECTING:
case NCS_HARDWARE_NOT_PRESENT:
case NCS_HARDWARE_DISABLED:
case NCS_HARDWARE_MALFUNCTION:
SetConnectMenuItem(hmenu, IsMediaLocalType(pcfp->ncm), idCmdFirst, FALSE);
break;
default:
AssertSz(FALSE, "HrSetConnectDisconnectMenuItem: What in the heck state is this?");
break;
}
}
TraceHr(ttidMenus, FAL, hr, FALSE, "HrSetConnectDisconnectMenuItem");
return hr;
}
HRESULT HrCanRenameConnection(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if (cfe.empty())
{
return S_FALSE;
}
if (cfe.GetCharacteristics() & NCCF_INCOMING_ONLY)
{
if (cfe.GetNetConMediaType() == NCM_NONE) // Incoming server - don't care
{
return S_FALSE;
}
else
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
}
else
{
CPConFoldPidl<ConFoldPidl_v2> pcfp;
cfe.ConvertToPidl(pcfp);
if (!HasPermissionToRenameConnection(pcfp))
{
nccs = NCCS_DISABLED;
}
else
{
return S_FALSE;
}
return S_OK;
}
}
HRESULT HrCanShowProperties(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if (cfe.empty())
{
return S_FALSE;
}
if (cfe.GetCharacteristics() & NCCF_INCOMING_ONLY)
{
if (cfe.GetNetConMediaType() == NCM_NONE) // Incoming server - don't care
{
return S_FALSE;
}
else
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
}
return S_FALSE;
}
BOOL IsBridgeInstalled()
{
BOOL fBridgePresent = FALSE; // fail to false
HRESULT hResult;
IHNetCfgMgr* pHomeNetConfigManager;
hResult = HrCreateInstance(CLSID_HNetCfgMgr, CLSCTX_INPROC, &pHomeNetConfigManager);
if(SUCCEEDED(hResult))
{
IHNetBridgeSettings* pNetBridgeSettings;
hResult = pHomeNetConfigManager->QueryInterface(IID_IHNetBridgeSettings, reinterpret_cast<void**>(&pNetBridgeSettings));
if(SUCCEEDED(hResult))
{
IHNetBridge* pNetBridge;
IEnumHNetBridges* pNetBridgeEnum;
hResult = pNetBridgeSettings->EnumBridges(&pNetBridgeEnum);
if(SUCCEEDED(hResult))
{
hResult = pNetBridgeEnum->Next(1, &pNetBridge, NULL);
if(S_OK == hResult)
{
fBridgePresent = TRUE;
ReleaseObj(pNetBridge);
}
ReleaseObj(pNetBridgeEnum);
}
ReleaseObj(pNetBridgeSettings);
}
ReleaseObj(pHomeNetConfigManager);
}
return fBridgePresent;
}
HRESULT HrIsBridgeSupported(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
// if (cfe.empty())
// {
// return S_FALSE;
// }
//
#ifdef _WIN64
// Homenet technologies are not available at all on IA64
nccs = NCCS_NOTSHOWN;
return S_OK;
#else
// If the machine is Advanced server or data center, delete the bridge menu item
OSVERSIONINFOEXW verInfo = {0};
ULONGLONG ConditionMask = 0;
verInfo.dwOSVersionInfoSize = sizeof(verInfo);
verInfo.wSuiteMask = VER_SUITE_ENTERPRISE;
VER_SET_CONDITION(ConditionMask, VER_SUITENAME, VER_AND);
if (VerifyVersionInfo(&verInfo, VER_SUITENAME, ConditionMask))
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
else
{
BOOL fUserIsAdmin = FALSE;
HRESULT hr = S_OK;
CComPtr<INetConnectionUiUtilities> pConnectionUi;
hr = CoCreateInstance(CLSID_NetConnectionUiUtilities, NULL, CLSCTX_INPROC,
IID_INetConnectionUiUtilities, reinterpret_cast<void**>(&pConnectionUi));
if (FAILED(hr))
{
return hr;
}
fUserIsAdmin = FIsUserAdmin();
if (IsBridgeInstalled())
{
if (CMIDM_CREATE_BRIDGE == iCommandId)
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
else if (CMIDM_CONMENU_CREATE_BRIDGE == iCommandId)
{
nccs = NCCS_DISABLED;
return S_OK;
}
else // CMIDM_ADD_TO_BRIDGE or CMID_REMOVE_FROM_BRIDGE
{
if (!fUserIsAdmin || !pConnectionUi->UserHasPermission(NCPERM_AllowNetBridge_NLA))
{
nccs = NCCS_DISABLED;
return S_OK;
}
else
{
return S_FALSE; // Leave alone
}
}
}
else
{
if ( (CMIDM_CREATE_BRIDGE == iCommandId) ||
(CMIDM_CONMENU_CREATE_BRIDGE == iCommandId) )
{
if (!fUserIsAdmin || !pConnectionUi->UserHasPermission(NCPERM_AllowNetBridge_NLA))
{
nccs = NCCS_DISABLED;
return S_OK;
}
else
{
return S_FALSE; // Leave alone
}
}
else // CMIDM_ADD_TO_BRIDGE or CMID_REMOVE_FROM_BRIDGE
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
}
}
#endif
}
HRESULT HrOsIsLikePersonal()
{
if (IsOS(OS_PERSONAL))
{
return S_OK;
}
if (IsOS(OS_PROFESSIONAL))
{
LPWSTR pszDomain;
NETSETUP_JOIN_STATUS njs = NetSetupUnknownStatus;
if (NERR_Success == NetGetJoinInformation(NULL, &pszDomain, &njs))
{
NetApiBufferFree(pszDomain);
}
if (NetSetupDomainName == njs)
{
return S_FALSE; // connected to domain
}
else
{
return S_OK; // Professional, but not a domain member
}
}
return S_FALSE; // not personal or non-domain professional
}
HRESULT HrShouldHaveHomeNetWizard()
{
#ifdef _WIN64
return S_FALSE;
#else
if ( ( HrOsIsLikePersonal() == S_OK ) &&
FIsUserAdmin())
{
return S_OK;
}
else
{
return S_FALSE;
}
#endif
}
HRESULT HrIsHomeNewWizardSupported(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if (S_OK == HrShouldHaveHomeNetWizard() )
{
nccs = NCCS_ENABLED;
return S_OK;
}
else
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
}
HRESULT HrIsTroubleShootSupported(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if ( cfe.empty() && (!fMultiSelect) )
{
if ( ! IsOS(OS_ANYSERVER) )
{
nccs = NCCS_ENABLED;
return S_OK;
}
else
{
nccs = NCCS_ENABLED;
return S_OK;
}
}
else
{
nccs = NCCS_DISABLED;
return S_OK;
}
}
HRESULT HrIsNCWSupported(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if ( (HrOsIsLikePersonal() == S_OK) &&
!FIsUserAdmin() )
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
else
{
return S_FALSE;
}
}
HRESULT HrIsMediaWireless(
IN const CConFoldEntry& cfe,
IN BOOL fMultiSelect,
IN int iCommandId,
OUT NCCS_STATE& nccs
)
{
if (cfe.GetNetConSubMediaType() != NCSM_WIRELESS)
{
nccs = NCCS_NOTSHOWN;
return S_OK;
}
return S_FALSE; // Continue with processing
}