Release 20000326.
[wine/gsoc-2012-control.git] / programs / regapi / regapi.c
bloba7dca2683b3b6ab8789e8e068e7db03b46e7b0ae
1 /*
2 * Command line Registry implementation
4 * Copyright 1999 Sylvain St-Germain
6 * Note: Please consult the README file for more information.
8 */
10 #include <stdio.h>
11 #include <malloc.h>
12 #include <windows.h>
13 #include <winreg.h>
14 #include <winerror.h>
15 #include <winnt.h>
16 #include <string.h>
17 #include <shell.h>
19 /******************************************************************************
20 * Defines and consts
22 #define IDENTICAL 0
23 #define COMMAND_COUNT 5
25 #define KEY_MAX_LEN 1024
26 #define STDIN_MAX_LEN 2048
28 /* Return values */
29 #define COMMAND_NOT_FOUND -1
30 #define SUCCESS 0
31 #define NOT_ENOUGH_MEMORY 1
32 #define KEY_VALUE_ALREADY_SET 2
33 #define COMMAND_NOT_SUPPORTED 3
35 /* Generic global */
36 static BOOL bForce = FALSE; /* Is set to TRUE when -force is
37 passed on the command line */
39 /* Globals used by the api setValue, queryValue */
40 static LPSTR currentKeyName = NULL;
41 static HKEY currentKeyClass = 0;
42 static HKEY currentKeyHandle = 0;
43 static BOOL bTheKeyIsOpen = FALSE;
45 /* Delimiters used to parse the "value"="data" pair for setValue*/
46 #define SET_VALUE_MAX_ARGS 2
47 /* Delimiters used to parse the "value" to query queryValue*/
48 #define QUERY_VALUE_MAX_ARGS 1
50 static const char *setValueDelim[SET_VALUE_MAX_ARGS] = {"=", ""};
51 static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS] = {""};
53 /* Array used to extract the data type from a string in getDataType. */
54 typedef struct tagDataTypeMap
56 char mask[15];
57 DWORD dataType;
58 } dataTypeMap;
60 static const dataTypeMap typeMap[] =
62 {"hex:", REG_BINARY},/* could be REG_NONE (?) */
63 {"dword:", REG_DWORD},
64 {"hex(0):", REG_NONE},
65 {"hex(1):", REG_SZ},
66 {"hex(2):", REG_EXPAND_SZ},
67 {"hex(3):", REG_BINARY},
68 {"hex(4):", REG_DWORD},
69 {"hex(5):", REG_DWORD_BIG_ENDIAN},
70 {"hex(6):", REG_LINK},
71 {"hex(7):", REG_MULTI_SZ},
72 {"hex(8):", REG_RESOURCE_LIST},
73 {"hex(9):", REG_FULL_RESOURCE_DESCRIPTOR},
74 {"hex(10):", REG_RESOURCE_REQUIREMENTS_LIST},
75 {"hex(80000000):", 0x80000000},
76 {"hex(80000001):", 0x80000001},
77 {"hex(80000002):", 0x80000002},
78 {"hex(80000003):", 0x80000003},
79 {"hex(80000004):", 0x80000004},
80 {"hex(80000005):", 0x80000005},
81 {"hex(80000006):", 0x80000006},
82 {"hex(80000007):", 0x80000007},
83 {"hex(80000008):", 0x80000008},
84 {"hex(80000009):", 0x80000000},
85 {"hex(8000000a):", 0x8000000A}
87 const static int LAST_TYPE_MAP = sizeof(typeMap)/sizeof(dataTypeMap);
90 /*
91 * Forward declaration
93 typedef void (*commandAPI)(LPSTR lpsLine);
95 static void doSetValue(LPSTR lpsLine);
96 static void doDeleteValue(LPSTR lpsLine);
97 static void doCreateKey(LPSTR lpsLine);
98 static void doDeleteKey(LPSTR lpsLine);
99 static void doQueryValue(LPSTR lpsLine);
102 * current supported api
104 static const char* commandNames[COMMAND_COUNT] = {
105 "setValue",
106 "deleteValue",
107 "createKey",
108 "deleteKey",
109 "queryValue"
113 * Pointers to processing entry points
115 static const commandAPI commandAPIs[COMMAND_COUNT] = {
116 doSetValue,
117 doDeleteValue,
118 doCreateKey,
119 doDeleteKey,
120 doQueryValue
124 * This array controls the registry saving needs at the end of the process
126 static const BOOL commandSaveRegistry[COMMAND_COUNT] = {
127 TRUE,
128 TRUE,
129 TRUE,
130 TRUE,
131 FALSE
135 * Generic prototyes
137 static HKEY getDataType(LPSTR *lpValue);
138 static LPSTR getRegKeyName(LPSTR lpLine);
139 static HKEY getRegClass(LPSTR lpLine);
140 static LPSTR getArg(LPSTR arg);
141 static INT getCommand(LPSTR commandName);
142 static DWORD convertHexToDWord(char *str, BYTE *buf);
143 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
144 static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
145 static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
146 static HRESULT openKey(LPSTR stdInput);
147 static void closeKey();
150 * api setValue prototypes
152 static void processSetValue(LPSTR cmdline);
153 static HRESULT setValue(LPSTR *argv);
156 * api queryValue prototypes
158 static void processQueryValue(LPSTR cmdline);
161 * Help Text displayed when invalid parameters are provided
163 static char helpText[] =
164 "NAME\n"
165 " regapi - provide a command line interface to the wine registry.\n"
166 "\n"
167 "SYNOPSIS\n"
168 " regapi commandName [-force] < file\n"
169 "\n"
170 "DESCRIPTION\n"
171 " regapi allows editing the wine registry. It processes the given\n"
172 " commandName for every line in the stdin data stream. Input data\n"
173 " format may vary depending on the commandName see INPUT FILE FORMAT.\n"
174 "\n"
175 "OPTIONS\n"
176 " commandName\n"
177 " Instruct regapi about what action to perform on the data stream.\n"
178 " Currently, only setValue and queryValue are supported and\n"
179 " implemented.\n"
180 "\n"
181 " -force\n"
182 " When provided the action will be performed anyway. This may\n"
183 " have a different meaning depending on the context. For example,\n"
184 " when providing -force to setValue, the value is set even if it\n"
185 " was previously set to another value.\n"
186 "\n"
187 " < file\n"
188 " STDIN channel, provide a file name with line of the appropriate\n"
189 " format.\n"
190 "\n"
191 "INPUT FILE FORMAT\n"
192 "\n"
193 " setValue\n"
194 " The input file format required by the setValue command is similar\n"
195 " to the one obtained from regedit.exe export option. The only\n"
196 " difference is that multi line values are not supported, the\n"
197 " value data must be on a single line.\n"
198 "\n"
199 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
200 " \"Value1\"=\"Data1\"\n"
201 " \"Value2\"=\"Data2\"\n"
202 " \"Valuen\"=\"Datan\"\n"
203 " ...\n"
204 "\n"
205 " queryValue\n"
206 " The input file format required by the queryValue command is\n"
207 " similar to the one required by setValue. The only\n"
208 " difference is that you only provide the value name.\n"
209 "\n"
210 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
211 " \"Value1\"\n"
212 " \"Value2\"\n"
213 " \"Valuen\"\n"
214 " ...\n"
215 " February 1999.\n"
219 /******************************************************************************
220 * This function returns the HKEY associated with the data type encoded in the
221 * value. It modify the input parameter (key value) in order to skip this
222 * "now useless" data type information.
224 HKEY getDataType(LPSTR *lpValue)
226 INT counter = 0;
227 DWORD dwReturn = REG_SZ;
229 for (; counter < LAST_TYPE_MAP; counter++)
231 LONG len = strlen(typeMap[counter].mask);
232 if ( strncasecmp( *lpValue, typeMap[counter].mask, len) == IDENTICAL)
235 * We found it, modify the value's pointer in order to skip the data
236 * type identifier, set the return value and exit the loop.
238 (*lpValue) += len;
239 dwReturn = typeMap[counter].dataType;
240 break;
244 return dwReturn;
246 /******************************************************************************
247 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
248 * after the first '\' and end before the ']'
250 LPSTR getRegKeyName(LPSTR lpLine)
252 LPSTR keyNameBeg = NULL;
253 LPSTR keyNameEnd = NULL;
254 char lpLineCopy[KEY_MAX_LEN];
256 if (lpLine == NULL)
257 return NULL;
259 strcpy(lpLineCopy, lpLine);
261 keyNameBeg = strstr(lpLineCopy, "\\"); /* The key name start by '\' */
262 keyNameBeg++; /* but is not part of the key name */
263 keyNameEnd = strstr(lpLineCopy, "]"); /* The key name end by ']' */
264 *keyNameEnd = '\0'; /* Isolate the key name */
266 currentKeyName = HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg)+1);
267 if (currentKeyName != NULL)
268 strcpy(currentKeyName, keyNameBeg);
270 return currentKeyName;
273 /******************************************************************************
274 * Extracts from a [HKEY/some/key/path] type of line the key class (what
275 * starts after the '[' and end before the first '\'
277 static HKEY getRegClass(LPSTR lpClass)
279 LPSTR classNameEnd;
280 LPSTR classNameBeg;
282 char lpClassCopy[KEY_MAX_LEN];
284 if (lpClass == NULL)
285 return ERROR_INVALID_PARAMETER;
287 strcpy(lpClassCopy, lpClass);
289 classNameEnd = strstr(lpClassCopy, "\\"); /* The class name end by '\' */
290 *classNameEnd = '\0'; /* Isolate the class name */
291 classNameBeg = &lpClassCopy[1]; /* Skip the '[' */
293 if (strcmp( classNameBeg, "HKEY_LOCAL_MACHINE") == IDENTICAL )
294 return HKEY_LOCAL_MACHINE;
295 else if (strcmp( classNameBeg, "HKEY_USERS") == IDENTICAL )
296 return HKEY_USERS;
297 else if (strcmp( classNameBeg, "HKEY_CLASSES_ROOT") == IDENTICAL )
298 return HKEY_CLASSES_ROOT;
299 else if (strcmp( classNameBeg, "HKEY_CURRENT_CONFIG") == IDENTICAL )
300 return HKEY_CURRENT_CONFIG;
301 else if (strcmp( classNameBeg, "HKEY_CURRENT_USER") == IDENTICAL )
302 return HKEY_CURRENT_USER;
303 else
304 return ERROR_INVALID_PARAMETER;
307 /******************************************************************************
308 * Returns an allocated buffer with a cleaned copy (removed the surrounding
309 * dbl quotes) of the passed value.
311 static LPSTR getArg( LPSTR arg)
313 LPSTR tmp = NULL;
314 ULONG len;
316 if (arg == NULL)
317 return NULL;
320 * Get rid of surrounding quotes
322 len = strlen(arg);
324 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
325 if( arg[0] == '\"' ) arg++;
327 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
328 strcpy(tmp, arg);
330 return tmp;
333 /******************************************************************************
334 * Returns the index in the commands array of the command to process.
336 static INT getCommand(LPSTR commandName)
338 INT count;
339 for (count=0; count < COMMAND_COUNT; count++)
340 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
341 return count;
343 return COMMAND_NOT_FOUND;
346 /******************************************************************************
347 * Converts a hex representation of a DWORD into a DWORD.
349 static DWORD convertHexToDWord(char *str, BYTE *buf)
351 char *s = str; /* Pointer to current */
352 char *b = buf; /* Pointer to result */
353 ULONG strPos = 0;
355 memset(buf, 0, 4);
357 while (strPos < 4) /* 8 byte in a DWORD */
359 char xbuf[3];
360 char wc;
362 memcpy(xbuf,s,2); xbuf[2]='\0';
363 sscanf(xbuf,"%02x",(UINT*)&wc);
364 *b++ =(unsigned char)wc;
366 s+=2;
367 strPos+=1;
370 return 4; /* always 4 byte for the word */
373 /******************************************************************************
374 * Converts a hex buffer into a hex comma separated values
376 static char* convertHexToHexCSV(BYTE *buf, ULONG bufLen)
378 char* str;
379 char* ptrStr;
380 BYTE* ptrBuf;
382 ULONG current = 0;
384 str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2);
385 memset(str, 0, (bufLen+1)*2);
386 ptrStr = str; /* Pointer to result */
387 ptrBuf = buf; /* Pointer to current */
389 while (current < bufLen)
391 BYTE bCur = ptrBuf[current++];
392 char res[3];
394 sprintf(res, "%02x", (unsigned int)*&bCur);
395 strcat(str, res);
396 strcat(str, ",");
399 /* Get rid of the last comma */
400 str[strlen(str)-1] = '\0';
401 return str;
404 /******************************************************************************
405 * Converts a hex buffer into a DWORD string
407 static char* convertHexToDWORDStr(BYTE *buf, ULONG bufLen)
409 char* str;
410 char* ptrStr;
411 BYTE* ptrBuf;
413 ULONG current = 0;
415 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
416 memset(str, 0, (bufLen*2)+1);
417 ptrStr = str; /* Pointer to result */
418 ptrBuf = buf; /* Pointer to current */
420 while (current < bufLen)
422 BYTE bCur = ptrBuf[current++];
423 char res[3];
425 sprintf(res, "%02x", (unsigned int)*&bCur);
426 strcat(str, res);
429 /* Get rid of the last comma */
430 return str;
432 /******************************************************************************
433 * Converts a hex comma separated values list into a hex list.
435 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
437 char *s = str; /* Pointer to current */
438 char *b = buf; /* Pointer to result */
440 ULONG strLen = strlen(str);
441 ULONG strPos = 0;
442 DWORD byteCount = 0;
444 memset(buf, 0, bufLen);
447 * warn the user if we are here with a string longer than 2 bytes that does
448 * not contains ",". It is more likely because the data is invalid.
450 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
451 printf("regapi: WARNING converting CSV hex stream with no comma, "
452 "input data seems invalid.\n");
454 while (strPos < strLen)
456 char xbuf[3];
457 char wc;
459 memcpy(xbuf,s,2); xbuf[3]='\0';
460 sscanf(xbuf,"%02x",(UINT*)&wc);
461 *b++ =(unsigned char)wc;
463 s+=3;
464 strPos+=3;
465 byteCount++;
468 return byteCount;
472 /******************************************************************************
473 * Sets the value in argv[0] to the data in argv[1] for the currently
474 * opened key.
476 static HRESULT setValue(LPSTR *argv)
478 HRESULT hRes;
479 DWORD dwSize = KEY_MAX_LEN;
480 DWORD dwType = 0;
481 DWORD dwDataType;
483 LPSTR lpsCurrentValue;
485 LPSTR keyValue = argv[0];
486 LPSTR keyData = argv[1];
488 /* Make some checks */
489 if ( (keyValue == NULL) || (keyData == NULL) )
490 return ERROR_INVALID_PARAMETER;
492 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
494 * Default registry values are encoded in the input stream as '@' but as
495 * blank in the wine registry.
497 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
498 keyValue[0] = '\0';
500 /* Get the data type stored into the value field */
501 dwDataType = getDataType(&keyData);
503 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
504 hRes = RegQueryValueExA(
505 currentKeyHandle,
506 keyValue,
507 NULL,
508 &dwType,
509 (LPBYTE)lpsCurrentValue,
510 &dwSize);
512 while(hRes==ERROR_MORE_DATA){
513 dwSize+=KEY_MAX_LEN;
514 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
515 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
518 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
519 ( bForce )) /* -force option */
521 LPBYTE lpbData;
522 BYTE convert[KEY_MAX_LEN];
523 DWORD dwLen;
525 if ( dwDataType == REG_SZ ) /* no convertion for string */
527 dwLen = strlen(keyData);
528 lpbData = keyData;
530 else if (dwDataType == REG_DWORD) /* Convert the dword types */
532 dwLen = convertHexToDWord(keyData, convert);
533 lpbData = convert;
535 else /* Convert the hexadecimal types */
537 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
538 lpbData = convert;
541 hRes = RegSetValueEx(
542 currentKeyHandle,
543 keyValue,
544 0, /* Reserved */
545 dwDataType,
546 lpbData,
547 dwLen);
549 else
551 /* return the current value data into argv[1] */
552 if (argv[1] != NULL)
554 HeapFree(GetProcessHeap(), 0, argv[1]);
555 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
557 if ( argv[1] != NULL ) {
558 strncpy(argv[1], lpsCurrentValue, dwSize);
559 argv[1][dwSize]='\0';
563 return KEY_VALUE_ALREADY_SET;
565 return hRes;
569 /******************************************************************************
570 * Open the key
572 static HRESULT openKey( LPSTR stdInput)
574 DWORD dwDisp;
575 HRESULT hRes;
577 /* Sanity checks */
578 if (stdInput == NULL)
579 return ERROR_INVALID_PARAMETER;
581 /* Get the registry class */
582 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
583 if (currentKeyClass == ERROR_INVALID_PARAMETER)
584 return ERROR_INVALID_PARAMETER;
586 /* Get the key name */
587 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
588 if (currentKeyName == NULL)
589 return ERROR_INVALID_PARAMETER;
591 hRes = RegCreateKeyEx(
592 currentKeyClass, /* Class */
593 currentKeyName, /* Sub Key */
594 0, /* MUST BE 0 */
595 NULL, /* object type */
596 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
597 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
598 NULL, /* security attribute */
599 &currentKeyHandle, /* result */
600 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
601 REG_OPENED_EXISTING_KEY */
603 if (hRes == ERROR_SUCCESS)
604 bTheKeyIsOpen = TRUE;
606 return hRes;
609 /******************************************************************************
610 * This function is a wrapper arround the setValue function. It prepares the
611 * land and clean the area once completed.
613 static void processSetValue(LPSTR cmdline)
615 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
617 LPSTR token = NULL; /* current token analized */
618 ULONG argCounter = 0; /* counter of args */
619 INT counter;
620 HRESULT hRes = 0;
623 * Init storage and parse the line
625 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
626 argv[counter]=NULL;
628 while( (token = strsep(&cmdline, setValueDelim[argCounter])) != NULL )
630 argv[argCounter++] = getArg(token);
632 if (argCounter == SET_VALUE_MAX_ARGS)
633 break; /* Stop processing args no matter what */
636 hRes = setValue(argv);
637 if ( hRes == ERROR_SUCCESS )
638 printf(
639 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
640 argv[0],
641 argv[1],
642 currentKeyName);
644 else if ( hRes == KEY_VALUE_ALREADY_SET )
645 printf(
646 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
647 argv[0],
648 argv[1],
649 currentKeyName);
651 else
652 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
653 currentKeyName,
654 argv[0],
655 argv[1]);
658 * Do some cleanup
660 for (counter=0; counter<argCounter; counter++)
661 if (argv[counter] != NULL)
662 HeapFree(GetProcessHeap(), 0, argv[counter]);
665 /******************************************************************************
666 * This function is a wrapper arround the queryValue function. It prepares the
667 * land and clean the area once completed.
669 static void processQueryValue(LPSTR cmdline)
671 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
672 LPSTR token = NULL; /* current token analized */
673 ULONG argCounter = 0; /* counter of args */
674 INT counter;
675 HRESULT hRes = 0;
676 LPSTR keyValue = NULL;
677 LPSTR lpsRes = NULL;
680 * Init storage and parse the line
682 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
683 argv[counter]=NULL;
685 while( (token = strsep(&cmdline, queryValueDelim[argCounter])) != NULL )
687 argv[argCounter++] = getArg(token);
689 if (argCounter == QUERY_VALUE_MAX_ARGS)
690 break; /* Stop processing args no matter what */
693 /* The value we look for is the first token on the line */
694 if ( argv[0] == NULL )
695 return; /* SHOULD NOT OCCURS */
696 else
697 keyValue = argv[0];
699 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
701 LONG lLen = KEY_MAX_LEN;
702 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
704 * We need to query the key default value
706 hRes = RegQueryValue(
707 currentKeyHandle,
708 currentKeyName,
709 (LPBYTE)lpsData,
710 &lLen);
712 if (hRes==ERROR_MORE_DATA) {
713 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
714 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
717 if (hRes == ERROR_SUCCESS)
719 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
720 strncpy(lpsRes, lpsData, lLen);
721 lpsRes[lLen-1]='\0';
724 else
726 DWORD dwLen = KEY_MAX_LEN;
727 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
728 DWORD dwType;
730 * We need to query a specific value for the key
732 hRes = RegQueryValueEx(
733 currentKeyHandle,
734 keyValue,
736 &dwType,
737 (LPBYTE)lpbData,
738 &dwLen);
740 if (hRes==ERROR_MORE_DATA) {
741 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
742 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
745 if (hRes == ERROR_SUCCESS)
748 * Convert the returned data to a displayable format
750 switch ( dwType )
752 case REG_SZ:
753 case REG_EXPAND_SZ:
755 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
756 strncpy(lpsRes, lpbData, dwLen);
757 lpsRes[dwLen-1]='\0';
758 break;
760 case REG_DWORD:
762 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
763 break;
765 default:
767 lpsRes = convertHexToHexCSV(lpbData, dwLen);
768 break;
773 HeapFree(GetProcessHeap(), 0, lpbData);
777 if ( hRes == ERROR_SUCCESS )
778 printf(
779 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
780 keyValue,
781 lpsRes,
782 currentKeyName);
784 else
785 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
786 keyValue,
787 currentKeyName);
790 * Do some cleanup
792 for (counter=0; counter<argCounter; counter++)
793 if (argv[counter] != NULL)
794 HeapFree(GetProcessHeap(), 0, argv[counter]);
796 if (lpsRes != NULL)
797 HeapFree(GetProcessHeap(), 0, lpsRes);
801 /******************************************************************************
802 * Close the currently opened key.
804 static void closeKey()
806 RegCloseKey(currentKeyHandle);
808 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
810 bTheKeyIsOpen = FALSE;
812 currentKeyName = NULL;
813 currentKeyClass = 0;
814 currentKeyHandle = 0;
817 /******************************************************************************
818 * This funtion is the main entry point to the setValue type of action. It
819 * receives the currently read line and dispatch the work depending on the
820 * context.
822 static void doSetValue(LPSTR stdInput)
825 * We encoutered the end of the file, make sure we
826 * close the opened key and exit
828 if (stdInput == NULL)
830 if (bTheKeyIsOpen != FALSE)
831 closeKey();
833 return;
836 if ( stdInput[0] == '[') /* We are reading a new key */
838 if ( bTheKeyIsOpen != FALSE )
839 closeKey(); /* Close the previous key before */
841 if ( openKey(stdInput) != ERROR_SUCCESS )
842 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
844 else if( ( bTheKeyIsOpen ) &&
845 (( stdInput[0] == '@') || /* reading a default @=data pair */
846 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
848 processSetValue(stdInput);
850 else /* since we are assuming that the */
851 { /* file format is valid we must */
852 if ( bTheKeyIsOpen ) /* be reading a blank line which */
853 closeKey(); /* indicate end of this key processing */
857 /******************************************************************************
858 * This funtion is the main entry point to the queryValue type of action. It
859 * receives the currently read line and dispatch the work depending on the
860 * context.
862 static void doQueryValue(LPSTR stdInput) {
864 * We encoutered the end of the file, make sure we
865 * close the opened key and exit
867 if (stdInput == NULL)
869 if (bTheKeyIsOpen != FALSE)
870 closeKey();
872 return;
875 if ( stdInput[0] == '[') /* We are reading a new key */
877 if ( bTheKeyIsOpen != FALSE )
878 closeKey(); /* Close the previous key before */
880 if ( openKey(stdInput) != ERROR_SUCCESS )
881 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
883 else if( ( bTheKeyIsOpen ) &&
884 (( stdInput[0] == '@') || /* reading a default @=data pair */
885 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
887 processQueryValue(stdInput);
889 else /* since we are assuming that the */
890 { /* file format is valid we must */
891 if ( bTheKeyIsOpen ) /* be reading a blank line which */
892 closeKey(); /* indicate end of this key processing */
896 /******************************************************************************
897 * This funtion is the main entry point to the deletetValue type of action. It
898 * receives the currently read line and dispatch the work depending on the
899 * context.
901 static void doDeleteValue(LPSTR line) {
902 printf ("regapi: deleteValue not yet implemented\n");
904 /******************************************************************************
905 * This funtion is the main entry point to the deleteKey type of action. It
906 * receives the currently read line and dispatch the work depending on the
907 * context.
909 static void doDeleteKey(LPSTR line) {
910 printf ("regapi: deleteKey not yet implemented\n");
912 /******************************************************************************
913 * This funtion is the main entry point to the createKey type of action. It
914 * receives the currently read line and dispatch the work depending on the
915 * context.
917 static void doCreateKey(LPSTR line) {
918 printf ("regapi: createKey not yet implemented\n");
921 /******************************************************************************
922 * MAIN - The main simply validate the first parameter (command to perform)
923 * It then read the STDIN lines by lines forwarding their processing
924 * to the appropriate method.
926 int PASCAL WinMain (HANDLE inst, HANDLE prev, LPSTR cmdline, int show)
928 LPSTR token = NULL; /* current token analized */
929 LPSTR stdInput = NULL; /* line read from stdin */
930 INT cmdIndex = -1; /* index of the command in array */
931 LPSTR nextLine = NULL;
932 ULONG currentSize = STDIN_MAX_LEN;
934 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
935 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
937 if (stdInput == NULL || nextLine== NULL)
938 return NOT_ENOUGH_MEMORY;
941 * get the command, should be the first arg (modify cmdLine)
943 token = strsep(&cmdline, " ");
944 if (token != NULL)
946 cmdIndex = getCommand(token);
947 if (cmdIndex == COMMAND_NOT_FOUND)
949 printf("regapi: Command \"%s\" is not supported.\n", token);
950 printf(helpText);
951 return COMMAND_NOT_SUPPORTED;
954 else
956 printf(
957 "regapi: The first item on the command line must be the command name.\n");
958 printf(helpText);
959 return COMMAND_NOT_SUPPORTED;
963 * check to see weather we force the action
964 * (meaning differ depending on the command performed)
966 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
967 if ( strstr(cmdline, "-force") != NULL )
968 bForce = TRUE;
970 printf("Processing stdin...\n");
972 while ( TRUE )
975 * read a line
977 ULONG curSize=STDIN_MAX_LEN;
978 char* s=NULL;
980 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
981 fseek(stdin,-curSize,SEEK_CUR+1);
982 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
985 * Make some handy generic stuff here...
987 if ( stdInput != NULL )
989 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
991 if( stdInput[0] == '#' ) /* this is a comment, skip */
992 continue;
994 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
995 /* that this line is not complete and we have to get */
996 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
998 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1000 nextLine[strlen(nextLine)-1] = '\0';
1002 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1004 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1006 currentSize+=STDIN_MAX_LEN;
1009 strcat(stdInput,nextLine+2);
1014 * We process every lines even the NULL (last) line, to indicate the
1015 * end of the processing to the specific process.
1017 commandAPIs[cmdIndex](stdInput);
1019 if (stdInput == NULL) /* EOF encountered */
1020 break;
1023 #if 0
1025 * Save the registry only if it was modified
1027 if ( commandSaveRegistry[cmdIndex] != FALSE )
1028 SHELL_SaveRegistry();
1029 #endif
1030 HeapFree(GetProcessHeap(), 0, nextLine);
1032 HeapFree(GetProcessHeap(), 0, stdInput);
1034 return SUCCESS;