1852 lines
47 KiB
C
1852 lines
47 KiB
C
|
/*++
|
||
|
|
||
|
Microsoft Confidential
|
||
|
Copyright (c) 1992-1997 Microsoft Corporation
|
||
|
All rights reserved
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
envvar.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Implements the Environment Variables dialog of the System
|
||
|
Control Panel Applet
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Eric Flo (ericflo) 19-Jun-1995
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
15-Oct-1997 scotthal
|
||
|
Complete overhaul
|
||
|
|
||
|
--*/
|
||
|
#include "sysdm.h"
|
||
|
|
||
|
#include <help.h>
|
||
|
// C Runtime
|
||
|
#include <stddef.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <tchar.h>
|
||
|
|
||
|
// for Hydra
|
||
|
#include <winsta.h>
|
||
|
|
||
|
|
||
|
//==========================================================================
|
||
|
// Local Definitions
|
||
|
//==========================================================================
|
||
|
#define LB_SYSVAR 1
|
||
|
#define LB_USERVAR 2
|
||
|
|
||
|
#define SYSTEMROOT TEXT("SystemRoot")
|
||
|
#define SYSTEMDRIVE TEXT("SystemDrive")
|
||
|
|
||
|
//==========================================================================
|
||
|
// Typedefs and Structs
|
||
|
//==========================================================================
|
||
|
|
||
|
// Registry valuename linked-list structure
|
||
|
typedef struct _regval
|
||
|
{
|
||
|
struct _regval *prvNext;
|
||
|
LPTSTR szValueName;
|
||
|
} REGVAL;
|
||
|
|
||
|
|
||
|
//==========================================================================
|
||
|
// Local Functions
|
||
|
//==========================================================================
|
||
|
void EVDoCommand(HWND hDlg, HWND hwndCtl, int idCtl, int iNotify );
|
||
|
void EVSave(HWND hDlg);
|
||
|
void EVCleanUp (HWND hDlg);
|
||
|
PENVAR GetVar(HWND hDlg, UINT VarType, int iSelection);
|
||
|
int FindVar (HWND hwndLB, LPTSTR szVar);
|
||
|
|
||
|
void
|
||
|
SetVar(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT VarType,
|
||
|
IN LPCTSTR szVarName,
|
||
|
IN LPCTSTR szVarValue
|
||
|
);
|
||
|
|
||
|
void
|
||
|
DeleteVar(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT VarType,
|
||
|
IN LPCTSTR szVarName
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// New.../Edit... subdialog functions
|
||
|
//
|
||
|
INT_PTR
|
||
|
APIENTRY
|
||
|
EnvVarsEditDlg(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT uMsg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam
|
||
|
);
|
||
|
|
||
|
void
|
||
|
EVDoEdit(
|
||
|
IN HWND hWnd,
|
||
|
IN UINT VarType,
|
||
|
IN UINT EditType,
|
||
|
IN int iSelection
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
ExpandSystemVar(
|
||
|
IN LPCTSTR pszSrc,
|
||
|
OUT LPTSTR pszDst,
|
||
|
IN DWORD cchDst
|
||
|
);
|
||
|
|
||
|
//==========================================================================
|
||
|
// "Global" Variables for this page
|
||
|
//==========================================================================
|
||
|
BOOL bEditSystemVars = FALSE;
|
||
|
DWORD cxLBSysVars = 0;
|
||
|
BOOL bUserVars = TRUE;
|
||
|
|
||
|
//
|
||
|
// Help ID's
|
||
|
//
|
||
|
|
||
|
DWORD aEnvVarsHelpIds[] = {
|
||
|
IDC_STATIC, NO_HELP,
|
||
|
IDC_ENVVAR_SYS_USERGROUP, (IDH_ENV + 2),
|
||
|
IDC_ENVVAR_SYS_LB_USERVARS, (IDH_ENV + 2),
|
||
|
IDC_ENVVAR_SYS_SYSGROUP, (IDH_ENV + 0),
|
||
|
IDC_ENVVAR_SYS_LB_SYSVARS, (IDH_ENV + 0),
|
||
|
IDC_ENVVAR_SYS_NEWUV, (IDH_ENV + 7),
|
||
|
IDC_ENVVAR_SYS_EDITUV, (IDH_ENV + 8),
|
||
|
IDC_ENVVAR_SYS_NDELUV, (IDH_ENV + 9),
|
||
|
IDC_ENVVAR_SYS_NEWSV, (IDH_ENV + 10),
|
||
|
IDC_ENVVAR_SYS_EDITSV, (IDH_ENV + 11),
|
||
|
IDC_ENVVAR_SYS_DELSV, (IDH_ENV + 12),
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
TCHAR szUserEnv[] = TEXT( "Environment" );
|
||
|
TCHAR szSysEnv[] = TEXT( "System\\CurrentControlSet\\Control\\Session Manager\\Environment" );
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
InitEnvVarsDlg(
|
||
|
IN HWND hDlg
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initializes the environment variables page
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if successful
|
||
|
FALSE if an error occurs
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR szBuffer1[200];
|
||
|
TCHAR szBuffer2[300];
|
||
|
TCHAR szUserName[MAX_USER_NAME];
|
||
|
DWORD dwSize = MAX_USER_NAME;
|
||
|
HWND hwndTemp;
|
||
|
HKEY hkeyEnv;
|
||
|
TCHAR *pszValue;
|
||
|
HANDLE hKey;
|
||
|
DWORD dwBufz, dwValz, dwIndex, dwType;
|
||
|
LONG Error;
|
||
|
TCHAR szTemp[BUFZ];
|
||
|
LPTSTR pszString;
|
||
|
ENVARS *penvar;
|
||
|
int n;
|
||
|
LV_COLUMN col;
|
||
|
LV_ITEM item;
|
||
|
RECT rect;
|
||
|
int cxFirstCol;
|
||
|
DWORD dwSysRegMode;
|
||
|
|
||
|
|
||
|
HourGlass (TRUE);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the first column
|
||
|
//
|
||
|
|
||
|
LoadString (hInstance, IDS_ENVVAR_VARIABLE_HEADING, szBuffer1, 200);
|
||
|
|
||
|
if (!GetClientRect (GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS), &rect)) {
|
||
|
rect.right = 300;
|
||
|
}
|
||
|
|
||
|
cxFirstCol = (int)(rect.right * .3);
|
||
|
|
||
|
col.mask = LVCF_FMT | LVCF_SUBITEM | LVCF_TEXT | LVCF_WIDTH;
|
||
|
col.fmt = LVCFMT_LEFT;
|
||
|
col.cx = cxFirstCol;
|
||
|
col.pszText = szBuffer1;
|
||
|
col.iSubItem = 0;
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_INSERTCOLUMN,
|
||
|
0, (LPARAM) &col);
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_INSERTCOLUMN,
|
||
|
0, (LPARAM) &col);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the second column
|
||
|
//
|
||
|
|
||
|
LoadString (hInstance, IDS_ENVVAR_VALUE_HEADING, szBuffer1, 200);
|
||
|
|
||
|
col.cx = rect.right - cxFirstCol - GetSystemMetrics(SM_CYHSCROLL);
|
||
|
col.iSubItem = 1;
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_INSERTCOLUMN,
|
||
|
1, (LPARAM) &col);
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_INSERTCOLUMN,
|
||
|
1, (LPARAM) &col);
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// Display System Variables from registry in listbox
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
|
||
|
|
||
|
hKey = MemAlloc (LPTR, BUFZ*SIZEOF(TCHAR));
|
||
|
pszString = (LPTSTR) MemAlloc (LPTR, BUFZ*sizeof(TCHAR));
|
||
|
|
||
|
cxLBSysVars = 0;
|
||
|
hkeyEnv = NULL;
|
||
|
|
||
|
// If user is an admin, then try to open the System Environment variables area with R/W, allow to edit
|
||
|
if (IsUserAdmin())
|
||
|
{
|
||
|
dwSysRegMode = KEY_READ | KEY_WRITE;
|
||
|
bEditSystemVars = TRUE;
|
||
|
}
|
||
|
else // If not ad admin, open with Read-Only, disallow edit of System Env variables area
|
||
|
{
|
||
|
dwSysRegMode = KEY_READ;
|
||
|
bEditSystemVars = FALSE;
|
||
|
}
|
||
|
|
||
|
// On failure, just try to open it for reading
|
||
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szSysEnv, 0, dwSysRegMode, &hkeyEnv) != ERROR_SUCCESS) {
|
||
|
hkeyEnv = NULL;
|
||
|
}
|
||
|
|
||
|
if (hkeyEnv)
|
||
|
{
|
||
|
pszValue = (TCHAR *) hKey;
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwValz = BUFZ * SIZEOF(TCHAR);
|
||
|
dwIndex = 0;
|
||
|
|
||
|
// Read all values until an error is encountered
|
||
|
|
||
|
while (!RegEnumValue(hkeyEnv,
|
||
|
dwIndex++, // Index'th value name/data
|
||
|
szTemp, // Ptr to ValueName buffer
|
||
|
&dwBufz, // Size of ValueName buffer
|
||
|
NULL, // Title index return
|
||
|
&dwType, // Type code of entry
|
||
|
(LPBYTE) pszValue, // Ptr to ValueData buffer
|
||
|
&dwValz)) // Size of ValueData buffer
|
||
|
{
|
||
|
if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
|
||
|
goto SysLoop;
|
||
|
|
||
|
//
|
||
|
// Clip length of returned Environment variable string
|
||
|
// to MAX_VALUE_LEN-1, as necessary.
|
||
|
//
|
||
|
|
||
|
pszValue[MAX_VALUE_LEN-1] = TEXT('\0');
|
||
|
|
||
|
ExpandSystemVar (pszValue, pszString, BUFZ);
|
||
|
|
||
|
penvar = (ENVARS *) MemAlloc (LPTR, SIZEOF(ENVARS));
|
||
|
|
||
|
penvar->dwType = dwType;
|
||
|
penvar->szValueName = CloneString( szTemp );
|
||
|
penvar->szValue = CloneString( pszValue );
|
||
|
penvar->szExpValue = CloneString( pszString );
|
||
|
|
||
|
|
||
|
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
item.iItem = (dwIndex - 1);
|
||
|
item.iSubItem = 0;
|
||
|
item.pszText = penvar->szValueName;
|
||
|
item.lParam = (LPARAM) penvar;
|
||
|
|
||
|
n = (int)SendMessage (hwndTemp, LVM_INSERTITEM, 0, (LPARAM) &item);
|
||
|
|
||
|
if (n != -1) {
|
||
|
item.mask = LVIF_TEXT;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 1;
|
||
|
item.pszText = penvar->szExpValue;
|
||
|
|
||
|
SendMessage (hwndTemp, LVM_SETITEMTEXT, n, (LPARAM) &item);
|
||
|
}
|
||
|
|
||
|
SysLoop:
|
||
|
// Reset vars for next iteration
|
||
|
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwValz = BUFZ * SIZEOF(TCHAR);
|
||
|
}
|
||
|
RegCloseKey (hkeyEnv);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// Display USER variables from registry in listbox
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
//
|
||
|
// Set the "User Environments for <username>" string
|
||
|
//
|
||
|
|
||
|
if (GetUserName(szUserName, &dwSize) &&
|
||
|
LoadString (hInstance, IDS_USERENVVARS, szBuffer1, 200)) {
|
||
|
|
||
|
wsprintf (szBuffer2, szBuffer1, szUserName);
|
||
|
SetDlgItemText (hDlg, IDC_ENVVAR_SYS_USERGROUP, szBuffer2);
|
||
|
}
|
||
|
|
||
|
|
||
|
Error = RegCreateKey (HKEY_CURRENT_USER, szUserEnv, &hkeyEnv);
|
||
|
|
||
|
if (Error == ERROR_SUCCESS && hKey)
|
||
|
{
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
|
||
|
|
||
|
pszValue = (TCHAR *) hKey;
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwValz = BUFZ * SIZEOF(TCHAR);
|
||
|
dwIndex = 0;
|
||
|
|
||
|
|
||
|
// Read all values until an error is encountered
|
||
|
|
||
|
while (!RegEnumValue(hkeyEnv,
|
||
|
dwIndex++, // Index'th value name/data
|
||
|
szTemp, // Ptr to ValueName buffer
|
||
|
&dwBufz, // Size of ValueName buffer
|
||
|
NULL, // Title index return
|
||
|
&dwType, // Type code of entry
|
||
|
(LPBYTE) pszValue, // Ptr to ValueData buffer
|
||
|
&dwValz)) // Size of ValueData buffer
|
||
|
{
|
||
|
if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
|
||
|
goto UserLoop;
|
||
|
|
||
|
//
|
||
|
// Clip length of returned Environment variable string
|
||
|
// to MAX_VALUE_LEN-1, as necessary.
|
||
|
//
|
||
|
|
||
|
pszValue[MAX_VALUE_LEN-1] = TEXT('\0');
|
||
|
|
||
|
ExpandEnvironmentStrings (pszValue, pszString, BUFZ);
|
||
|
|
||
|
penvar = (ENVARS *) MemAlloc (LPTR, sizeof(ENVARS));
|
||
|
|
||
|
penvar->dwType = dwType;
|
||
|
penvar->szValueName = CloneString (szTemp);
|
||
|
penvar->szValue = CloneString (pszValue);
|
||
|
penvar->szExpValue = CloneString (pszString);
|
||
|
|
||
|
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
item.iItem = (dwIndex - 1);
|
||
|
item.iSubItem = 0;
|
||
|
item.pszText = penvar->szValueName;
|
||
|
item.lParam = (LPARAM) penvar;
|
||
|
|
||
|
n = (int)SendMessage (hwndTemp, LVM_INSERTITEM, 0, (LPARAM) &item);
|
||
|
|
||
|
if (n != -1) {
|
||
|
item.mask = LVIF_TEXT;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 1;
|
||
|
item.pszText = penvar->szExpValue;
|
||
|
|
||
|
SendMessage (hwndTemp, LVM_SETITEMTEXT, n, (LPARAM) &item);
|
||
|
}
|
||
|
|
||
|
UserLoop:
|
||
|
// Reset vars for next iteration
|
||
|
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwValz = BUFZ * SIZEOF(TCHAR);
|
||
|
|
||
|
}
|
||
|
RegCloseKey (hkeyEnv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Report opening USER Environment key
|
||
|
if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_USER_UNK : IDS_SYSDM_NOOPEN_USER_NOTADMIN,
|
||
|
IDS_SYSDM_TITLE, MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||
|
{
|
||
|
// Free allocated memory since we are returning from here
|
||
|
MemFree ((LPVOID)hKey);
|
||
|
MemFree (pszString);
|
||
|
|
||
|
HourGlass (FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Select the first items in the listviews
|
||
|
// It is important to set the User listview first, and
|
||
|
// then the system. When the system listview is set,
|
||
|
// we will receive a LVN_ITEMCHANGED notification and
|
||
|
// clear the focus in the User listview. But when someone
|
||
|
// tabs to the control the arrow keys will work correctly.
|
||
|
//
|
||
|
|
||
|
item.mask = LVIF_STATE;
|
||
|
item.iItem = 0;
|
||
|
item.iSubItem = 0;
|
||
|
item.state = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_USERVARS,
|
||
|
LVM_SETITEMSTATE, 0, (LPARAM) &item);
|
||
|
|
||
|
SendDlgItemMessage (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS,
|
||
|
LVM_SETITEMSTATE, 0, (LPARAM) &item);
|
||
|
|
||
|
|
||
|
|
||
|
MemFree ((LPVOID)hKey);
|
||
|
MemFree (pszString);
|
||
|
|
||
|
// Set extended LV style for whole line selection
|
||
|
SendDlgItemMessage(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
|
||
|
SendDlgItemMessage(hDlg, IDC_ENVVAR_SYS_LB_USERVARS, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT);
|
||
|
|
||
|
HourGlass (FALSE);
|
||
|
|
||
|
//
|
||
|
// Disable System Var Editing buttons if
|
||
|
// user is not an administrator
|
||
|
//
|
||
|
EnableWindow(
|
||
|
GetDlgItem(hDlg, IDC_ENVVAR_SYS_NEWSV),
|
||
|
bEditSystemVars
|
||
|
);
|
||
|
EnableWindow(
|
||
|
GetDlgItem(hDlg, IDC_ENVVAR_SYS_EDITSV),
|
||
|
bEditSystemVars
|
||
|
);
|
||
|
EnableWindow(
|
||
|
GetDlgItem(hDlg, IDC_ENVVAR_SYS_DELSV),
|
||
|
bEditSystemVars
|
||
|
);
|
||
|
|
||
|
///////////////////
|
||
|
// Return succes //
|
||
|
///////////////////
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
INT_PTR
|
||
|
APIENTRY
|
||
|
EnvVarsDlgProc(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT uMsg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Handles messages sent to the Environment Variables dialog box
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
uMsg -
|
||
|
Supplies message being sent
|
||
|
|
||
|
wParam -
|
||
|
Supplies message parameter
|
||
|
|
||
|
lParam -
|
||
|
Supplies message parameter
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if message was handled
|
||
|
FALSE if message was unhandled
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
INT i = 0;
|
||
|
HWND hWndTemp = NULL;
|
||
|
|
||
|
switch (uMsg)
|
||
|
{
|
||
|
case WM_INITDIALOG:
|
||
|
|
||
|
if (!InitEnvVarsDlg(hDlg)) {
|
||
|
EndDialog (hDlg, 0);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
|
||
|
switch (((NMHDR FAR*)lParam)->code)
|
||
|
{
|
||
|
case LVN_KEYDOWN:
|
||
|
switch (((NMHDR FAR*)lParam)->idFrom) {
|
||
|
case IDC_ENVVAR_SYS_LB_USERVARS:
|
||
|
i = IDC_ENVVAR_SYS_NDELUV;
|
||
|
break;
|
||
|
case IDC_ENVVAR_SYS_LB_SYSVARS:
|
||
|
i = IDC_ENVVAR_SYS_DELSV;
|
||
|
break;
|
||
|
default:
|
||
|
return(FALSE);
|
||
|
break;
|
||
|
} // switch
|
||
|
|
||
|
hWndTemp = GetDlgItem(hDlg, i);
|
||
|
|
||
|
if ((VK_DELETE == ((LV_KEYDOWN FAR *) lParam)->wVKey)) {
|
||
|
if (IsWindowEnabled(hWndTemp)) {
|
||
|
SendMessage(
|
||
|
hDlg,
|
||
|
WM_COMMAND,
|
||
|
MAKEWPARAM(i, BN_CLICKED),
|
||
|
(LPARAM) hWndTemp
|
||
|
);
|
||
|
} // if (IsWindowEnabled...
|
||
|
else {
|
||
|
MessageBeep(MB_ICONASTERISK);
|
||
|
} // else
|
||
|
} // if (VK_DELETE...
|
||
|
break;
|
||
|
|
||
|
|
||
|
case NM_DBLCLK:
|
||
|
switch (((NMHDR FAR*)lParam)->idFrom) {
|
||
|
case IDC_ENVVAR_SYS_LB_USERVARS:
|
||
|
i = IDC_ENVVAR_SYS_EDITUV;
|
||
|
break;
|
||
|
case IDC_ENVVAR_SYS_LB_SYSVARS:
|
||
|
i = IDC_ENVVAR_SYS_EDITSV;
|
||
|
break;
|
||
|
default:
|
||
|
return(FALSE);
|
||
|
break;
|
||
|
} // switch
|
||
|
|
||
|
hWndTemp = GetDlgItem(hDlg, i);
|
||
|
|
||
|
if (IsWindowEnabled(hWndTemp)) {
|
||
|
SendMessage(
|
||
|
hDlg,
|
||
|
WM_COMMAND,
|
||
|
MAKEWPARAM(i, BN_CLICKED),
|
||
|
(LPARAM) hWndTemp
|
||
|
);
|
||
|
} // if (IsWindowEnabled...
|
||
|
else {
|
||
|
MessageBeep(MB_ICONASTERISK);
|
||
|
} // else
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
EVDoCommand(hDlg, (HWND)lParam, LOWORD(wParam), HIWORD(wParam));
|
||
|
break;
|
||
|
|
||
|
case WM_DESTROY:
|
||
|
EVCleanUp (hDlg);
|
||
|
break;
|
||
|
|
||
|
case WM_HELP: // F1
|
||
|
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP, (DWORD_PTR) (LPSTR) aEnvVarsHelpIds);
|
||
|
break;
|
||
|
|
||
|
case WM_CONTEXTMENU: // right mouse click
|
||
|
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU, (DWORD_PTR) (LPSTR) aEnvVarsHelpIds);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
EVDoCommand(
|
||
|
IN HWND hDlg,
|
||
|
IN HWND hwndCtl,
|
||
|
IN int idCtl,
|
||
|
IN int iNotify
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Handles WM_COMMAND messages sent to Environment Variables dialog box
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
hwndCtl -
|
||
|
Supplies window handle of control which sent the WM_COMMAND
|
||
|
|
||
|
idCtl -
|
||
|
Supplies ID of control which sent the WM_COMMAND
|
||
|
|
||
|
iNotify -
|
||
|
Supplies notification code
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR szTemp[MAX_PATH];
|
||
|
int i;
|
||
|
HWND hwndTemp;
|
||
|
PENVAR penvar;
|
||
|
|
||
|
switch (idCtl) {
|
||
|
case IDOK:
|
||
|
EVSave(hDlg);
|
||
|
EndDialog(hDlg, 0);
|
||
|
break;
|
||
|
|
||
|
case IDCANCEL:
|
||
|
EndDialog(hDlg, 0);
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_EDITSV:
|
||
|
EVDoEdit(
|
||
|
hDlg,
|
||
|
SYSTEM_VAR,
|
||
|
EDIT_VAR,
|
||
|
GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS))
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_EDITUV:
|
||
|
EVDoEdit(
|
||
|
hDlg,
|
||
|
USER_VAR,
|
||
|
EDIT_VAR,
|
||
|
GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS))
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_NEWSV:
|
||
|
EVDoEdit(hDlg, SYSTEM_VAR, NEW_VAR, -1);
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_NEWUV:
|
||
|
EVDoEdit(hDlg, USER_VAR, NEW_VAR, -1);
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_DELSV:
|
||
|
i = GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS));
|
||
|
if (-1 != i)
|
||
|
{
|
||
|
penvar = GetVar(hDlg, SYSTEM_VAR, i);
|
||
|
if (penvar)
|
||
|
{
|
||
|
DeleteVar(hDlg, SYSTEM_VAR, penvar->szValueName);
|
||
|
}
|
||
|
} // if
|
||
|
break;
|
||
|
|
||
|
case IDC_ENVVAR_SYS_NDELUV:
|
||
|
i = GetSelectedItem(GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS));
|
||
|
if (-1 != i)
|
||
|
{
|
||
|
penvar = GetVar(hDlg, USER_VAR, i);
|
||
|
if (penvar)
|
||
|
{
|
||
|
DeleteVar(hDlg, USER_VAR, penvar->szValueName);
|
||
|
}
|
||
|
} // if
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
} // switch
|
||
|
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
DeleteVar(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT VarType,
|
||
|
IN LPCTSTR szVarName
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Deletes an environment variable of a given name and type
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
VarType -
|
||
|
Supplies variable type (user or system)
|
||
|
|
||
|
szVarName -
|
||
|
Supplies variable name
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None, although it really should have one someday.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR szTemp2[MAX_PATH];
|
||
|
int i, n;
|
||
|
TCHAR *bBuffer;
|
||
|
TCHAR *pszTemp;
|
||
|
LPTSTR pszString;
|
||
|
HWND hwndTemp;
|
||
|
ENVARS *penvar;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
// Delete listbox entry that matches value in szVarName
|
||
|
// If found, delete entry else ignore
|
||
|
wsprintf(
|
||
|
szTemp2,
|
||
|
TEXT("%s"),
|
||
|
szVarName
|
||
|
);
|
||
|
|
||
|
if (szTemp2[0] == TEXT('\0'))
|
||
|
return;
|
||
|
|
||
|
// Determine which Listbox to use (SYSTEM or USER vars)
|
||
|
switch (VarType) {
|
||
|
case SYSTEM_VAR:
|
||
|
i = IDC_ENVVAR_SYS_LB_SYSVARS;
|
||
|
break;
|
||
|
|
||
|
case USER_VAR:
|
||
|
default:
|
||
|
i = IDC_ENVVAR_SYS_LB_USERVARS;
|
||
|
break;
|
||
|
|
||
|
} // switch (VarType)
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, i);
|
||
|
|
||
|
n = FindVar (hwndTemp, szTemp2);
|
||
|
|
||
|
if (n != -1)
|
||
|
{
|
||
|
// Free existing strings (listbox and ours)
|
||
|
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 0;
|
||
|
|
||
|
|
||
|
if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
|
||
|
} else {
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
if (penvar) {
|
||
|
MemFree (penvar->szValueName);
|
||
|
MemFree (penvar->szValue);
|
||
|
MemFree (penvar->szExpValue);
|
||
|
MemFree ((LPVOID) penvar);
|
||
|
}
|
||
|
|
||
|
SendMessage (hwndTemp, LVM_DELETEITEM, n, 0L);
|
||
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
||
|
|
||
|
// Fix selection state in listview
|
||
|
if (n > 0) {
|
||
|
n--;
|
||
|
}
|
||
|
|
||
|
item.mask = LVIF_STATE;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 0;
|
||
|
item.state = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
|
||
|
SendDlgItemMessage (hDlg, i,
|
||
|
LVM_SETITEMSTATE, n, (LPARAM) &item);
|
||
|
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
SetVar(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT VarType,
|
||
|
IN LPCTSTR szVarName,
|
||
|
IN LPCTSTR szVarValue
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given an environment variable's type (system or user), name, and value,
|
||
|
creates a ENVVARS structure for that environment variable and inserts
|
||
|
it into the proper list view control, deleteing any existing variable
|
||
|
of the same name.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
VarType -
|
||
|
Supplies the type of the environment variable (system or user)
|
||
|
|
||
|
szVarName -
|
||
|
Supplies the name of the environment variable
|
||
|
|
||
|
szVarValue -
|
||
|
Supplies the value of the environment variable
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None, although it really should have one someday.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR szTemp2[BUFZ];
|
||
|
int i, n;
|
||
|
TCHAR *bBuffer;
|
||
|
TCHAR *pszTemp;
|
||
|
LPTSTR pszString;
|
||
|
HWND hwndTemp;
|
||
|
int idTemp;
|
||
|
ENVARS *penvar;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
wnsprintf(szTemp2, ARRAYSIZE(szTemp2), TEXT("%s"), szVarName);
|
||
|
|
||
|
// Strip trailing whitespace from end of Env Variable
|
||
|
i = lstrlen(szTemp2) - 1;
|
||
|
while (i >= 0)
|
||
|
{
|
||
|
if (_istspace(szTemp2[i]))
|
||
|
szTemp2[i--] = TEXT('\0');
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Make sure variable name does not contain the "=" sign.
|
||
|
pszTemp = _tcspbrk (szTemp2, TEXT("="));
|
||
|
if (pszTemp)
|
||
|
*pszTemp = TEXT('\0');
|
||
|
|
||
|
if (szTemp2[0] == TEXT('\0'))
|
||
|
return;
|
||
|
|
||
|
bBuffer = (TCHAR *) MemAlloc (LPTR, BUFZ * sizeof(TCHAR));
|
||
|
if (bBuffer)
|
||
|
{
|
||
|
pszString = (LPTSTR) MemAlloc (LPTR, BUFZ * sizeof(TCHAR));
|
||
|
if (pszString)
|
||
|
{
|
||
|
wnsprintf(bBuffer, (BUFZ), TEXT("%s"), szVarValue);
|
||
|
|
||
|
// Determine which Listbox to use (SYSTEM or USER vars)
|
||
|
switch (VarType)
|
||
|
{
|
||
|
case SYSTEM_VAR:
|
||
|
idTemp = IDC_ENVVAR_SYS_LB_SYSVARS;
|
||
|
break;
|
||
|
|
||
|
case USER_VAR:
|
||
|
default:
|
||
|
idTemp = IDC_ENVVAR_SYS_LB_USERVARS;
|
||
|
break;
|
||
|
|
||
|
} // switch (VarType)
|
||
|
hwndTemp = GetDlgItem(hDlg, idTemp);
|
||
|
|
||
|
n = FindVar(hwndTemp, szTemp2);
|
||
|
if (n != -1)
|
||
|
{
|
||
|
// Free existing strings (listview and ours)
|
||
|
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 0;
|
||
|
|
||
|
if (SendMessage(hwndTemp, LVM_GETITEM, 0, (LPARAM) &item))
|
||
|
{
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
if (penvar)
|
||
|
{
|
||
|
MemFree(penvar->szValueName);
|
||
|
MemFree(penvar->szValue);
|
||
|
MemFree(penvar->szExpValue);
|
||
|
}
|
||
|
|
||
|
SendMessage(hwndTemp, LVM_DELETEITEM, n, 0L);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Get some storage for new Env Var
|
||
|
penvar = (ENVARS *) MemAlloc(LPTR, sizeof(ENVARS));
|
||
|
}
|
||
|
|
||
|
// If there are two '%' chars in string, then this is a
|
||
|
// REG_EXPAND_SZ style environment string
|
||
|
pszTemp = _tcspbrk (bBuffer, TEXT("%"));
|
||
|
if (penvar)
|
||
|
{
|
||
|
if (pszTemp && _tcspbrk (pszTemp, TEXT("%")))
|
||
|
penvar->dwType = REG_EXPAND_SZ;
|
||
|
else
|
||
|
penvar->dwType = REG_SZ;
|
||
|
}
|
||
|
|
||
|
switch (VarType)
|
||
|
{
|
||
|
case SYSTEM_VAR:
|
||
|
ExpandSystemVar(bBuffer, pszString, BUFZ);
|
||
|
break;
|
||
|
|
||
|
case USER_VAR:
|
||
|
ExpandEnvironmentStrings (bBuffer, pszString, BUFZ);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
|
||
|
} // switch
|
||
|
|
||
|
if (penvar)
|
||
|
{
|
||
|
penvar->szValueName = CloneString (szTemp2);
|
||
|
penvar->szValue = CloneString (bBuffer);
|
||
|
penvar->szExpValue = CloneString (pszString);
|
||
|
|
||
|
item.mask = LVIF_TEXT | LVIF_PARAM;
|
||
|
item.iItem = ListView_GetItemCount(hwndTemp);
|
||
|
item.iSubItem = 0;
|
||
|
item.pszText = penvar->szValueName;
|
||
|
item.lParam = (LPARAM) penvar;
|
||
|
|
||
|
n = (int)SendMessage (hwndTemp, LVM_INSERTITEM, 0, (LPARAM) &item);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
n = -1;
|
||
|
}
|
||
|
|
||
|
if (n != -1)
|
||
|
{
|
||
|
item.mask = LVIF_TEXT;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 1;
|
||
|
item.pszText = penvar->szExpValue;
|
||
|
|
||
|
SendMessage (hwndTemp, LVM_SETITEMTEXT, n, (LPARAM) &item);
|
||
|
|
||
|
item.mask = LVIF_STATE;
|
||
|
item.iItem = n;
|
||
|
item.iSubItem = 0;
|
||
|
item.state = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
item.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
|
||
|
|
||
|
SendDlgItemMessage (hDlg, idTemp, LVM_SETITEMSTATE, n, (LPARAM) &item);
|
||
|
}
|
||
|
|
||
|
MemFree(pszString);
|
||
|
}
|
||
|
|
||
|
MemFree(bBuffer);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
void
|
||
|
EVDoEdit(
|
||
|
IN HWND hWnd,
|
||
|
IN UINT VarType,
|
||
|
IN UINT EditType,
|
||
|
IN int iSelection
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Sets up for, executes, and cleans up after an Environment Variable
|
||
|
New... or Edit... dialog. Called when user presses a New... or Edit...
|
||
|
button.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hWnd -
|
||
|
Supplies window handle
|
||
|
|
||
|
VarType -
|
||
|
Supplies the type of the variable: User (USER_VAR) or
|
||
|
System (SYSTEM_VAR)
|
||
|
|
||
|
EditType -
|
||
|
Supplies the type of the edit: create New (NEW_VAR) or
|
||
|
Edit existing (EDIT_VAR)
|
||
|
|
||
|
iSelection -
|
||
|
Supplies the currently selected variable of type VarType. This
|
||
|
value is ignored if EditType is NEW_VAR.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None. May alter the contents of a list view control as a side effect.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LRESULT Result = 0;
|
||
|
BOOL fVarChanged = FALSE;
|
||
|
HWND hWndLB = NULL;
|
||
|
ENVARS *penvar = NULL;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
ASSERT((-1 != iSelection) || (NEW_VAR == EditType));
|
||
|
|
||
|
g_VarType = VarType;
|
||
|
g_EditType = EditType;
|
||
|
|
||
|
penvar = GetVar(hWnd, VarType, iSelection);
|
||
|
|
||
|
switch (EditType) {
|
||
|
case NEW_VAR:
|
||
|
ZeroMemory((LPVOID) g_szVarName, (DWORD) BUFZ * sizeof(TCHAR));
|
||
|
ZeroMemory((LPVOID) g_szVarValue, (DWORD) BUFZ * sizeof(TCHAR));
|
||
|
break;
|
||
|
|
||
|
case EDIT_VAR:
|
||
|
if (penvar) {
|
||
|
wsprintf(
|
||
|
g_szVarName,
|
||
|
TEXT("%s"),
|
||
|
penvar->szValueName
|
||
|
);
|
||
|
wsprintf(
|
||
|
g_szVarValue,
|
||
|
TEXT("%s"),
|
||
|
penvar->szValue
|
||
|
);
|
||
|
|
||
|
} // if
|
||
|
else {
|
||
|
MessageBeep(MB_ICONASTERISK);
|
||
|
return;
|
||
|
} // else
|
||
|
break;
|
||
|
|
||
|
case INVALID_EDIT_TYPE:
|
||
|
default:
|
||
|
return;
|
||
|
} // switch
|
||
|
|
||
|
Result = DialogBox(
|
||
|
hInstance,
|
||
|
(LPTSTR) MAKEINTRESOURCE(IDD_ENVVAREDIT),
|
||
|
hWnd,
|
||
|
EnvVarsEditDlg
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Only update the list view control if the user
|
||
|
// actually changed or created a variable
|
||
|
//
|
||
|
switch (Result) {
|
||
|
case EDIT_CHANGE:
|
||
|
if (EDIT_VAR == EditType) {
|
||
|
fVarChanged =
|
||
|
lstrcmp(penvar->szValueName, g_szVarName) ||
|
||
|
lstrcmp(penvar->szValue, g_szVarValue);
|
||
|
} // if (EDIT_VAR...
|
||
|
else if (NEW_VAR == EditType) {
|
||
|
fVarChanged =
|
||
|
lstrlen(g_szVarName) && lstrlen(g_szVarValue);
|
||
|
} // else if (NEW_VAR...
|
||
|
else {
|
||
|
fVarChanged = FALSE;
|
||
|
} // else
|
||
|
|
||
|
if (fVarChanged) {
|
||
|
if (EDIT_VAR == EditType) {
|
||
|
DeleteVar(hWnd, VarType, penvar->szValueName);
|
||
|
} // if (EDIT_VAR...
|
||
|
SetVar(hWnd, VarType, g_szVarName, g_szVarValue);
|
||
|
} // if (fVarChanged)
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
} // switch (Result)
|
||
|
|
||
|
g_VarType = INVALID_VAR_TYPE;
|
||
|
g_EditType = INVALID_EDIT_TYPE;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
PENVAR
|
||
|
GetVar(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT VarType,
|
||
|
IN int iSelection
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Returns a given System or User environment variable, as stored
|
||
|
in the System or User environment variable listview control.
|
||
|
|
||
|
Changing the structure returned by this routine is not
|
||
|
recommended, because it will alter the values actually stored
|
||
|
in the listview control.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
VarType -
|
||
|
Supplies variable type--System or User
|
||
|
|
||
|
iSelection -
|
||
|
Supplies the selection index into the listview control of
|
||
|
the desired environment variable
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Pointer to a valid ENVARS structure if successful.
|
||
|
|
||
|
NULL if unsuccessful.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
HWND hWndLB = NULL;
|
||
|
PENVAR penvar = NULL;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
switch (VarType)
|
||
|
{
|
||
|
case SYSTEM_VAR:
|
||
|
hWndLB = GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
|
||
|
break;
|
||
|
|
||
|
case USER_VAR:
|
||
|
hWndLB = GetDlgItem(hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
|
||
|
break;
|
||
|
|
||
|
case INVALID_VAR_TYPE:
|
||
|
default:
|
||
|
return NULL;
|
||
|
} // switch (VarType)
|
||
|
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iItem = iSelection;
|
||
|
item.iSubItem = 0;
|
||
|
if (iSelection >= 0 && SendMessage (hWndLB, LVM_GETITEM, 0, (LPARAM) &item))
|
||
|
{
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
return penvar;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
FindVar(
|
||
|
IN HWND hwndLV,
|
||
|
IN LPTSTR szVar
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Find the USER Environment variable that matches passed string
|
||
|
and return its listview index or -1
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hwndLV -
|
||
|
Supplies window handle to the list view control containing the
|
||
|
environment variables
|
||
|
|
||
|
szVar -
|
||
|
Supplies the variable name in string form
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
List view item index which matches the passed in string if the string
|
||
|
is the name of an environment variable
|
||
|
|
||
|
-1 if the passed in string is not the name of an environment variable
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LV_FINDINFO FindInfo;
|
||
|
|
||
|
|
||
|
FindInfo.flags = LVFI_STRING;
|
||
|
FindInfo.psz = szVar;
|
||
|
|
||
|
return (int)(SendMessage (hwndLV, LVM_FINDITEM, (WPARAM) -1, (LPARAM) &FindInfo));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Hydra's
|
||
|
// WinStationBroadcastSystemMessage(
|
||
|
//
|
||
|
typedef
|
||
|
LONG
|
||
|
(*PWINSTABSM_ROUTINE) (
|
||
|
HANDLE hServer,
|
||
|
BOOL sendToAllWinstations, // you set this to TRUE
|
||
|
ULONG sessionID, // set to NULL, due to above
|
||
|
ULONG timeOut,
|
||
|
DWORD dwFlags,
|
||
|
DWORD *lpdwRecipients,
|
||
|
ULONG uiMessage,
|
||
|
WPARAM wParam,
|
||
|
LPARAM lParam,
|
||
|
LONG *pResponse);
|
||
|
|
||
|
PWINSTABSM_ROUTINE fp_WinStaBroadcastSystemMessage;
|
||
|
|
||
|
// load winsta.dll (if any) and initialize the global function pointers to use
|
||
|
HANDLE
|
||
|
InitializeHydraInterface(
|
||
|
void
|
||
|
)
|
||
|
{
|
||
|
HANDLE hwinStaLib=NULL;
|
||
|
|
||
|
//
|
||
|
// Load the Terminal Server base library that contains the user message dispatch
|
||
|
// routines if termial server is running.
|
||
|
//
|
||
|
if (hwinStaLib = LoadLibrary(TEXT("WINSTA.DLL")))
|
||
|
{
|
||
|
fp_WinStaBroadcastSystemMessage = (PWINSTABSM_ROUTINE)GetProcAddress(
|
||
|
hwinStaLib,"WinStationBroadcastSystemMessage");
|
||
|
|
||
|
if (fp_WinStaBroadcastSystemMessage )
|
||
|
{
|
||
|
return (hwinStaLib);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// this must not be a NT5 running Terminal Services, which means
|
||
|
// it could be NT5 WKS, or some flavor of NT4.
|
||
|
// So, we just bail out, no problem.
|
||
|
FreeLibrary(hwinStaLib);
|
||
|
return (NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
EVSave(
|
||
|
IN HWND hDlg
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Saves the environment variables in the registry
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR szTemp[BUFZ];
|
||
|
int selection;
|
||
|
int i, n;
|
||
|
TCHAR *bBuffer;
|
||
|
TCHAR *pszTemp;
|
||
|
LPTSTR pszString;
|
||
|
HWND hwndTemp;
|
||
|
ENVARS *penvar;
|
||
|
REGVAL *prvFirst;
|
||
|
REGVAL *prvRegVal;
|
||
|
HKEY hkeyEnv;
|
||
|
DWORD dwBufz, dwIndex, dwType;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
HourGlass (TRUE);
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////
|
||
|
// Set all new USER environment variables to current values
|
||
|
// but delete all old environment variables first
|
||
|
/////////////////////////////////////////////////////////////////
|
||
|
|
||
|
if (RegOpenKeyEx (HKEY_CURRENT_USER, szUserEnv, 0,
|
||
|
KEY_READ | KEY_WRITE, &hkeyEnv)
|
||
|
== ERROR_SUCCESS)
|
||
|
{
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwIndex = 0;
|
||
|
|
||
|
// Delete all values of type REG_SZ & REG_EXPAND_SZ under key
|
||
|
|
||
|
// First: Make a linked list of all USER Env string vars
|
||
|
|
||
|
prvFirst = (REGVAL *) NULL;
|
||
|
|
||
|
while (!RegEnumValue(hkeyEnv,
|
||
|
dwIndex++, // Index'th value name/data
|
||
|
szTemp, // Ptr to ValueName buffer
|
||
|
&dwBufz, // Size of ValueName buffer
|
||
|
NULL, // Title index return
|
||
|
&dwType, // Type code of entry
|
||
|
NULL, // Ptr to ValueData buffer
|
||
|
NULL)) // Size of ValueData buffer
|
||
|
{
|
||
|
if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
|
||
|
goto EVSGetNextUserVar;
|
||
|
|
||
|
if (prvFirst)
|
||
|
{
|
||
|
prvRegVal->prvNext = (REGVAL *) MemAlloc (LPTR, sizeof(REGVAL));
|
||
|
prvRegVal = prvRegVal->prvNext;
|
||
|
}
|
||
|
else // First time thru
|
||
|
{
|
||
|
prvFirst = prvRegVal = (REGVAL *) MemAlloc (LPTR, sizeof(REGVAL));
|
||
|
}
|
||
|
|
||
|
prvRegVal->prvNext = NULL;
|
||
|
prvRegVal->szValueName = CloneString (szTemp);
|
||
|
|
||
|
// Reset vars for next call
|
||
|
EVSGetNextUserVar:
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
}
|
||
|
|
||
|
// Now traverse the list, deleting them all
|
||
|
|
||
|
prvRegVal = prvFirst;
|
||
|
|
||
|
while (prvRegVal)
|
||
|
{
|
||
|
RegDeleteValue (hkeyEnv, prvRegVal->szValueName);
|
||
|
|
||
|
MemFree (prvRegVal->szValueName);
|
||
|
|
||
|
prvFirst = prvRegVal;
|
||
|
prvRegVal = prvRegVal->prvNext;
|
||
|
|
||
|
MemFree ((LPVOID) prvFirst);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
// Set all new USER environment variables to current values
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
|
||
|
|
||
|
if ((n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L)) != LB_ERR)
|
||
|
{
|
||
|
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iSubItem = 0;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
{
|
||
|
|
||
|
item.iItem = i;
|
||
|
|
||
|
if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
|
||
|
} else {
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
if (penvar) {
|
||
|
if (RegSetValueEx (hkeyEnv,
|
||
|
penvar->szValueName,
|
||
|
0L,
|
||
|
penvar->dwType,
|
||
|
(LPBYTE) penvar->szValue,
|
||
|
(lstrlen (penvar->szValue)+1) * sizeof(TCHAR)))
|
||
|
{
|
||
|
// Report error trying to set registry values
|
||
|
|
||
|
if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NONEW_ENV_UNK : IDS_SYSDM_NONEW_ENV_NOTADMIN, IDS_SYSDM_TITLE,
|
||
|
MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegFlushKey (hkeyEnv);
|
||
|
RegCloseKey (hkeyEnv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Report opening USER Environment key
|
||
|
if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_USER_UNK : IDS_SYSDM_NOOPEN_USER_NOTADMIN, IDS_SYSDM_TITLE,
|
||
|
MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////
|
||
|
// Set all new SYSTEM environment variables to current values
|
||
|
// but delete all old environment variables first
|
||
|
/////////////////////////////////////////////////////////////////
|
||
|
|
||
|
if (!bEditSystemVars)
|
||
|
goto SkipSystemVars;
|
||
|
|
||
|
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
|
||
|
szSysEnv,
|
||
|
0,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hkeyEnv)
|
||
|
== ERROR_SUCCESS)
|
||
|
{
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
dwIndex = 0;
|
||
|
|
||
|
// Delete all values of type REG_SZ & REG_EXPAND_SZ under key
|
||
|
|
||
|
// First: Make a linked list of all Env string vars
|
||
|
|
||
|
prvFirst = (REGVAL *) NULL;
|
||
|
|
||
|
while (!RegEnumValue(hkeyEnv,
|
||
|
dwIndex++, // Index'th value name/data
|
||
|
szTemp, // Ptr to ValueName buffer
|
||
|
&dwBufz, // Size of ValueName buffer
|
||
|
NULL, // Title index return
|
||
|
&dwType, // Type code of entry
|
||
|
NULL, // Ptr to ValueData buffer
|
||
|
NULL)) // Size of ValueData buffer
|
||
|
{
|
||
|
if ((dwType != REG_SZ) && (dwType != REG_EXPAND_SZ))
|
||
|
goto EVSGetNextSysVar;
|
||
|
|
||
|
if (prvFirst)
|
||
|
{
|
||
|
prvRegVal->prvNext = (REGVAL *) MemAlloc (LPTR, sizeof(REGVAL));
|
||
|
prvRegVal = prvRegVal->prvNext;
|
||
|
}
|
||
|
else // First time thru
|
||
|
{
|
||
|
prvFirst = prvRegVal = (REGVAL *) MemAlloc (LPTR, sizeof(REGVAL));
|
||
|
}
|
||
|
|
||
|
prvRegVal->prvNext = NULL;
|
||
|
prvRegVal->szValueName = CloneString (szTemp);
|
||
|
|
||
|
// Reset vars for next call
|
||
|
EVSGetNextSysVar:
|
||
|
dwBufz = ARRAYSIZE(szTemp);
|
||
|
}
|
||
|
|
||
|
// Now traverse the list, deleting them all
|
||
|
|
||
|
prvRegVal = prvFirst;
|
||
|
|
||
|
while (prvRegVal)
|
||
|
{
|
||
|
RegDeleteValue (hkeyEnv, prvRegVal->szValueName);
|
||
|
|
||
|
MemFree (prvRegVal->szValueName);
|
||
|
|
||
|
prvFirst = prvRegVal;
|
||
|
prvRegVal = prvRegVal->prvNext;
|
||
|
|
||
|
MemFree ((LPVOID) prvFirst);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
// Set all new SYSTEM environment variables to current values
|
||
|
///////////////////////////////////////////////////////////////
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
|
||
|
|
||
|
if ((n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L)) != LB_ERR)
|
||
|
{
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iSubItem = 0;
|
||
|
|
||
|
for (i = 0; i < n; i++)
|
||
|
{
|
||
|
item.iItem = i;
|
||
|
|
||
|
if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
|
||
|
} else {
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
if (penvar) {
|
||
|
if (RegSetValueEx (hkeyEnv,
|
||
|
penvar->szValueName,
|
||
|
0L,
|
||
|
penvar->dwType,
|
||
|
(LPBYTE) penvar->szValue,
|
||
|
(lstrlen (penvar->szValue)+1) * sizeof(TCHAR)))
|
||
|
{
|
||
|
// Report error trying to set registry values
|
||
|
|
||
|
if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NONEW_ENV_UNK : IDS_SYSDM_NONEW_ENV_NOTADMIN, IDS_SYSDM_TITLE,
|
||
|
MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RegFlushKey (hkeyEnv);
|
||
|
RegCloseKey (hkeyEnv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Report opening SYSTEM Environment key
|
||
|
if (MsgBoxParam (hDlg, IsUserAnAdmin() ? IDS_SYSDM_NOOPEN_SYS_UNK : IDS_SYSDM_NOOPEN_SYS_NOTADMIN, IDS_SYSDM_TITLE,
|
||
|
MB_OKCANCEL | MB_ICONEXCLAMATION) == IDCANCEL)
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
SkipSystemVars:
|
||
|
|
||
|
|
||
|
// Send public message announcing change to Environment
|
||
|
SendMessageTimeout( (HWND)-1, WM_WININICHANGE, 0L, (LPARAM)szUserEnv,
|
||
|
SMTO_ABORTIFHUNG, 1000, NULL );
|
||
|
|
||
|
// the folllowing block will send a message to all terminal server session
|
||
|
// if and only if this is a NT5 and terminal services has been enabled.
|
||
|
if ( IsUserAdmin() )
|
||
|
{
|
||
|
HANDLE hwinStaLib;
|
||
|
// if this is an NT5, then we get a valid handle to winsta.dll library
|
||
|
// and the function pointer will be valid/initialized
|
||
|
hwinStaLib = InitializeHydraInterface();
|
||
|
if ( hwinStaLib)
|
||
|
{
|
||
|
// these are not used
|
||
|
DWORD dwRecipients=0;
|
||
|
LONG dwResponse=0;
|
||
|
|
||
|
// Broadcast the message to all hydra sessions (if any)
|
||
|
fp_WinStaBroadcastSystemMessage( SERVERNAME_CURRENT, TRUE, 0,
|
||
|
1 /*timeout in seconds*/ , BSF_NOHANG,
|
||
|
&dwRecipients,
|
||
|
WM_WININICHANGE, 0L,
|
||
|
(LPARAM)szUserEnv,
|
||
|
&dwResponse );
|
||
|
|
||
|
//Close the handle to Winsta
|
||
|
FreeLibrary (hwinStaLib);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
|
||
|
HourGlass (FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
EVCleanUp(
|
||
|
IN HWND hDlg
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Frees memory allocated for environment variables
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
hDlg -
|
||
|
Supplies window handle
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int i, n;
|
||
|
HWND hwndTemp;
|
||
|
ENVARS *penvar;
|
||
|
LV_ITEM item;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Free alloc'd strings and memory for UserEnvVars list box items
|
||
|
//
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_USERVARS);
|
||
|
n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
|
||
|
|
||
|
item.mask = LVIF_PARAM;
|
||
|
item.iSubItem = 0;
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
|
||
|
item.iItem = i;
|
||
|
|
||
|
if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
|
||
|
} else {
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
if (penvar) {
|
||
|
MemFree (penvar->szValueName);
|
||
|
MemFree (penvar->szValue);
|
||
|
MemFree (penvar->szExpValue);
|
||
|
MemFree ((LPVOID) penvar);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Free alloc'd strings and memory for SysEnvVars list box items
|
||
|
//
|
||
|
|
||
|
hwndTemp = GetDlgItem (hDlg, IDC_ENVVAR_SYS_LB_SYSVARS);
|
||
|
n = (int)SendMessage (hwndTemp, LVM_GETITEMCOUNT, 0, 0L);
|
||
|
|
||
|
for (i = 0; i < n; i++) {
|
||
|
|
||
|
item.iItem = i;
|
||
|
|
||
|
if (SendMessage (hwndTemp, LVM_GETITEM, 0, (LPARAM) &item)) {
|
||
|
penvar = (ENVARS *) item.lParam;
|
||
|
|
||
|
} else {
|
||
|
penvar = NULL;
|
||
|
}
|
||
|
|
||
|
if (penvar) {
|
||
|
MemFree (penvar->szValueName);
|
||
|
MemFree (penvar->szValue);
|
||
|
MemFree (penvar->szExpValue);
|
||
|
MemFree ((LPVOID) penvar);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
ExpandSystemVar(
|
||
|
IN LPCTSTR pszSrc,
|
||
|
OUT LPTSTR pszDst,
|
||
|
IN DWORD cchDst
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Private version of ExpandEnvironmentStrings() which only expands
|
||
|
references to the variables "SystemRoot" and "SystemDrive".
|
||
|
|
||
|
This behavior is intended to match the way SMSS expands system
|
||
|
environment variables.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pszSrc -
|
||
|
Supplies the system variable value to be expanded.
|
||
|
|
||
|
pszDst -
|
||
|
Returns the expanded system variable value.
|
||
|
|
||
|
cchDst -
|
||
|
Supplies the size, in characters, of the buffer pointed to
|
||
|
by pszDst
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if there was room in the supplied buffer for the entire
|
||
|
expanded string.
|
||
|
|
||
|
FALSE if there was insufficient space in the supplied buffer
|
||
|
for the entire expanded string.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
TCHAR ch;
|
||
|
LPTSTR p;
|
||
|
TCHAR szVar[BUFZ];
|
||
|
DWORD cch;
|
||
|
|
||
|
do {
|
||
|
|
||
|
ch = *pszSrc++;
|
||
|
|
||
|
if (ch != TEXT('%') ) {
|
||
|
|
||
|
// no space left, truncate string and return false
|
||
|
if (--cchDst == 0) {
|
||
|
*pszDst = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
*pszDst++ = ch;
|
||
|
|
||
|
} else {
|
||
|
/*
|
||
|
* Expand variable
|
||
|
*/
|
||
|
// look for the next '%'
|
||
|
p = szVar;
|
||
|
while( *pszSrc != TEXT('\0') && *pszSrc != TEXT('%') )
|
||
|
*p++ = *pszSrc++;
|
||
|
|
||
|
*p = TEXT('\0');
|
||
|
|
||
|
if (*pszSrc == TEXT('\0')) {
|
||
|
// end of string, first '%' must be literal
|
||
|
cch = lstrlen(szVar) + 1;
|
||
|
|
||
|
// no more space, return false
|
||
|
if (cch + 1 > cchDst) {
|
||
|
*pszDst++ = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
*pszDst++ = TEXT('%');
|
||
|
CopyMemory( pszDst, szVar, cch * sizeof(TCHAR));
|
||
|
return TRUE;
|
||
|
|
||
|
} else {
|
||
|
// we found the ending '%' sign, expand that string
|
||
|
|
||
|
//
|
||
|
// We're expanding a SYSTEM variable, so only expand
|
||
|
// references to SystemRoot and SystemDrive.
|
||
|
//
|
||
|
if ((!lstrcmpi(szVar, SYSTEMROOT)) || (!lstrcmpi(szVar, SYSTEMDRIVE))) {
|
||
|
cch = GetEnvironmentVariable(szVar, pszDst, cchDst);
|
||
|
} /* if */
|
||
|
else {
|
||
|
cch = 0;
|
||
|
} /* else */
|
||
|
|
||
|
if (cch == 0 || cch >= cchDst) {
|
||
|
//String didn't expand, copy it as a literal
|
||
|
cch = lstrlen(szVar);
|
||
|
|
||
|
// no space left, trunc string and return FALSE
|
||
|
if (cch + 2 + 1 > cchDst ) {
|
||
|
*pszDst = TEXT('\0');
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
*pszDst++ = TEXT('%');
|
||
|
|
||
|
CopyMemory(pszDst, szVar, cch * sizeof(TCHAR));
|
||
|
pszDst += cch;
|
||
|
|
||
|
*pszDst++ = TEXT('%');
|
||
|
|
||
|
// cchDst -= two %'s and the string
|
||
|
cchDst -= (2 + cch);
|
||
|
|
||
|
} else {
|
||
|
// string was expanded in place, bump pointer past its end
|
||
|
pszDst += cch;
|
||
|
cchDst -= cch;
|
||
|
}
|
||
|
|
||
|
// continue with next char after ending '%'
|
||
|
pszSrc++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} while( ch != TEXT('\0') );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|