//-----------------------------------------------------------------------// // // 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; iszValueName) return REG_STATUS_INVALIDPARAMS; i++; if(iszValueName = (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(idwRegDataType = 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(iszSeparator, 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(iszValue = (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; }