Make access to the DCE list thread safe by ensuring we have acquired
[wine/hacks.git] / programs / regapi / regapi.c
blob59c74d36df470fea8b4e3de83992314d43cd4021
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 = NULL;
42 static HKEY currentKeyHandle = NULL;
43 static BOOL bTheKeyIsOpen = FALSE;
45 /* Delimitors used to parse the "value"="data" pair for setValue*/
46 #define SET_VALUE_MAX_ARGS 2
47 /* Delimitors 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(80000000):", REG_NONE},
75 {"hex(80000001):", REG_SZ},
76 {"hex(80000002):", REG_EXPAND_SZ},
77 {"hex(80000003):", REG_BINARY},
78 {"hex(80000004):", REG_DWORD},
79 {"hex(80000005):", REG_DWORD_BIG_ENDIAN},
80 {"hex(80000006):", REG_LINK},
81 {"hex(80000007):", REG_MULTI_SZ},
82 {"hex(80000008):", REG_RESOURCE_LIST},
83 {"hex(80000009):", REG_FULL_RESOURCE_DESCRIPTOR},
84 {"hex(8000000a):", REG_BINARY}, /* REG_RESOURCE_REQUIREMENTS_LIST}, !Exist */
85 {"hex(8000000A):", REG_BINARY}, /* REG_RESOURCE_REQUIREMENTS_LIST}, !Exist */
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 suuported 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 displyed when invalid parameters are provided
163 static char helpText[] = "
164 NAME
165 regapi - provide a command line interface to the wine registry.
167 SYNOPSYS
168 regapi commandName [-force] < file
170 DESCRIPTION
171 regapi allows editing the wine resgistry. It processes the given
172 commandName for every line in the stdin data stream. Input data
173 format may vary depending on the commandName see INPUT FILE FORMAT.
175 OPTIONS
176 commandName
177 Instruct regapi about what action to perform on the data stream.
178 Currently, only setValue and queryValue are supported and
179 implemented.
181 -force
182 When provided the action will be performed anyway. This may
183 have a different meaning depending on the context. For example,
184 when providing -force to setValue, the value is set even if it
185 was previously set to another value.
187 < file
188 STDIN chanel, provide a file name with line of the appropriate
189 format.
191 INPUT FILE FORMAT
193 setValue
194 The input file format required by the setValue command is similar
195 to the one obtained from regedit.exe export option. The only
196 difference is that multi line values are not supported, the
197 value data must be on a single line.
199 [KEY_CLASS\\Some\\Path\\For\\A\\Key]
200 \"Value1\"=\"Data1\"
201 \"Value2\"=\"Data2\"
202 \"Valuen\"=\"Datan\"
205 queryValue
206 The input file format required by the queryValue command is
207 similar to the one required by setValue. The only
208 difference is that you only provide the value name.
210 [KEY_CLASS\\Some\\Path\\For\\A\\Key]
211 \"Value1\"
212 \"Value2\"
213 \"Valuen\"
215 February 1999.
219 /******************************************************************************
220 * This funtion 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 ( strncmp( *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 = NULL; /* 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 = NULL; /* 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] = NULL;
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 coma 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 coma */
400 str[strlen(str)-1] = NULL;
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 coma */
430 return str;
432 /******************************************************************************
433 * Converts a hex coma 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 coma, "
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 = NULL;
481 DWORD dwDataType;
483 CHAR lpsCurrentValue[KEY_MAX_LEN];
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;
493 * Default registry values are encoded in the input stream as '@' but as
494 * blank in the wine registry.
496 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
497 keyValue[0] = NULL;
499 /* Get the data type stored into the value field */
500 dwDataType = getDataType(&keyData);
502 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
503 hRes = RegQueryValueExA(
504 currentKeyHandle,
505 keyValue,
506 NULL,
507 &dwType,
508 (LPBYTE)lpsCurrentValue,
509 &dwSize);
511 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
512 ( bForce )) /* -force option */
514 LPBYTE lpbData;
515 BYTE convert[KEY_MAX_LEN];
516 DWORD dwLen;
518 if ( dwDataType == REG_SZ ) /* no convertion for string */
520 dwLen = strlen(keyData);
521 lpbData = keyData;
523 else if (dwDataType == REG_DWORD) /* Convert the dword types */
525 dwLen = convertHexToDWord(keyData, convert);
526 lpbData = convert;
528 else /* Convert the hexadecimal types */
530 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
531 lpbData = convert;
534 hRes = RegSetValueEx(
535 currentKeyHandle,
536 keyValue,
537 0, /* Reserved */
538 dwDataType,
539 lpbData,
540 dwLen);
542 else
544 /* return the current value data into argv[1] */
545 if (argv[1] != NULL)
547 HeapFree(GetProcessHeap(), 0, argv[1]);
548 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
550 if ( argv[1] != NULL )
551 strncpy(argv[1], lpsCurrentValue, dwSize);
554 return KEY_VALUE_ALREADY_SET;
556 return hRes;
560 /******************************************************************************
561 * Open the key
563 static HRESULT openKey( LPSTR stdInput)
565 DWORD dwDisp;
566 HRESULT hRes;
568 /* Sanity checks */
569 if (stdInput == NULL)
570 return ERROR_INVALID_PARAMETER;
572 /* Get the registry class */
573 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
574 if (currentKeyClass == ERROR_INVALID_PARAMETER)
575 return ERROR_INVALID_PARAMETER;
577 /* Get the key name */
578 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
579 if (currentKeyName == NULL)
580 return ERROR_INVALID_PARAMETER;
582 hRes = RegCreateKeyEx(
583 currentKeyClass, /* Class */
584 currentKeyName, /* Sub Key */
585 0, /* MUST BE 0 */
586 NULL, /* object type */
587 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
588 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
589 NULL, /* security attribute */
590 &currentKeyHandle, /* result */
591 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
592 REG_OPENED_EXISTING_KEY */
594 if (hRes == ERROR_SUCCESS)
595 bTheKeyIsOpen = TRUE;
597 return hRes;
600 /******************************************************************************
601 * This function is a wrapper arround the setValue function. It prepares the
602 * land and clean the area once completed.
604 static void processSetValue(LPSTR cmdline)
606 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
608 LPSTR token = NULL; /* current token analized */
609 ULONG argCounter = 0; /* counter of args */
610 INT counter;
611 HRESULT hRes = NULL;
614 * Init storage and parse the line
616 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
617 argv[counter]=NULL;
619 while( (token = strsep(&cmdline, setValueDelim[argCounter])) != NULL )
621 argv[argCounter++] = getArg(token);
623 if (argCounter == SET_VALUE_MAX_ARGS)
624 break; /* Stop processing args no matter what */
627 hRes = setValue(argv);
628 if ( hRes == ERROR_SUCCESS )
629 printf(
630 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
631 argv[0],
632 argv[1],
633 currentKeyName);
635 else if ( hRes == KEY_VALUE_ALREADY_SET )
636 printf(
637 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
638 argv[0],
639 argv[1],
640 currentKeyName);
642 else
643 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
644 currentKeyName,
645 argv[0],
646 argv[1]);
649 * Do some cleanup
651 for (counter=0; counter<argCounter; counter++)
652 if (argv[counter] != NULL)
653 HeapFree(GetProcessHeap(), 0, argv[counter]);
656 /******************************************************************************
657 * This function is a wrapper arround the queryValue function. It prepares the
658 * land and clean the area once completed.
660 static void processQueryValue(LPSTR cmdline)
662 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
663 LPSTR token = NULL; /* current token analized */
664 ULONG argCounter = 0; /* counter of args */
665 INT counter;
666 HRESULT hRes = NULL;
667 LPSTR keyValue = NULL;
668 LPSTR lpsRes = NULL;
671 * Init storage and parse the line
673 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
674 argv[counter]=NULL;
676 while( (token = strsep(&cmdline, queryValueDelim[argCounter])) != NULL )
678 argv[argCounter++] = getArg(token);
680 if (argCounter == QUERY_VALUE_MAX_ARGS)
681 break; /* Stop processing args no matter what */
684 /* The value we look for is the first token on the line */
685 if ( argv[0] == NULL )
686 return; /* SHOULD NOT OCCURS */
687 else
688 keyValue = argv[0];
690 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
692 LONG lLen = KEY_MAX_LEN;
693 CHAR lpsData[KEY_MAX_LEN];
695 * We need to query the key default value
697 hRes = RegQueryValue(
698 currentKeyHandle,
699 currentKeyName,
700 (LPBYTE)lpsData,
701 &lLen);
703 if (hRes == ERROR_SUCCESS)
705 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
706 strncpy(lpsRes, lpsData, lLen);
709 else
711 DWORD dwLen = KEY_MAX_LEN;
712 BYTE lpbData[KEY_MAX_LEN];
713 DWORD dwType;
715 * We need to query a specific value for the key
717 hRes = RegQueryValueEx(
718 currentKeyHandle,
719 keyValue,
721 &dwType,
722 (LPBYTE)lpbData,
723 &dwLen);
725 if (hRes == ERROR_SUCCESS)
728 * Convert the returned data to a displayable format
730 switch ( dwType )
732 case REG_SZ:
734 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
735 strncpy(lpsRes, lpbData, dwLen);
736 break;
738 case REG_DWORD:
740 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
741 break;
743 default:
745 lpsRes = convertHexToHexCSV(lpbData, dwLen);
746 break;
753 if ( hRes == ERROR_SUCCESS )
754 printf(
755 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
756 keyValue,
757 lpsRes,
758 currentKeyName);
760 else
761 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
762 keyValue,
763 currentKeyName);
766 * Do some cleanup
768 for (counter=0; counter<argCounter; counter++)
769 if (argv[counter] != NULL)
770 HeapFree(GetProcessHeap(), 0, argv[counter]);
772 if (lpsRes != NULL)
773 HeapFree(GetProcessHeap(), 0, lpsRes);
777 /******************************************************************************
778 * Close the currently opened key.
780 static void closeKey()
782 RegCloseKey(currentKeyHandle);
784 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
786 bTheKeyIsOpen = FALSE;
788 currentKeyName = NULL;
789 currentKeyClass = NULL;
790 currentKeyHandle = NULL;
793 /******************************************************************************
794 * This funtion is the main entry point to the setValue type of action. It
795 * receives the currently read line and dispatch the work depending on the
796 * context.
798 static void doSetValue(LPSTR stdInput)
801 * We encoutered the end of the file, make sure we
802 * close the opened key and exit
804 if (stdInput == NULL)
806 if (bTheKeyIsOpen != FALSE)
807 closeKey();
809 return;
812 if ( stdInput[0] == '[') /* We are reading a new key */
814 if ( bTheKeyIsOpen != FALSE )
815 closeKey(); /* Close the previous key before */
817 if ( openKey(stdInput) != ERROR_SUCCESS )
818 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
820 else if( ( bTheKeyIsOpen ) &&
821 (( stdInput[0] == '@') || /* reading a default @=data pair */
822 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
824 processSetValue(stdInput);
826 else /* since we are assuming that the */
827 { /* file format is valid we must */
828 if ( bTheKeyIsOpen ) /* be reading a blank line which */
829 closeKey(); /* indicate end of this key processing */
833 /******************************************************************************
834 * This funtion is the main entry point to the queryValue type of action. It
835 * receives the currently read line and dispatch the work depending on the
836 * context.
838 static void doQueryValue(LPSTR stdInput) {
840 * We encoutered the end of the file, make sure we
841 * close the opened key and exit
843 if (stdInput == NULL)
845 if (bTheKeyIsOpen != FALSE)
846 closeKey();
848 return;
851 if ( stdInput[0] == '[') /* We are reading a new key */
853 if ( bTheKeyIsOpen != FALSE )
854 closeKey(); /* Close the previous key before */
856 if ( openKey(stdInput) != ERROR_SUCCESS )
857 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
859 else if( ( bTheKeyIsOpen ) &&
860 (( stdInput[0] == '@') || /* reading a default @=data pair */
861 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
863 processQueryValue(stdInput);
865 else /* since we are assuming that the */
866 { /* file format is valid we must */
867 if ( bTheKeyIsOpen ) /* be reading a blank line which */
868 closeKey(); /* indicate end of this key processing */
872 /******************************************************************************
873 * This funtion is the main entry point to the deletetValue type of action. It
874 * receives the currently read line and dispatch the work depending on the
875 * context.
877 static void doDeleteValue(LPSTR line) {
878 printf ("regapi: deleteValue not yet implemented\n");
880 /******************************************************************************
881 * This funtion is the main entry point to the deleteKey type of action. It
882 * receives the currently read line and dispatch the work depending on the
883 * context.
885 static void doDeleteKey(LPSTR line) {
886 printf ("regapi: deleteKey not yet implemented\n");
888 /******************************************************************************
889 * This funtion is the main entry point to the createKey type of action. It
890 * receives the currently read line and dispatch the work depending on the
891 * context.
893 static void doCreateKey(LPSTR line) {
894 printf ("regapi: createKey not yet implemented\n");
897 /******************************************************************************
898 * MAIN - The main simply validate the first parameter (command to perform)
899 * It then read the STDIN lines by lines forwarding their processing
900 * to the appropriate method.
902 int PASCAL WinMain (HANDLE inst, HANDLE prev, LPSTR cmdline, int show)
904 LPSTR token = NULL; /* current token analized */
905 LPSTR stdInput = NULL; /* line read from stdin */
906 INT cmdIndex = -1; /* index of the command in array */
908 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
909 if (stdInput == NULL)
910 return NOT_ENOUGH_MEMORY;
913 * get the command, should be the first arg (modify cmdLine)
915 token = strsep(&cmdline, " ");
916 if (token != NULL)
918 cmdIndex = getCommand(token);
919 if (cmdIndex == COMMAND_NOT_FOUND)
921 printf("regapi: Command \"%s\" is not supported.\n", token);
922 printf(helpText);
923 return COMMAND_NOT_SUPPORTED;
926 else
928 printf(
929 "regapi: The first item on the command line must be the command name.\n");
930 printf(helpText);
931 return COMMAND_NOT_SUPPORTED;
935 * check to see weather we force the action
936 * (meaning differ depending on the command performed)
938 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
939 if ( strstr(cmdline, "-force") != NULL )
940 bForce = TRUE;
942 printf("Processing stdin...\n");
944 while ( TRUE )
947 * read a line
949 stdInput = fgets(stdInput, STDIN_MAX_LEN, stdin);
952 * Make some handy generic stuff here...
954 if ( stdInput != NULL )
956 stdInput[strlen(stdInput) -1] = NULL; /* get rid of new line */
958 if( stdInput[0] == '#' ) /* this is a comment, skip */
959 continue;
963 * We process every lines even the NULL (last) line, to indicate the
964 * end of the processing to the specific process.
966 commandAPIs[cmdIndex](stdInput);
968 if (stdInput == NULL) /* EOF encountered */
969 break;
973 * Save the registry only if it was modified
975 if ( commandSaveRegistry[cmdIndex] != FALSE )
976 SHELL_SaveRegistry();
978 HeapFree(GetProcessHeap(), 0, stdInput);
979 return SUCCESS;