windows-nt/Source/XPSP1/NT/base/fs/utils/reg/add.c
2020-09-26 16:20:57 +08:00

446 lines
13 KiB
C

//-----------------------------------------------------------------------//
//
// File: add.cpp
// Created: March 1997
// By: Martin Holladay (a-martih)
// Purpose: Registry Add (Write) Support for REG.CPP
// Modification History:
// March 1997 (a-martih):
// Copied from Query.cpp and modificd.
// October 1997 (martinho)
// Added additional termination character for MULTI_SZ strings.
// Added \0 delimiter between MULTI_SZ strings items
// April 1999 Zeyong Xu: re-design, revision -> version 2.0
//------------------------------------------------------------------------//
#include "stdafx.h"
#include "reg.h"
//-----------------------------------------------------------------------//
//
// AddRegistry()
//
//-----------------------------------------------------------------------//
LONG AddRegistry(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
LONG nResult;
HKEY hKey;
DWORD dwDisposition;
BYTE* byteData;
//
// Parse the cmd-line
//
nResult = ParseAddCmdLine(pAppVars, argc, argv);
if(nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Connect to the Remote Machine - if applicable
//
nResult = RegConnectMachine(pAppVars);
if (nResult != ERROR_SUCCESS)
{
return nResult;
}
//
// Create/Open the registry key
//
nResult = RegCreateKeyEx(pAppVars->hRootKey,
pAppVars->szSubKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE,
NULL,
&hKey,
&dwDisposition);
if( nResult == ERROR_SUCCESS &&
pAppVars->szValueName )
{
// check value if existed
DWORD dwType;
DWORD dwLen = 1;
nResult = RegQueryValueEx(hKey,
pAppVars->szValueName,
NULL,
&dwType,
NULL,
&dwLen);
if(nResult == ERROR_SUCCESS)
{
// if exist
if(!Prompt(_T("Value %s exists, overwrite(Y/N)? "),
pAppVars->szValueName,
pAppVars->bForce) )
{
RegCloseKey(hKey);
return nResult;
}
}
nResult = ERROR_SUCCESS;
switch(pAppVars->dwRegDataType)
{
case REG_DWORD:
case REG_DWORD_BIG_ENDIAN:
// case REG_DWORD_LITTLE_ENDIAN:
//
// auto convert szValue (hex, octal, decimal format) to dwData
//
{
TCHAR* szStop = NULL;
DWORD dwData = _tcstoul(pAppVars->szValue, &szStop, 0);
if(_tcslen(szStop) > 0) // invalid data format
nResult = REG_STATUS_INVALIDPARAMS;
else
nResult = RegSetValueEx(hKey,
pAppVars->szValueName,
0,
pAppVars->dwRegDataType,
(BYTE*) &dwData,
sizeof(DWORD));
}
break;
case REG_BINARY:
{
TCHAR buff[3];
LONG onebyte;
LONG count = 0;
TCHAR* szStart;
TCHAR* szStop;
//
// Convert szValue (hex data string) to binary
//
dwLen = _tcslen(pAppVars->szValue);
byteData = (BYTE*) calloc(dwLen/2 + dwLen%2,
sizeof(BYTE));
if (!byteData) {
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
buff[2] = _T('\0');
count = 0;
szStart = pAppVars->szValue;
while(_tcslen(szStart) > 0)
{
buff[0] = *szStart;
szStart++;
if(_tcslen(szStart) > 0)
{
buff[1] = *szStart;
szStart++;
}
else
{
buff[1] = _T('0'); // if half byte, append a '0'
}
// hex format
onebyte = _tcstol(buff, &szStop, 16);
if(_tcslen(szStop) > 0) // invalid data format
{
nResult = REG_STATUS_INVALIDPARAMS;
break;
}
else
{
byteData[count] = (BYTE)(onebyte);
}
count++;
}
if(nResult == ERROR_SUCCESS)
{
nResult = RegSetValueEx(hKey,
pAppVars->szValueName,
0,
pAppVars->dwRegDataType,
byteData,
count);
}
if(byteData)
free(byteData);
}
break;
case REG_SZ:
case REG_EXPAND_SZ:
case REG_NONE:
dwLen = (_tcslen(pAppVars->szValue) + 1) * sizeof(TCHAR);
nResult = RegSetValueEx(hKey,
pAppVars->szValueName,
0,
pAppVars->dwRegDataType,
(BYTE*) pAppVars->szValue,
dwLen);
break;
case REG_MULTI_SZ:
{
BOOL bErrorString = FALSE;
DWORD dwLengthOfSeparator = _tcslen(pAppVars->szSeparator);
BOOL bTrailing = FALSE;
TCHAR* szData;
TCHAR* pStart;
TCHAR* pEnd;
TCHAR* pString;
//
// Replace separator("\0") with '\0' for MULTI_SZ,
// "\0" uses to separate string by default,
// if two separators("\0\0"), error
//
dwLen = _tcslen(pAppVars->szValue);
// calloc() initializes all char to 0
szData = (TCHAR*) calloc(dwLen + 2, sizeof(TCHAR));
pStart = pAppVars->szValue;
pString = szData;
if (!szData) {
nResult = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
while(_tcslen(pStart) > 0)
{
pEnd = _tcsstr(pStart, pAppVars->szSeparator);
if(pEnd)
{
/*
**** MODIFIED BY V-SMGUM ****
//two separators("\0\0") inside string
if( pEnd == pStart ||
//one separator("\0") in end of string
_tcslen(pEnd) == dwLengthOfSeparator)
{
bErrorString = TRUE;
break;
}
*pEnd = 0;
*/
//
// MODIFIED BY V-SMGUM
// THIS IS TO REMOVE THE TRAILING SEPERATOR EVEN IF IT IS SPECIFIED
//
// specifying two seperators in the data is error
bTrailing = FALSE;
if ( pEnd == pStart )
{
bErrorString = TRUE;
break;
}
else if ( _tcslen( pEnd ) == dwLengthOfSeparator )
{
// set the flag
bTrailing = TRUE;
}
*pEnd = 0;
}
// do the concat only if start is having valid buffer
_tcscat(pString, pStart);
pString += _tcslen(pString) + 1;
if( pEnd && bTrailing == FALSE )
pStart = pEnd + dwLengthOfSeparator;
else
break;
}
// empty
if(_tcsicmp(pAppVars->szValue, pAppVars->szSeparator) == 0)
{
pString = szData + 2;
bErrorString = FALSE;
}
else
pString += 1; // double null terminated string
if(bErrorString)
{
nResult = REG_STATUS_INVALIDPARAMS;
}
else
{
DWORD dwByteToWrite = (DWORD)((pString - szData) * sizeof(TCHAR));
nResult = RegSetValueEx(hKey,
pAppVars->szValueName,
0,
pAppVars->dwRegDataType,
(BYTE*) szData,
dwByteToWrite);
}
if(szData)
free(szData);
}
break;
default:
nResult = REG_STATUS_INVALIDPARAMS;
break;
}
RegCloseKey(hKey);
}
Cleanup:
return nResult;
}
//------------------------------------------------------------------------//
//
// ParseAddCmdLine()
//
//------------------------------------------------------------------------//
REG_STATUS ParseAddCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
{
REG_STATUS nResult = ERROR_SUCCESS;
UINT i;
BOOL bHasType = FALSE;
if(argc < 3)
{
return REG_STATUS_TOFEWPARAMS;
}
// Machine Name and Registry key
//
nResult = BreakDownKeyString(argv[2], pAppVars);
if(nResult != ERROR_SUCCESS)
return nResult;
// parsing
for(i=3; i<argc; i++)
{
if(!_tcsicmp(argv[i], _T("/v")))
{
if(pAppVars->szValueName)
return REG_STATUS_INVALIDPARAMS;
i++;
if(i<argc)
{
pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
sizeof(TCHAR));
if (!pAppVars->szValueName) {
return ERROR_NOT_ENOUGH_MEMORY;
}
_tcscpy(pAppVars->szValueName, argv[i]);
}
else
return REG_STATUS_TOFEWPARAMS;
}
else if(!_tcsicmp(argv[i], _T("/ve")))
{
if(pAppVars->szValueName)
return REG_STATUS_INVALIDPARAMS;
pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR));
if (!pAppVars->szValueName) {
return ERROR_NOT_ENOUGH_MEMORY;
}
}
else if(!_tcsicmp(argv[i], _T("/t")))
{
i++;
if(i<argc)
{
pAppVars->dwRegDataType = IsRegDataType(argv[i]);
if(pAppVars->dwRegDataType == (DWORD)-1)
{
return REG_STATUS_INVALIDPARAMS;
}
bHasType = TRUE;
}
else
return REG_STATUS_TOFEWPARAMS;
}
else if(!_tcsicmp(argv[i], _T("/s")))
{
if(pAppVars->dwRegDataType != REG_MULTI_SZ)
return REG_STATUS_INVALIDPARAMS;
i++;
if(i<argc)
{
if(_tcslen(argv[i]) == 1)
{
_tcscpy(pAppVars->szSeparator, argv[i]);
}
else
return REG_STATUS_INVALIDPARAMS;
}
else
return REG_STATUS_TOFEWPARAMS;
}
else if(!_tcsicmp(argv[i], _T("/d")))
{
if(pAppVars->szValue)
return REG_STATUS_INVALIDPARAMS;
i++;
if(i<argc)
{
pAppVars->szValue = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
sizeof(TCHAR));
if (!pAppVars->szValue) {
return ERROR_NOT_ENOUGH_MEMORY;
}
_tcscpy(pAppVars->szValue, argv[i]);
}
else
return REG_STATUS_TOFEWPARAMS;
}
else if(!_tcsicmp(argv[i], _T("/f")))
{
pAppVars->bForce = TRUE;
}
else
return REG_STATUS_TOMANYPARAMS;
}
// if no value, set to empty value data
if(pAppVars->szValueName && !pAppVars->szValue)
{
pAppVars->szValue = (TCHAR*) calloc(1, sizeof(TCHAR));
if (!pAppVars->szValue) {
return ERROR_NOT_ENOUGH_MEMORY;
}
*(pAppVars->szValue) = 0;
}
else if( !pAppVars->szValueName &&
(bHasType || pAppVars->szValue) )
{
return REG_STATUS_INVALIDPARAMS;
}
return ERROR_SUCCESS;
}