Thread: Reading REG_MULTI_SZ strings

  1. #31
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Quote Originally Posted by zmfcat View Post
    Actually I was able to use the code snippet in comment #2, to retrieve data from the registry without the null terminators and have written it to params.

    >>You may want to consider possibly using unsigned char * as the type of input as opposed to >>char * to your function as a starting point

    Can you let me know where you are pointing this too? Thanks.
    Here is one possible option. I've tested it withe my code from above.


    Code:
    VOID SplitMultiString(unsigned char * instr)
    {
    	int x = 0;
    	while(1)
    	{
    		printf("%c", instr[x]);
    		if(instr[++x] == '\0' && instr[x + 1] == '\0')
    			break;
    		else if (instr[x] == '\0')
    		{
    			++x;
    			printf("\n");
    		}
    	}
    }
    It's called from the code as follows:

    Code:
    SplitMultiString(lpBuffer);

  2. #32
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hii all,
    Below are the latest modifications to my code, I believe the data has be written to tmp2
    using ptr1, but not sure whether I am returning things right, when I print the value of tmp2 its prints only the first data value, which is obvious because of the \0 after the first data value.
    I pass tmp2 into RegSetValueEx which is not correct. Ho can i pass the whole sting tmp2 which will include the null characters in between and teh terminating null characters.

    Code:
    char* createMultiString(char *params[], int j, char *tmp2)
    {   
       char *ptr1; 
       
       int i=0;
       int count=0;
       int len=0;
       char value[MAX_PATH]={NULL};
       
       sprintf (value,"XXX");
       tmp2 = (char *)malloc(MAX_PATH);
       memset(tmp2, '\0', sizeof(tmp2));
       ptr1=tmp2;
    	
       for (i=0; i<j;i++)
       {
    		printf ("In loop\n"); 
    		if (strcmp(params[i],value) != 0)
    		{				
    			printf ("Data value not XXX\n"); 
    			strcpy(ptr1,params[i]);
    			len =strlen(ptr1);
    			printf ("Data value is %s and len is %d\n",ptr1,len); 
    			ptr1 += len + 2;
    			printf ("The current pointer value is\n",ptr1); 
    		}	
    		else
    		{
    			printf ("Data value is XXX\n"); 
    		}
    	}
    	printf("---Final Value of Temp is %s after appending all Parameters\n",tmp2);	
    	return tmp2; 
    }

  3. #33
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hi all
    Just a follow up to my earlier post, this is how tmp2 is being passed to RegSetValueEx

    Code:
    sprintf(value11, "ValueName");
    RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)&srcKeyName,0,KEY_SET_VALUE, &Gt5Key);
    if (setValue_multi_sz(Gt5Key, value11, tmp2) == true)
    {
    	printf("---Success in setting new ValueName\n");
    }
    else
    {
    printf("---Failure in setting value of ValueName under &#37;s , errorcode is: %d\n",srcKeyName, GetLastError());				
    }
    
    bool setValue_multi_sz(HKEY hKey, const char *valueName, char* value) {
    
    //indent++;
    bool rc = true;
     DWORD result = RegSetValueEx(hKey, valueName, 0,REG_MULTI_SZ, reinterpret_cast <CONST BYTE *>(value), strlen(value)+1);   
    if (NO_ERROR != result) {
    //MessageBox(hWnd, valueName, "setValue error", MB_OK);
    printf(msgbuff, "ERROR: RegSetValueEx(%s:%s) failed with error code %d.\n", valueName, value, result);
    //	LogMessage(hModule, (LPCTSTR)msgbuff);		
    rc = false;
       }
    else {		
    printf("\t to set %s=%s\n", valueName, value);
    //	LogMessage(hModule, (LPCTSTR)msgbuff);
    }
    
    	// indent--;
    	return rc;
    }

  4. #34
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    I pass tmp2 into RegSetValueEx which is not correct. Ho can i pass the whole sting tmp2 which will include the null characters in between and teh terminating null characters.
    I'm just not sure I'd want to use strcpy, strlen etc. in your project. IMHO, it's just too easy to get into trouble using those calls with char arrays that have embedded nulls.

    Here is one possible solution:

    Code:
    #pragma comment ( lib, "advapi32.lib" ) 
    
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    CHAR* createMultiString(CHAR *params[], INT iCount, INT *iReturn)
    {
        char *pData = NULL;
        int iIndex1,iIndex2;
        for (iIndex1 = 0, iIndex2 = 0; iIndex1 < iCount; iIndex1++)
            iIndex2 += strlen(params[iIndex1])+ 1;
        pData = (char *)malloc(iIndex2);
        memset(pData, 0, sizeof(pData));
        for (iIndex1 = 0, iIndex2 = 0; iIndex1 < iCount; iIndex1++)
        {
            strcpy(pData+iIndex2, params[iIndex1]);
            iIndex2 += strlen(params[iIndex1])+1;
        }
        pData[iIndex2] = 0;
        *iReturn = iIndex2;
        return pData;
    }
    
    INT main(VOID)
    {
        HKEY hKey = NULL;
        char szValue[MAX_PATH] = {0};
        char **pPtr = NULL; 
        int iReturn, iIndex; 
    
        pPtr = (char **)malloc(3 * sizeof *pPtr);
        if (pPtr != NULL)
    	{
            for (iIndex = 0; iIndex < 3; iIndex++)
                pPtr[iIndex] = (char *) malloc(sizeof(char) * 10);
        }
        else return 0;
        strcpy(pPtr[0], "String1");
        strcpy(pPtr[1], "String2");
        strcpy(pPtr[2], "String3");
        memcpy(szValue, createMultiString(pPtr, 3, &iReturn), MAX_PATH);
        RegOpenKeyEx(HKEY_LOCAL_MACHINE,TEXT("Software\\TestKey"),0,KEY_ALL_ACCESS,&hKey);
        RegSetValueEx(hKey, "TestSubKey", 0,REG_MULTI_SZ, reinterpret_cast <CONST BYTE *>(szValue), iReturn + 1);   
        RegCloseKey(hKey);
        return 0; 
    }

  5. #35
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by zmfcat View Post
    iMalc,
    I actually tried the approach that you suggested. But when I used RegSetValueEx to write to the registry, it writes just the first data value, not sure why. Thanks.
    You probably took the strlen after converting \n back to \0 which wont work.

    Here's an abstract from some old code production code where I have renamed everything to anonymise it, and this code is no longer used anyway. It appends a string to a multiistring registry value. This code is not particularly C++ish, and I take no responsibility for any problems it might cause. The code we eventually used did not have the potential buffer overrun this has.
    Code:
    	TCHAR appendMe = _T("Append Me\n");
    	CRegKey regKey;
    	if (regKey.Create(HKEY_LOCAL_MACHINE, MY_HKEY_LOCATION) == ERROR_SUCCESS)
    	{
    		TCHAR multiString[512];
    		ULONG nChars(countof(multiString));
    		regKey.QueryMultiStringValue(_T("MyMultiString"), multiString, &nChars);
    		for (ULONG i=0; i<nChars-1; ++i)
    			if (multiString[i] == _T('\0'))
    				multiString[i] = _T('\n');
    		if (_tcsstr(multiString, appendMe) == NULL)
    		{
    			_tcscat(&multiString[nChars-1], appendMe);
    			nChars += (ULONG)_tcslen(appendMe);
    
    			for (ULONG i=0; i<nChars-1; ++i)
    				if (multiString[i] == _T('\n'))
    					multiString[i] = _T('\0');
    			regKey.SetMultiStringValue(_T("MyMultiString"), multiString);
    		}
    		regKey.Close();
    	}
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #36
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hi all, another follow up question

    I have a string array with the following data
    AAA BBB CCC DDD
    and I want to copy all the above data expect BB to another string array. I have the below. inputarray is my source string array and I want to write it to outputarr.
    The problem I have is as seen below where data does not get copied consecutively to outputarr. Can some help me on this? Thanks.

    Code:
    nt remBBB(char *inputarray[], char *outputarr[], int count)
    {
    	printf ("In remBBB\n");
    	int x=0; 
    	int count1=0; 
    	char value[MAX_PATH]={NULL}; 
    	sprintf (value,"BBB"); 
    	for (x=0; x < count; x++)
    	{
    		if (strcmp(inputarray[x],value) != 0)
    		{
    			memcpy(outputarr[x], inputarray[x], sizeof(outputarr[x])); 
    			count1++; 
    		}	
    	}
    	return count1++; 
    }

  7. #37
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hi all, reposting because of some typos

    I have a string array with the following data
    AAA BBB CCC DDD
    and I want to copy all the above data except BBB to another string array. I have the below. inputarray is my source string array and I want to write it to outputarr.
    The problem I have is as seen below where data does not get copied consecutively to outputarr. Can some help me on this? Thanks.

    Code:
    int remBBB(char *inputarray[], char *outputarr[], int count)
    {
    	printf ("In remBBB\n");
    	int x=0; 
    	int count1=0; 
    	char value[MAX_PATH]={NULL}; 
    	sprintf (value,"BBB"); 
    	for (x=0; x < count; x++)
    	{
    		if (strcmp(inputarray[x],value) != 0)
    		{
    			memcpy(outputarr[x], inputarray[x], sizeof(outputarr[x])); 
    			count1++; 
    		}	
    	}
    	return count1++; 
    }

  8. #38
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Quote Originally Posted by zmfcat View Post
    Hi all, reposting because of some typos

    I have a string array with the following data
    AAA BBB CCC DDD
    and I want to copy all the above data except BBB to another string array. I have the below. inputarray is my source string array and I want to write it to outputarr.
    The problem I have is as seen below where data does not get copied consecutively to outputarr. Can some help me on this? Thanks.

    Code:
    int remBBB(char *inputarray[], char *outputarr[], int count)
    {
    	printf ("In remBBB\n");
    	int x=0; 
    	int count1=0; 
    	char value[MAX_PATH]={NULL}; 
    	sprintf (value,"BBB"); 
    	for (x=0; x < count; x++)
    	{
    		if (strcmp(inputarray[x],value) != 0)
    		{
    			memcpy(outputarr[x], inputarray[x], sizeof(outputarr[x])); 
    			count1++; 
    		}	
    	}
    	return count1++; 
    }
    One possible solution:

    Code:
    BOOL ModifyRegistryValue(LPTSTR lpInput, LPCTSTR lpSearchValue, INT iSize)
    {
        INT iCount = 0, iIndex = 0;
    
        while(_tcslen(lpInput))
        {
            if(_tcscmp(lpInput, lpSearchValue) == 0)
            {
                iCount += _tcslen(lpInput) + 1;
                iIndex = _tcslen(lpInput) + 1;
                memcpy(lpInput,lpInput + iIndex, iSize - iCount);
                lpInput[iIndex + iCount + 1] = 0;
    			return TRUE;
            }
            else
            {
                iCount += _tcslen(lpInput) + 1;
                lpInput +=  _tcslen(lpInput) + 1;
            }
        }
        return FALSE;
    }
    It's called as follows:

    Code:
    RegQueryValueEx(
        hKey,           
        TEXT("TestSubKey"),
        0,              
        &dwType,        
        lpBuffer,      
        &dwSize        
        );
    
    LPTSTR p = LPTSTR(lpBuffer);
    ModifyRegistryValue(p, "BBB", dwSize);

  9. #39
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Did you mean?
    Code:
                memcpy(lpInput, lpInput + iIndex, (iSize - (iCount * sizeof(*lpInput))));
                lpInput[_tcslen(lpInput) + 1] = 0;
                return TRUE;
    iSize is a byte count while iCount is a character count, their subtraction would yield an incorrect number of bytes to copy for Unicode strings.

  10. #40
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Quote Originally Posted by adeyblue View Post
    Did you mean?
    Code:
                memcpy(lpInput, lpInput + iIndex, (iSize - (iCount * sizeof(*lpInput))));
                lpInput[_tcslen(lpInput) + 1] = 0;
                return TRUE;
    iSize is a byte count while iCount is a character count, their subtraction would yield an incorrect number of bytes to copy for Unicode strings.
    Done in context of post #24

  11. #41
    'Allo, 'Allo, Allo
    Join Date
    Apr 2008
    Posts
    639
    Then why use the all the _t versions? Besides judging from all the dubious casts in post 33 it looks like (s)he's planning to or already compiling as unicode.

    Oh and the code in post 22 has an out of bounds access if a string consisting of "\0\0" is passed in. I know you're trying to help Bob, but giving out buggy code ultimately helps no-one.

    @zmfcat
    What errors or warnings do you get if you take out the red bit below? It smells a bit dodgy, and shouldn't be required.
    RegOpenKeyEx(HKEY_LOCAL_MACHINE,(LPCTSTR)&srcKeyName,0,KEY_SET_VALUE, &Gt5Key);

  12. #42
    Registered User
    Join Date
    Mar 2005
    Location
    Mountaintop, Pa
    Posts
    1,058
    Quote Originally Posted by adeyblue View Post
    Then why use the all the _t versions? Besides judging from all the dubious casts in post 33 it looks like (s)he's planning to or already compiling as unicode.

    Oh and the code in post 22 has an out of bounds access if a string consisting of "\0\0" is passed in. I know you're trying to help Bob, but giving out buggy code ultimately helps no-one.

    @zmfcat
    What errors or warnings do you get if you take out the red bit below? It smells a bit dodgy, and shouldn't be required.
    Post 22 doesn't belong to me and post 33 is your post.
    Last edited by BobS0327; 12-11-2008 at 08:56 AM.

  13. #43
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hi all,
    Thanks for your help, I was able to get things working. Posting the code snippet, which might help someone.

    count is the number of data values found in the registry string.
    Code:
    int remBBB(char *inputarray[], char *outputarr[], int count,MSIHANDLE hModule)
    {
    	sprintf (msgbuff,"---In remBBB\n");
    	LogMessage(hModule, (LPCTSTR)msgbuff);
    	sprintf (msgbuff,"----Number of data values received by this function is &#37;d\n",count);
    	LogMessage(hModule, (LPCTSTR)msgbuff);
    	int x=0; 
    	int count1=0; 
    	char value[MAX_PATH]={NULL}; 
    	sprintf (value,"BBB"); 
    	for (x=0; x < count; x++)
    	{
    		sprintf (msgbuff, "----The input data value is %s\n",inputarray[x]);
    		LogMessage(hModule, (LPCTSTR)msgbuff);
    		if (strcmp(inputarray[x],value) != 0)
    		{			
    			outputarr[count1]= inputarray[x];
    			count1++; 			
    		}		
    	}
    	return count1; 
    }

  14. #44
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Hi Bob
    I used the createMultiString snippet posted in comment #34, I have no issues on 32-bit compilation, but it throws me some warnings on 64-bit compilation, I see the below. Is there a conversion problem that we need to take care off? Thanks.

    C:\Program Files\Microsoft Visual Studio\MyProjects\123\xxx\xxx.cpp(292) : warning C4267: '+=' : conversion from 'size_t' to 'int', possible loss of data

  15. #45
    Registered User
    Join Date
    Dec 2008
    Posts
    19
    Just a follow up to comment #44, teh above warning is thrown on the line
    iIndex2 += strlen(params[iIndex1])+ 1;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. reading data from strings
    By Winston Hong in forum C Programming
    Replies: 11
    Last Post: 05-28-2008, 08:56 PM
  2. Replies: 2
    Last Post: 01-28-2008, 03:07 AM
  3. reading from a file + list of strings
    By stewie1986 in forum C Programming
    Replies: 2
    Last Post: 12-06-2007, 11:59 PM
  4. Reading strings input by the user...
    By Cmuppet in forum C Programming
    Replies: 13
    Last Post: 07-21-2004, 06:37 AM
  5. question about reading in strings from a file :>
    By bball887 in forum C Programming
    Replies: 8
    Last Post: 04-13-2004, 06:24 PM