mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1086 lines
26 KiB
1086 lines
26 KiB
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORP., 1993-1994
|
|
*
|
|
* TITLE: REGVALUE.C
|
|
*
|
|
* VERSION: 4.01
|
|
*
|
|
* AUTHOR: Tracy Sharpe
|
|
*
|
|
* DATE: 05 Mar 1994
|
|
*
|
|
* ValueListWnd ListView routines for the Registry Editor.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "pch.h"
|
|
#include "regedit.h"
|
|
#include "regvalue.h"
|
|
#include "regstred.h"
|
|
#include "regbined.h"
|
|
#include "regdwded.h"
|
|
#include "regresid.h"
|
|
|
|
#define MAX_VALUENAME_TEMPLATE_ID 100
|
|
|
|
// Maximum number of bytes that will be shown in the ListView. If the user
|
|
// wants to see more, then they can use the edit dialogs.
|
|
#define SIZE_DATATEXT 196
|
|
|
|
// Allow room in a SIZE_DATATEXT buffer for one null, two quotes, and possibly
|
|
// the ellipsis.
|
|
#define MAXIMUM_STRINGDATATEXT 190
|
|
#ifndef DBCS
|
|
const CHAR s_StringDataFormatSpec[] = "\"%.190s\"";
|
|
#endif
|
|
|
|
// Allow room for multiple three character pairs, one null, and possibly the
|
|
// ellipsis.
|
|
#define MAXIMUM_BINARYDATABYTES 64
|
|
const CHAR s_BinaryDataFormatSpec[] = "%02x ";
|
|
|
|
const CHAR s_Ellipsis[] = "...";
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListDelete(
|
|
HWND hWnd
|
|
);
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListRename(
|
|
HWND hWnd
|
|
);
|
|
|
|
VOID
|
|
PASCAL
|
|
ValueList_EditLabel(
|
|
HWND hValueListWnd,
|
|
int ListIndex
|
|
);
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnNewValue
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
* hWnd, handle of RegEdit window.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnNewValue(
|
|
HWND hWnd,
|
|
DWORD Type
|
|
)
|
|
{
|
|
|
|
UINT NewValueNameID;
|
|
CHAR ValueName[MAXVALUENAME_LENGTH];
|
|
DWORD Ignore;
|
|
DWORD cbValueData;
|
|
LV_ITEM LVItem;
|
|
int ListIndex;
|
|
UINT ErrorStringID;
|
|
|
|
if (g_RegEditData.hCurrentSelectionKey == NULL)
|
|
return;
|
|
|
|
//
|
|
// Loop through the registry trying to find a valid temporary name until
|
|
// the user renames the key.
|
|
//
|
|
|
|
NewValueNameID = 1;
|
|
|
|
while (NewValueNameID < MAX_VALUENAME_TEMPLATE_ID) {
|
|
|
|
wsprintf(ValueName, g_RegEditData.pNewValueTemplate, NewValueNameID);
|
|
|
|
if (RegQueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
|
|
NULL, &Ignore, NULL, &Ignore) != ERROR_SUCCESS) {
|
|
|
|
//
|
|
// For strings, we need to have at least one byte to represent the
|
|
// null. For binary data, it's okay to have zero-length data.
|
|
//
|
|
|
|
switch (Type) {
|
|
|
|
case REG_SZ:
|
|
g_ValueDataBuffer[0] = '\0';
|
|
cbValueData = 1;
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
((LPDWORD) g_ValueDataBuffer)[0] = 0;
|
|
cbValueData = sizeof(DWORD);
|
|
break;
|
|
|
|
case REG_BINARY:
|
|
cbValueData = 0;
|
|
break;
|
|
|
|
}
|
|
|
|
if (RegSetValueEx(g_RegEditData.hCurrentSelectionKey, ValueName, 0,
|
|
Type, g_ValueDataBuffer, cbValueData) == ERROR_SUCCESS)
|
|
break;
|
|
|
|
else {
|
|
|
|
ErrorStringID = IDS_NEWVALUECANNOTCREATE;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NewValueNameID++;
|
|
|
|
}
|
|
|
|
if (NewValueNameID == MAX_VALUENAME_TEMPLATE_ID) {
|
|
|
|
ErrorStringID = IDS_NEWVALUENOUNIQUE;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
LVItem.mask = LVIF_TEXT | LVIF_IMAGE;
|
|
LVItem.pszText = ValueName;
|
|
LVItem.iItem = ListView_GetItemCount(g_RegEditData.hValueListWnd);
|
|
LVItem.iSubItem = 0;
|
|
LVItem.iImage = IsRegStringType(Type) ? IMAGEINDEX(IDI_STRING) :
|
|
IMAGEINDEX(IDI_BINARY);
|
|
|
|
if ((ListIndex = ListView_InsertItem(g_RegEditData.hValueListWnd,
|
|
&LVItem)) != -1) {
|
|
|
|
ValueList_SetItemDataText(g_RegEditData.hValueListWnd, ListIndex,
|
|
g_ValueDataBuffer, cbValueData, Type);
|
|
|
|
ValueList_EditLabel(g_RegEditData.hValueListWnd, ListIndex);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
error_ShowDialog:
|
|
InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(ErrorStringID),
|
|
MAKEINTRESOURCE(IDS_NEWVALUEERRORTITLE), MB_ICONERROR | MB_OK);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListBeginLabelEdit
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
* hWnd, handle of RegEdit window.
|
|
* lpLVDispInfo,
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL
|
|
PASCAL
|
|
RegEdit_OnValueListBeginLabelEdit(
|
|
HWND hWnd,
|
|
LV_DISPINFO FAR* lpLVDispInfo
|
|
)
|
|
{
|
|
|
|
//
|
|
// B#7933: We don't want the user to hurt themselves by making it too easy
|
|
// to rename keys and values. Only allow renames via the menus.
|
|
//
|
|
|
|
//
|
|
// We don't get any information on the source of this editing action, so
|
|
// we must maintain a flag that tells us whether or not this is "good".
|
|
//
|
|
|
|
if (!g_RegEditData.fAllowLabelEdits)
|
|
return TRUE;
|
|
|
|
//
|
|
// All other labels are fair game. We need to disable our keyboard
|
|
// accelerators so that the edit control can "see" them.
|
|
//
|
|
|
|
g_fDisableAccelerators = TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListEndLabelEdit
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
BOOL
|
|
PASCAL
|
|
RegEdit_OnValueListEndLabelEdit(
|
|
HWND hWnd,
|
|
LV_DISPINFO FAR* lpLVDispInfo
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
DWORD cbValueData;
|
|
DWORD Ignore;
|
|
DWORD Type;
|
|
CHAR ValueName[MAXVALUENAME_LENGTH];
|
|
UINT ErrorStringID;
|
|
|
|
//
|
|
// We can reenable our keyboard accelerators now that the edit control no
|
|
// longer needs to "see" them.
|
|
//
|
|
|
|
g_fDisableAccelerators = FALSE;
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
//
|
|
// Check to see if the user cancelled the edit. If so, we don't care so
|
|
// just return.
|
|
//
|
|
|
|
if (lpLVDispInfo-> item.pszText == NULL)
|
|
return TRUE;
|
|
|
|
ListView_GetItemText(hValueListWnd, lpLVDispInfo-> item.iItem, 0,
|
|
ValueName, sizeof(ValueName));
|
|
|
|
if (RegQueryValueEx(g_RegEditData.hCurrentSelectionKey, lpLVDispInfo->
|
|
item.pszText, NULL, &Ignore, NULL, &Ignore) != ERROR_FILE_NOT_FOUND) {
|
|
|
|
ErrorStringID = IDS_RENAMEVALEXISTS;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
cbValueData = sizeof(g_ValueDataBuffer);
|
|
|
|
if (RegQueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName, NULL,
|
|
&Type, g_ValueDataBuffer, &cbValueData) != ERROR_SUCCESS) {
|
|
|
|
ErrorStringID = IDS_RENAMEVALOTHERERROR;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
if (RegSetValueEx(g_RegEditData.hCurrentSelectionKey, lpLVDispInfo->
|
|
item.pszText, 0, Type, g_ValueDataBuffer, cbValueData) !=
|
|
ERROR_SUCCESS) {
|
|
|
|
ErrorStringID = IDS_RENAMEVALOTHERERROR;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
if (RegDeleteValue(g_RegEditData.hCurrentSelectionKey, ValueName) !=
|
|
ERROR_SUCCESS) {
|
|
|
|
ErrorStringID = IDS_RENAMEVALOTHERERROR;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
error_ShowDialog:
|
|
InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(ErrorStringID),
|
|
MAKEINTRESOURCE(IDS_RENAMEVALERRORTITLE), MB_ICONERROR | MB_OK,
|
|
(LPSTR) ValueName);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListCommand
|
|
*
|
|
* DESCRIPTION:
|
|
* Handles the selection of a menu item by the user intended for the
|
|
* ValueList child window.
|
|
*
|
|
* PARAMETERS:
|
|
* hWnd, handle of RegEdit window.
|
|
* MenuCommand, identifier of menu command.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListCommand(
|
|
HWND hWnd,
|
|
int MenuCommand
|
|
)
|
|
{
|
|
|
|
//
|
|
// Check to see if this menu command should be handled by the main window's
|
|
// command handler.
|
|
//
|
|
|
|
if (MenuCommand >= ID_FIRSTMAINMENUITEM && MenuCommand <=
|
|
ID_LASTMAINMENUITEM)
|
|
RegEdit_OnCommand(hWnd, MenuCommand, NULL, 0);
|
|
|
|
else {
|
|
|
|
switch (MenuCommand) {
|
|
|
|
case ID_CONTEXTMENU:
|
|
RegEdit_OnValueListContextMenu(hWnd, TRUE);
|
|
break;
|
|
|
|
case ID_MODIFY:
|
|
RegEdit_OnValueListModify(hWnd);
|
|
break;
|
|
|
|
case ID_DELETE:
|
|
RegEdit_OnValueListDelete(hWnd);
|
|
break;
|
|
|
|
case ID_RENAME:
|
|
RegEdit_OnValueListRename(hWnd);
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListContextMenu
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListContextMenu(
|
|
HWND hWnd,
|
|
BOOL fByAccelerator
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
DWORD MessagePos;
|
|
POINT MessagePoint;
|
|
LV_HITTESTINFO LVHitTestInfo;
|
|
int ListIndex;
|
|
UINT MenuID;
|
|
HMENU hContextMenu;
|
|
HMENU hContextPopupMenu;
|
|
int MenuCommand;
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
//
|
|
// If fByAcclerator is TRUE, then the user hit Shift-F10 to bring up the
|
|
// context menu. Following the Cabinet's convention, this menu is
|
|
// placed at (0,0) of the ListView client area.
|
|
//
|
|
|
|
if (fByAccelerator) {
|
|
|
|
MessagePoint.x = 0;
|
|
MessagePoint.y = 0;
|
|
|
|
ClientToScreen(hValueListWnd, &MessagePoint);
|
|
|
|
ListIndex = ListView_GetNextItem(hValueListWnd, -1, LVNI_SELECTED);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
MessagePos = GetMessagePos();
|
|
MessagePoint.x = LOWORD(MessagePos);
|
|
MessagePoint.y = HIWORD(MessagePos);
|
|
|
|
LVHitTestInfo.pt = MessagePoint;
|
|
ScreenToClient(hValueListWnd, &LVHitTestInfo.pt);
|
|
ListIndex = ListView_HitTest(hValueListWnd, &LVHitTestInfo);
|
|
|
|
}
|
|
|
|
MenuID = (ListIndex != -1) ? IDM_VALUE_CONTEXT :
|
|
IDM_VALUELIST_NOITEM_CONTEXT;
|
|
|
|
if ((hContextMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(MenuID))) == NULL)
|
|
return;
|
|
|
|
hContextPopupMenu = GetSubMenu(hContextMenu, 0);
|
|
|
|
if (ListIndex != -1) {
|
|
|
|
RegEdit_SetValueListEditMenuItems(hContextMenu, ListIndex);
|
|
|
|
SetMenuDefaultItem(hContextPopupMenu, ID_MODIFY, MF_BYCOMMAND);
|
|
|
|
}
|
|
|
|
// BUGBUG: Fix constant
|
|
else
|
|
RegEdit_SetNewObjectEditMenuItems(GetSubMenu(hContextPopupMenu, 0));
|
|
|
|
MenuCommand = TrackPopupMenuEx(hContextPopupMenu, TPM_RETURNCMD |
|
|
TPM_RIGHTBUTTON | TPM_LEFTALIGN | TPM_TOPALIGN, MessagePoint.x,
|
|
MessagePoint.y, hWnd, NULL);
|
|
|
|
DestroyMenu(hContextMenu);
|
|
|
|
RegEdit_OnValueListCommand(hWnd, MenuCommand);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_SetValueListEditMenuItems
|
|
*
|
|
* DESCRIPTION:
|
|
* Shared routine between the main menu and the context menu to setup the
|
|
* edit menu items.
|
|
*
|
|
* PARAMETERS:
|
|
* hPopupMenu, handle of popup menu to modify.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_SetValueListEditMenuItems(
|
|
HMENU hPopupMenu,
|
|
int SelectedListIndex
|
|
)
|
|
{
|
|
|
|
UINT SelectedCount;
|
|
UINT EnableFlags;
|
|
|
|
SelectedCount = ListView_GetSelectedCount(g_RegEditData.hValueListWnd);
|
|
|
|
//
|
|
// The edit option is only enabled when a single item is selected. Note
|
|
// that this item is not in the main menu, but this should work fine.
|
|
//
|
|
|
|
if (SelectedCount == 1)
|
|
EnableFlags = MF_ENABLED | MF_BYCOMMAND;
|
|
else
|
|
EnableFlags = MF_GRAYED | MF_BYCOMMAND;
|
|
|
|
EnableMenuItem(hPopupMenu, ID_MODIFY, EnableFlags);
|
|
|
|
//
|
|
// The rename option is also only enabled when a single item is selected
|
|
// and that item cannot be the default item. EnableFlags is already
|
|
// disabled if the SelectedCount is not one from above.
|
|
//
|
|
|
|
if (SelectedListIndex == 0)
|
|
EnableFlags = MF_GRAYED | MF_BYCOMMAND;
|
|
|
|
EnableMenuItem(hPopupMenu, ID_RENAME, EnableFlags);
|
|
|
|
//
|
|
// The delete option is only enabled when multiple items are selected.
|
|
//
|
|
|
|
if (SelectedCount > 0)
|
|
EnableFlags = MF_ENABLED | MF_BYCOMMAND;
|
|
else
|
|
EnableFlags = MF_GRAYED | MF_BYCOMMAND;
|
|
|
|
EnableMenuItem(hPopupMenu, ID_DELETE, EnableFlags);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListModify
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListModify(
|
|
HWND hWnd
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
UINT SelectedCount;
|
|
int ListIndex;
|
|
CHAR ValueName[MAXVALUENAME_LENGTH];
|
|
EDITVALUEPARAM EditValueParam;
|
|
DWORD Type;
|
|
LONG RegError;
|
|
UINT TemplateID;
|
|
DLGPROC lpDlgProc;
|
|
UINT ErrorStringID;
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
//
|
|
// Verify that we only have one item selected for editing and "notify" the
|
|
// user if this is not the case. Don't beep if the user is just double-
|
|
// clicking on the background.
|
|
//
|
|
|
|
SelectedCount = ListView_GetSelectedCount(hValueListWnd);
|
|
|
|
if (SelectedCount != 1) {
|
|
|
|
if (SelectedCount > 0)
|
|
MessageBeep(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// Determine which item we are to edit.
|
|
//
|
|
|
|
ListIndex = ListView_GetNextItem(hValueListWnd, -1, LVNI_SELECTED);
|
|
|
|
ListView_GetItemText(hValueListWnd, ListIndex, 0, ValueName,
|
|
sizeof(ValueName));
|
|
|
|
//
|
|
// If this is the default value, zap the first byte to null so that we
|
|
// can do a RegQueryValueEx. Note that below we replace this "zapped"
|
|
// byte.
|
|
//
|
|
|
|
if (ListIndex == 0)
|
|
ValueName[0] = '\0';
|
|
|
|
EditValueParam.pValueName = ValueName;
|
|
EditValueParam.pValueData = g_ValueDataBuffer;
|
|
EditValueParam.cbValueData = sizeof(g_ValueDataBuffer);
|
|
|
|
RegError = RegQueryValueEx(g_RegEditData.hCurrentSelectionKey, ValueName,
|
|
NULL, &Type, g_ValueDataBuffer, &EditValueParam.cbValueData);
|
|
|
|
if (RegError != ERROR_SUCCESS) {
|
|
|
|
//
|
|
// If this is the default value, then the value may not really exist
|
|
// in the registry, so ignore ERROR_FILE_NOT_FOUND. We always display
|
|
// the default value in the ListView regardless of its existence.
|
|
//
|
|
|
|
if (ListIndex != 0 || RegError != ERROR_FILE_NOT_FOUND) {
|
|
|
|
ErrorStringID = IDS_EDITVALCANNOTREAD;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
//
|
|
// If the default value didn't exist, then Type isn't necessarily
|
|
// valid. Here, we make sure it's a string which by definition must be
|
|
// true.
|
|
//
|
|
|
|
if (ListIndex == 0)
|
|
Type = REG_SZ;
|
|
|
|
}
|
|
|
|
//
|
|
// This is kinda funky-- if this is the default value, then we zapped the
|
|
// first byte of "(Default Value") up above to do the RegQueryValueEx.
|
|
// Here we replace the byte just to avoid a string copy...
|
|
//
|
|
|
|
if (ListIndex == 0)
|
|
ValueName[0] = g_RegEditData.pDefaultValue[0];
|
|
|
|
switch (Type) {
|
|
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ:
|
|
TemplateID = IDD_EDITSTRINGVALUE;
|
|
lpDlgProc = EditStringValueDlgProc;
|
|
break;
|
|
|
|
case REG_DWORD:
|
|
if (EditValueParam.cbValueData == sizeof(DWORD)) {
|
|
|
|
TemplateID = IDD_EDITDWORDVALUE;
|
|
lpDlgProc = EditDwordValueDlgProc;
|
|
break;
|
|
|
|
}
|
|
// FALL THROUGH
|
|
|
|
case REG_BINARY:
|
|
default:
|
|
TemplateID = IDD_EDITBINARYVALUE;
|
|
lpDlgProc = EditBinaryValueDlgProc;
|
|
break;
|
|
|
|
}
|
|
|
|
if (DialogBoxParam(g_hInstance, MAKEINTRESOURCE(TemplateID), hWnd,
|
|
lpDlgProc, (LPARAM) (LPEDITVALUEPARAM) &EditValueParam) == IDOK) {
|
|
|
|
if (ListIndex == 0)
|
|
ValueName[0] = '\0';
|
|
|
|
if (RegSetValueEx(g_RegEditData.hCurrentSelectionKey, ValueName, 0,
|
|
Type, EditValueParam.pValueData, EditValueParam.cbValueData) !=
|
|
ERROR_SUCCESS) {
|
|
|
|
ErrorStringID = IDS_EDITVALCANNOTWRITE;
|
|
goto error_ShowDialog;
|
|
|
|
}
|
|
|
|
ValueList_SetItemDataText(hValueListWnd, ListIndex,
|
|
EditValueParam.pValueData, EditValueParam.cbValueData, Type);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
error_ShowDialog:
|
|
InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(ErrorStringID),
|
|
MAKEINTRESOURCE(IDS_EDITVALERRORTITLE), MB_ICONERROR | MB_OK,
|
|
(LPSTR) ValueName);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListDelete
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListDelete(
|
|
HWND hWnd
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
UINT ConfirmTextStringID;
|
|
BOOL fErrorDeleting;
|
|
int ListStartIndex;
|
|
int ListIndex;
|
|
CHAR ValueName[MAXVALUENAME_LENGTH];
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
ConfirmTextStringID = (ListView_GetSelectedCount(hValueListWnd) == 1) ?
|
|
IDS_CONFIRMDELVALTEXT : IDS_CONFIRMDELVALMULTITEXT;
|
|
|
|
if (InternalMessageBox(g_hInstance, hWnd, MAKEINTRESOURCE(ConfirmTextStringID),
|
|
MAKEINTRESOURCE(IDS_CONFIRMDELVALTITLE), MB_ICONWARNING | MB_YESNO) !=
|
|
IDYES)
|
|
return;
|
|
|
|
SetWindowRedraw(hValueListWnd, FALSE);
|
|
|
|
fErrorDeleting = FALSE;
|
|
ListStartIndex = -1;
|
|
|
|
while ((ListIndex = ListView_GetNextItem(hValueListWnd, ListStartIndex,
|
|
LVNI_SELECTED)) != -1) {
|
|
|
|
if (ListIndex != 0) {
|
|
|
|
ListView_GetItemText(hValueListWnd, ListIndex, 0, ValueName,
|
|
sizeof(ValueName));
|
|
|
|
}
|
|
|
|
else
|
|
ValueName[0] = '\0';
|
|
|
|
if (RegDeleteValue(g_RegEditData.hCurrentSelectionKey, ValueName) ==
|
|
ERROR_SUCCESS) {
|
|
|
|
if (ListIndex != 0)
|
|
ListView_DeleteItem(hValueListWnd, ListIndex);
|
|
|
|
else {
|
|
|
|
ValueList_SetItemDataText(hValueListWnd, 0, NULL, 0, REG_SZ);
|
|
|
|
ListStartIndex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fErrorDeleting = TRUE;
|
|
|
|
ListStartIndex = ListIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetWindowRedraw(hValueListWnd, TRUE);
|
|
|
|
if (fErrorDeleting)
|
|
InternalMessageBox(g_hInstance, hWnd,
|
|
MAKEINTRESOURCE(IDS_DELETEVALDELETEFAILED),
|
|
MAKEINTRESOURCE(IDS_DELETEVALERRORTITLE), MB_ICONERROR | MB_OK);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListRename
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListRename(
|
|
HWND hWnd
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
int ListIndex;
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
if (ListView_GetSelectedCount(hValueListWnd) == 1 && (ListIndex =
|
|
ListView_GetNextItem(hValueListWnd, -1, LVNI_SELECTED)) != 0)
|
|
ValueList_EditLabel(g_RegEditData.hValueListWnd, ListIndex);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegEdit_OnValueListRefresh
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
RegEdit_OnValueListRefresh(
|
|
HWND hWnd
|
|
)
|
|
{
|
|
|
|
HWND hValueListWnd;
|
|
LV_ITEM LVItem;
|
|
DWORD cbValueName;
|
|
DWORD cbValueData;
|
|
CHAR ValueName[MAXVALUENAME_LENGTH];
|
|
DWORD Type;
|
|
LONG PrevStyle;
|
|
DWORD EnumIndex;
|
|
BOOL fInsertedDefaultValue;
|
|
int ListIndex;
|
|
|
|
hValueListWnd = g_RegEditData.hValueListWnd;
|
|
|
|
RegEdit_SetWaitCursor(TRUE);
|
|
SetWindowRedraw(hValueListWnd, FALSE);
|
|
|
|
ListView_DeleteAllItems(hValueListWnd);
|
|
|
|
if (g_RegEditData.hCurrentSelectionKey != NULL) {
|
|
|
|
LVItem.mask = LVIF_TEXT | LVIF_IMAGE;
|
|
LVItem.pszText = ValueName;
|
|
LVItem.iSubItem = 0;
|
|
|
|
PrevStyle = SetWindowLong(hValueListWnd, GWL_STYLE,
|
|
GetWindowLong(hValueListWnd, GWL_STYLE) | LVS_SORTASCENDING);
|
|
|
|
EnumIndex = 0;
|
|
fInsertedDefaultValue = FALSE;
|
|
|
|
while (TRUE) {
|
|
|
|
cbValueName = sizeof(ValueName);
|
|
cbValueData = sizeof(g_ValueDataBuffer);
|
|
|
|
if (RegEnumValue(g_RegEditData.hCurrentSelectionKey, EnumIndex++,
|
|
ValueName, &cbValueName, NULL, &Type, g_ValueDataBuffer,
|
|
&cbValueData) != ERROR_SUCCESS)
|
|
break;
|
|
|
|
if (cbValueName == 0)
|
|
fInsertedDefaultValue = TRUE;
|
|
|
|
LVItem.iImage = IsRegStringType(Type) ? IMAGEINDEX(IDI_STRING) :
|
|
IMAGEINDEX(IDI_BINARY);
|
|
|
|
ListIndex = ListView_InsertItem(hValueListWnd, &LVItem);
|
|
|
|
ValueList_SetItemDataText(hValueListWnd, ListIndex,
|
|
g_ValueDataBuffer, cbValueData, Type);
|
|
|
|
}
|
|
|
|
SetWindowLong(hValueListWnd, GWL_STYLE, PrevStyle);
|
|
|
|
LVItem.iItem = 0;
|
|
LVItem.pszText = g_RegEditData.pDefaultValue;
|
|
LVItem.iImage = IMAGEINDEX(IDI_STRING);
|
|
|
|
if (fInsertedDefaultValue) {
|
|
|
|
LVItem.mask = LVIF_TEXT;
|
|
ListView_SetItem(hValueListWnd, &LVItem);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ListView_InsertItem(hValueListWnd, &LVItem);
|
|
ValueList_SetItemDataText(hValueListWnd, 0, NULL, 0, REG_SZ);
|
|
|
|
}
|
|
|
|
ListView_SetItemState(hValueListWnd, 0, LVIS_FOCUSED, LVIS_FOCUSED);
|
|
|
|
}
|
|
|
|
SetWindowRedraw(hValueListWnd, TRUE);
|
|
RegEdit_SetWaitCursor(FALSE);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ValueList_SetItemDataText
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
* hValueListWnd, handle of ValueList window.
|
|
* ListIndex, index into ValueList window.
|
|
* pValueData, pointer to buffer containing data.
|
|
* cbValueData, size of the above buffer.
|
|
* Type, type of data this buffer contains (REG_* definition).
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
ValueList_SetItemDataText(
|
|
HWND hValueListWnd,
|
|
int ListIndex,
|
|
PBYTE pValueData,
|
|
DWORD cbValueData,
|
|
DWORD Type
|
|
)
|
|
{
|
|
|
|
BOOL fMustDeleteString;
|
|
CHAR DataText[SIZE_DATATEXT];
|
|
int BytesToWrite;
|
|
PSTR pString;
|
|
|
|
fMustDeleteString = FALSE;
|
|
|
|
//
|
|
// When pValueData is NULL, then that's a special indicator to us that this
|
|
// is the default value and it's value is undefined.
|
|
//
|
|
|
|
if (pValueData == NULL)
|
|
pString = g_RegEditData.pValueNotSet;
|
|
|
|
else if (IsRegStringType(Type)) {
|
|
|
|
#ifdef DBCS
|
|
//
|
|
// The wsprintf function could potentially break up a double-byte
|
|
// character and that's not a very good thing to do! So, we manually
|
|
// copy over the string and check for DBCS characters.
|
|
//
|
|
|
|
pString = DataText;
|
|
*pString++ = '"';
|
|
|
|
BytesToWrite = min(lstrlen(pValueData), min(cbValueData, MAXIMUM_STRINGDATATEXT));
|
|
|
|
// cbValueData does not exactry mean the length of string here.
|
|
//
|
|
while (BytesToWrite > 0) {
|
|
|
|
if (IsDBCSLeadByte(*pString++ = *pValueData++)) {
|
|
|
|
*pString++ = *pValueData++;
|
|
BytesToWrite--;
|
|
|
|
}
|
|
|
|
BytesToWrite--;
|
|
|
|
}
|
|
|
|
//
|
|
// Here's the magic we need for DBCS. If we overran our allowed buffer
|
|
// space, then back up to before both the lead and trail DBCS bytes.
|
|
//
|
|
|
|
if (BytesToWrite < 0)
|
|
pString -= 2;
|
|
|
|
*pString++ = '"';
|
|
|
|
if (cbValueData > MAXIMUM_STRINGDATATEXT + 1) // for null
|
|
lstrcpy(pString, s_Ellipsis);
|
|
else
|
|
*pString = '\0';
|
|
#else
|
|
//
|
|
// Ahhh... uniform width character sets are great!
|
|
//
|
|
|
|
wsprintf(DataText, s_StringDataFormatSpec, (LPSTR) pValueData);
|
|
|
|
if (cbValueData > MAXIMUM_STRINGDATATEXT + 1) // for null
|
|
lstrcat(DataText, s_Ellipsis);
|
|
#endif
|
|
|
|
pString = DataText;
|
|
|
|
}
|
|
|
|
else if (Type == REG_DWORD) {
|
|
|
|
// BUGBUG: Check for invalid cbValueData!
|
|
if (cbValueData == sizeof(DWORD))
|
|
pString = LoadDynamicString(IDS_DWORDDATAFORMATSPEC,
|
|
((LPDWORD) g_ValueDataBuffer)[0]);
|
|
else
|
|
pString = LoadDynamicString(IDS_INVALIDDWORDDATA);
|
|
|
|
fMustDeleteString = TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (cbValueData == 0)
|
|
pString = g_RegEditData.pEmptyBinary;
|
|
|
|
else {
|
|
|
|
BytesToWrite = min(cbValueData, MAXIMUM_BINARYDATABYTES);
|
|
|
|
pString = DataText;
|
|
|
|
while (BytesToWrite--)
|
|
pString += wsprintf(pString, s_BinaryDataFormatSpec,
|
|
(BYTE) *pValueData++);
|
|
|
|
*(--pString) = '\0';
|
|
|
|
if (cbValueData > MAXIMUM_BINARYDATABYTES)
|
|
lstrcpy(pString, s_Ellipsis);
|
|
|
|
pString = DataText;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ListView_SetItemText(hValueListWnd, ListIndex, 1, pString);
|
|
|
|
if (fMustDeleteString)
|
|
DeleteDynamicString(pString);
|
|
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* ValueList_EditLabel
|
|
*
|
|
* DESCRIPTION:
|
|
*
|
|
* PARAMETERS:
|
|
* hValueListWnd, handle of ValueList window.
|
|
* ListIndex, index of item to edit.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
VOID
|
|
PASCAL
|
|
ValueList_EditLabel(
|
|
HWND hValueListWnd,
|
|
int ListIndex
|
|
)
|
|
{
|
|
|
|
g_RegEditData.fAllowLabelEdits = TRUE;
|
|
|
|
//
|
|
// We have to set the focus to the ListView or else ListView_EditLabel will
|
|
// return FALSE. While we're at it, clear the selected state of all the
|
|
// items to eliminate some flicker when we move the focus back to this
|
|
// pane.
|
|
//
|
|
|
|
if (hValueListWnd != g_RegEditData.hFocusWnd) {
|
|
|
|
ListView_SetItemState(hValueListWnd, -1, 0, LVIS_SELECTED |
|
|
LVIS_FOCUSED);
|
|
|
|
SetFocus(hValueListWnd);
|
|
|
|
}
|
|
|
|
ListView_EditLabel(hValueListWnd, ListIndex);
|
|
|
|
g_RegEditData.fAllowLabelEdits = FALSE;
|
|
|
|
}
|