Use the font default char for undefined characters when mapping from
[wine.git] / programs / regapi / regapi.c
blob70eea66b10936c720982ad20ecda5f55f54ef94e
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 7
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);
100 static void doRegisterDLL(LPSTR lpsLine);
101 static void doUnregisterDLL(LPSTR lpsLine);
104 * current supported api
106 static const char* commandNames[COMMAND_COUNT] = {
107 "setValue",
108 "deleteValue",
109 "createKey",
110 "deleteKey",
111 "queryValue",
112 "registerDLL",
113 "unregisterDLL"
117 * Pointers to processing entry points
119 static const commandAPI commandAPIs[COMMAND_COUNT] = {
120 doSetValue,
121 doDeleteValue,
122 doCreateKey,
123 doDeleteKey,
124 doQueryValue,
125 doRegisterDLL,
126 doUnregisterDLL
130 * This array controls the registry saving needs at the end of the process
132 static const BOOL commandSaveRegistry[COMMAND_COUNT] = {
133 TRUE,
134 TRUE,
135 TRUE,
136 TRUE,
137 FALSE,
138 TRUE,
139 TRUE
143 * Generic prototyes
145 static HKEY getDataType(LPSTR *lpValue);
146 static LPSTR getRegKeyName(LPSTR lpLine);
147 static HKEY getRegClass(LPSTR lpLine);
148 static LPSTR getArg(LPSTR arg);
149 static INT getCommand(LPSTR commandName);
150 static DWORD convertHexToDWord(char *str, BYTE *buf);
151 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
152 static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
153 static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
154 static HRESULT openKey(LPSTR stdInput);
155 static void closeKey();
158 * api setValue prototypes
160 static void processSetValue(LPSTR cmdline);
161 static HRESULT setValue(LPSTR *argv);
164 * api queryValue prototypes
166 static void processQueryValue(LPSTR cmdline);
169 * Help Text displayed when invalid parameters are provided
171 static char helpText[] =
172 "NAME\n"
173 " regapi - provide a command line interface to the wine registry.\n"
174 "\n"
175 "SYNOPSIS\n"
176 " regapi commandName [-force] < file\n"
177 "\n"
178 "DESCRIPTION\n"
179 " regapi allows editing the wine registry. It processes the given\n"
180 " commandName for every line in the stdin data stream. Input data\n"
181 " format may vary depending on the commandName see INPUT FILE FORMAT.\n"
182 "\n"
183 "OPTIONS\n"
184 " commandName\n"
185 " Instruct regapi about what action to perform on the data stream.\n"
186 " Currently, only setValue and queryValue are supported and\n"
187 " implemented.\n"
188 "\n"
189 " -force\n"
190 " When provided the action will be performed anyway. This may\n"
191 " have a different meaning depending on the context. For example,\n"
192 " when providing -force to setValue, the value is set even if it\n"
193 " was previously set to another value.\n"
194 "\n"
195 " < file\n"
196 " STDIN channel, provide a file name with line of the appropriate\n"
197 " format.\n"
198 "\n"
199 "INPUT FILE FORMAT\n"
200 "\n"
201 " setValue\n"
202 " The input file format required by the setValue command is similar\n"
203 " to the one obtained from regedit.exe export option. The only\n"
204 " difference is that multi line values are not supported, the\n"
205 " value data must be on a single line.\n"
206 "\n"
207 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
208 " \"Value1\"=\"Data1\"\n"
209 " \"Value2\"=\"Data2\"\n"
210 " \"Valuen\"=\"Datan\"\n"
211 " ...\n"
212 "\n"
213 " queryValue\n"
214 " The input file format required by the queryValue command is\n"
215 " similar to the one required by setValue. The only\n"
216 " difference is that you only provide the value name.\n"
217 "\n"
218 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
219 " \"Value1\"\n"
220 " \"Value2\"\n"
221 " \"Valuen\"\n"
222 " ...\n"
223 " registerDLL\n"
224 " The input file format is a list of DLLs to register\n"
225 "\n"
226 " unregisterDLL\n"
227 " The input file format is a list of DLLs to unregister\n"
228 " February 1999.\n"
232 /******************************************************************************
233 * This function returns the HKEY associated with the data type encoded in the
234 * value. It modify the input parameter (key value) in order to skip this
235 * "now useless" data type information.
237 HKEY getDataType(LPSTR *lpValue)
239 INT counter = 0;
240 DWORD dwReturn = REG_SZ;
242 for (; counter < LAST_TYPE_MAP; counter++)
244 LONG len = strlen(typeMap[counter].mask);
245 if ( strncasecmp( *lpValue, typeMap[counter].mask, len) == IDENTICAL)
248 * We found it, modify the value's pointer in order to skip the data
249 * type identifier, set the return value and exit the loop.
251 (*lpValue) += len;
252 dwReturn = typeMap[counter].dataType;
253 break;
257 return dwReturn;
259 /******************************************************************************
260 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
261 * after the first '\' and end before the ']'
263 LPSTR getRegKeyName(LPSTR lpLine)
265 LPSTR keyNameBeg = NULL;
266 LPSTR keyNameEnd = NULL;
267 char lpLineCopy[KEY_MAX_LEN];
269 if (lpLine == NULL)
270 return NULL;
272 strcpy(lpLineCopy, lpLine);
274 keyNameBeg = strstr(lpLineCopy, "\\"); /* The key name start by '\' */
275 keyNameBeg++; /* but is not part of the key name */
276 keyNameEnd = strstr(lpLineCopy, "]"); /* The key name end by ']' */
277 *keyNameEnd = '\0'; /* Isolate the key name */
279 currentKeyName = HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg)+1);
280 if (currentKeyName != NULL)
281 strcpy(currentKeyName, keyNameBeg);
283 return currentKeyName;
286 /******************************************************************************
287 * Extracts from a [HKEY/some/key/path] type of line the key class (what
288 * starts after the '[' and end before the first '\'
290 static HKEY getRegClass(LPSTR lpClass)
292 LPSTR classNameEnd;
293 LPSTR classNameBeg;
295 char lpClassCopy[KEY_MAX_LEN];
297 if (lpClass == NULL)
298 return ERROR_INVALID_PARAMETER;
300 strcpy(lpClassCopy, lpClass);
302 classNameEnd = strstr(lpClassCopy, "\\"); /* The class name end by '\' */
303 *classNameEnd = '\0'; /* Isolate the class name */
304 classNameBeg = &lpClassCopy[1]; /* Skip the '[' */
306 if (strcmp( classNameBeg, "HKEY_LOCAL_MACHINE") == IDENTICAL )
307 return HKEY_LOCAL_MACHINE;
308 else if (strcmp( classNameBeg, "HKEY_USERS") == IDENTICAL )
309 return HKEY_USERS;
310 else if (strcmp( classNameBeg, "HKEY_CLASSES_ROOT") == IDENTICAL )
311 return HKEY_CLASSES_ROOT;
312 else if (strcmp( classNameBeg, "HKEY_CURRENT_CONFIG") == IDENTICAL )
313 return HKEY_CURRENT_CONFIG;
314 else if (strcmp( classNameBeg, "HKEY_CURRENT_USER") == IDENTICAL )
315 return HKEY_CURRENT_USER;
316 else
317 return ERROR_INVALID_PARAMETER;
320 /******************************************************************************
321 * Returns an allocated buffer with a cleaned copy (removed the surrounding
322 * dbl quotes) of the passed value.
324 static LPSTR getArg( LPSTR arg)
326 LPSTR tmp = NULL;
327 ULONG len;
329 if (arg == NULL)
330 return NULL;
333 * Get rid of surrounding quotes
335 len = strlen(arg);
337 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
338 if( arg[0] == '\"' ) arg++;
340 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
341 strcpy(tmp, arg);
343 return tmp;
346 /******************************************************************************
347 * Returns the index in the commands array of the command to process.
349 static INT getCommand(LPSTR commandName)
351 INT count;
352 for (count=0; count < COMMAND_COUNT; count++)
353 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
354 return count;
356 return COMMAND_NOT_FOUND;
359 /******************************************************************************
360 * Converts a hex representation of a DWORD into a DWORD.
362 static DWORD convertHexToDWord(char *str, BYTE *buf)
364 char *s = str; /* Pointer to current */
365 char *b = buf; /* Pointer to result */
366 ULONG strPos = 0;
368 memset(buf, 0, 4);
370 while (strPos < 4) /* 8 byte in a DWORD */
372 char xbuf[3];
373 char wc;
375 memcpy(xbuf,s,2); xbuf[2]='\0';
376 sscanf(xbuf,"%02x",(UINT*)&wc);
377 *b++ =(unsigned char)wc;
379 s+=2;
380 strPos+=1;
383 return 4; /* always 4 byte for the word */
386 /******************************************************************************
387 * Converts a hex buffer into a hex comma separated values
389 static char* convertHexToHexCSV(BYTE *buf, ULONG bufLen)
391 char* str;
392 char* ptrStr;
393 BYTE* ptrBuf;
395 ULONG current = 0;
397 str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2);
398 memset(str, 0, (bufLen+1)*2);
399 ptrStr = str; /* Pointer to result */
400 ptrBuf = buf; /* Pointer to current */
402 while (current < bufLen)
404 BYTE bCur = ptrBuf[current++];
405 char res[3];
407 sprintf(res, "%02x", (unsigned int)*&bCur);
408 strcat(str, res);
409 strcat(str, ",");
412 /* Get rid of the last comma */
413 str[strlen(str)-1] = '\0';
414 return str;
417 /******************************************************************************
418 * Converts a hex buffer into a DWORD string
420 static char* convertHexToDWORDStr(BYTE *buf, ULONG bufLen)
422 char* str;
423 char* ptrStr;
424 BYTE* ptrBuf;
426 ULONG current = 0;
428 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
429 memset(str, 0, (bufLen*2)+1);
430 ptrStr = str; /* Pointer to result */
431 ptrBuf = buf; /* Pointer to current */
433 while (current < bufLen)
435 BYTE bCur = ptrBuf[current++];
436 char res[3];
438 sprintf(res, "%02x", (unsigned int)*&bCur);
439 strcat(str, res);
442 /* Get rid of the last comma */
443 return str;
445 /******************************************************************************
446 * Converts a hex comma separated values list into a hex list.
448 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
450 char *s = str; /* Pointer to current */
451 char *b = buf; /* Pointer to result */
453 ULONG strLen = strlen(str);
454 ULONG strPos = 0;
455 DWORD byteCount = 0;
457 memset(buf, 0, bufLen);
460 * warn the user if we are here with a string longer than 2 bytes that does
461 * not contains ",". It is more likely because the data is invalid.
463 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
464 printf("regapi: WARNING converting CSV hex stream with no comma, "
465 "input data seems invalid.\n");
467 while (strPos < strLen)
469 char xbuf[3];
470 char wc;
472 memcpy(xbuf,s,2); xbuf[3]='\0';
473 sscanf(xbuf,"%02x",(UINT*)&wc);
474 *b++ =(unsigned char)wc;
476 s+=3;
477 strPos+=3;
478 byteCount++;
481 return byteCount;
485 /******************************************************************************
486 * Sets the value in argv[0] to the data in argv[1] for the currently
487 * opened key.
489 static HRESULT setValue(LPSTR *argv)
491 HRESULT hRes;
492 DWORD dwSize = KEY_MAX_LEN;
493 DWORD dwType = 0;
494 DWORD dwDataType;
496 LPSTR lpsCurrentValue;
498 LPSTR keyValue = argv[0];
499 LPSTR keyData = argv[1];
501 /* Make some checks */
502 if ( (keyValue == NULL) || (keyData == NULL) )
503 return ERROR_INVALID_PARAMETER;
505 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
507 * Default registry values are encoded in the input stream as '@' but as
508 * blank in the wine registry.
510 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
511 keyValue[0] = '\0';
513 /* Get the data type stored into the value field */
514 dwDataType = getDataType(&keyData);
516 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
517 hRes = RegQueryValueExA(
518 currentKeyHandle,
519 keyValue,
520 NULL,
521 &dwType,
522 (LPBYTE)lpsCurrentValue,
523 &dwSize);
525 while(hRes==ERROR_MORE_DATA){
526 dwSize+=KEY_MAX_LEN;
527 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
528 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
531 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
532 ( bForce )) /* -force option */
534 LPBYTE lpbData;
535 BYTE convert[KEY_MAX_LEN];
536 DWORD dwLen;
538 if ( dwDataType == REG_SZ ) /* no convertion for string */
540 dwLen = strlen(keyData);
541 lpbData = keyData;
543 else if (dwDataType == REG_DWORD) /* Convert the dword types */
545 dwLen = convertHexToDWord(keyData, convert);
546 lpbData = convert;
548 else /* Convert the hexadecimal types */
550 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
551 lpbData = convert;
554 hRes = RegSetValueEx(
555 currentKeyHandle,
556 keyValue,
557 0, /* Reserved */
558 dwDataType,
559 lpbData,
560 dwLen);
562 else
564 /* return the current value data into argv[1] */
565 if (argv[1] != NULL)
567 HeapFree(GetProcessHeap(), 0, argv[1]);
568 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
570 if ( argv[1] != NULL ) {
571 strncpy(argv[1], lpsCurrentValue, dwSize);
572 argv[1][dwSize]='\0';
576 return KEY_VALUE_ALREADY_SET;
578 return hRes;
582 /******************************************************************************
583 * Open the key
585 static HRESULT openKey( LPSTR stdInput)
587 DWORD dwDisp;
588 HRESULT hRes;
590 /* Sanity checks */
591 if (stdInput == NULL)
592 return ERROR_INVALID_PARAMETER;
594 /* Get the registry class */
595 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
596 if (currentKeyClass == ERROR_INVALID_PARAMETER)
597 return ERROR_INVALID_PARAMETER;
599 /* Get the key name */
600 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
601 if (currentKeyName == NULL)
602 return ERROR_INVALID_PARAMETER;
604 hRes = RegCreateKeyEx(
605 currentKeyClass, /* Class */
606 currentKeyName, /* Sub Key */
607 0, /* MUST BE 0 */
608 NULL, /* object type */
609 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
610 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
611 NULL, /* security attribute */
612 &currentKeyHandle, /* result */
613 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
614 REG_OPENED_EXISTING_KEY */
616 if (hRes == ERROR_SUCCESS)
617 bTheKeyIsOpen = TRUE;
619 return hRes;
622 /******************************************************************************
623 * This function is a wrapper arround the setValue function. It prepares the
624 * land and clean the area once completed.
626 static void processSetValue(LPSTR cmdline)
628 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
630 LPSTR token = NULL; /* current token analized */
631 ULONG argCounter = 0; /* counter of args */
632 INT counter;
633 HRESULT hRes = 0;
636 * Init storage and parse the line
638 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
639 argv[counter]=NULL;
641 while( (token = strsep(&cmdline, setValueDelim[argCounter])) != NULL )
643 argv[argCounter++] = getArg(token);
645 if (argCounter == SET_VALUE_MAX_ARGS)
646 break; /* Stop processing args no matter what */
649 hRes = setValue(argv);
650 if ( hRes == ERROR_SUCCESS )
651 printf(
652 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
653 argv[0],
654 argv[1],
655 currentKeyName);
657 else if ( hRes == KEY_VALUE_ALREADY_SET )
658 printf(
659 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
660 argv[0],
661 argv[1],
662 currentKeyName);
664 else
665 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
666 currentKeyName,
667 argv[0],
668 argv[1]);
671 * Do some cleanup
673 for (counter=0; counter<argCounter; counter++)
674 if (argv[counter] != NULL)
675 HeapFree(GetProcessHeap(), 0, argv[counter]);
678 /******************************************************************************
679 * This function is a wrapper arround the queryValue function. It prepares the
680 * land and clean the area once completed.
682 static void processQueryValue(LPSTR cmdline)
684 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
685 LPSTR token = NULL; /* current token analized */
686 ULONG argCounter = 0; /* counter of args */
687 INT counter;
688 HRESULT hRes = 0;
689 LPSTR keyValue = NULL;
690 LPSTR lpsRes = NULL;
693 * Init storage and parse the line
695 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
696 argv[counter]=NULL;
698 while( (token = strsep(&cmdline, queryValueDelim[argCounter])) != NULL )
700 argv[argCounter++] = getArg(token);
702 if (argCounter == QUERY_VALUE_MAX_ARGS)
703 break; /* Stop processing args no matter what */
706 /* The value we look for is the first token on the line */
707 if ( argv[0] == NULL )
708 return; /* SHOULD NOT OCCURS */
709 else
710 keyValue = argv[0];
712 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
714 LONG lLen = KEY_MAX_LEN;
715 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
717 * We need to query the key default value
719 hRes = RegQueryValue(
720 currentKeyHandle,
721 currentKeyName,
722 (LPBYTE)lpsData,
723 &lLen);
725 if (hRes==ERROR_MORE_DATA) {
726 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
727 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
730 if (hRes == ERROR_SUCCESS)
732 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
733 strncpy(lpsRes, lpsData, lLen);
734 lpsRes[lLen-1]='\0';
737 else
739 DWORD dwLen = KEY_MAX_LEN;
740 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
741 DWORD dwType;
743 * We need to query a specific value for the key
745 hRes = RegQueryValueEx(
746 currentKeyHandle,
747 keyValue,
749 &dwType,
750 (LPBYTE)lpbData,
751 &dwLen);
753 if (hRes==ERROR_MORE_DATA) {
754 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
755 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
758 if (hRes == ERROR_SUCCESS)
761 * Convert the returned data to a displayable format
763 switch ( dwType )
765 case REG_SZ:
766 case REG_EXPAND_SZ:
768 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
769 strncpy(lpsRes, lpbData, dwLen);
770 lpsRes[dwLen-1]='\0';
771 break;
773 case REG_DWORD:
775 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
776 break;
778 default:
780 lpsRes = convertHexToHexCSV(lpbData, dwLen);
781 break;
786 HeapFree(GetProcessHeap(), 0, lpbData);
790 if ( hRes == ERROR_SUCCESS )
791 printf(
792 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
793 keyValue,
794 lpsRes,
795 currentKeyName);
797 else
798 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
799 keyValue,
800 currentKeyName);
803 * Do some cleanup
805 for (counter=0; counter<argCounter; counter++)
806 if (argv[counter] != NULL)
807 HeapFree(GetProcessHeap(), 0, argv[counter]);
809 if (lpsRes != NULL)
810 HeapFree(GetProcessHeap(), 0, lpsRes);
814 /******************************************************************************
815 * Close the currently opened key.
817 static void closeKey()
819 RegCloseKey(currentKeyHandle);
821 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
823 bTheKeyIsOpen = FALSE;
825 currentKeyName = NULL;
826 currentKeyClass = 0;
827 currentKeyHandle = 0;
830 /******************************************************************************
831 * This funtion is the main entry point to the setValue type of action. It
832 * receives the currently read line and dispatch the work depending on the
833 * context.
835 static void doSetValue(LPSTR stdInput)
838 * We encoutered the end of the file, make sure we
839 * close the opened key and exit
841 if (stdInput == NULL)
843 if (bTheKeyIsOpen != FALSE)
844 closeKey();
846 return;
849 if ( stdInput[0] == '[') /* We are reading a new key */
851 if ( bTheKeyIsOpen != FALSE )
852 closeKey(); /* Close the previous key before */
854 if ( openKey(stdInput) != ERROR_SUCCESS )
855 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
857 else if( ( bTheKeyIsOpen ) &&
858 (( stdInput[0] == '@') || /* reading a default @=data pair */
859 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
861 processSetValue(stdInput);
863 else /* since we are assuming that the */
864 { /* file format is valid we must */
865 if ( bTheKeyIsOpen ) /* be reading a blank line which */
866 closeKey(); /* indicate end of this key processing */
870 /******************************************************************************
871 * This funtion is the main entry point to the queryValue type of action. It
872 * receives the currently read line and dispatch the work depending on the
873 * context.
875 static void doQueryValue(LPSTR stdInput) {
877 * We encoutered the end of the file, make sure we
878 * close the opened key and exit
880 if (stdInput == NULL)
882 if (bTheKeyIsOpen != FALSE)
883 closeKey();
885 return;
888 if ( stdInput[0] == '[') /* We are reading a new key */
890 if ( bTheKeyIsOpen != FALSE )
891 closeKey(); /* Close the previous key before */
893 if ( openKey(stdInput) != ERROR_SUCCESS )
894 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
896 else if( ( bTheKeyIsOpen ) &&
897 (( stdInput[0] == '@') || /* reading a default @=data pair */
898 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
900 processQueryValue(stdInput);
902 else /* since we are assuming that the */
903 { /* file format is valid we must */
904 if ( bTheKeyIsOpen ) /* be reading a blank line which */
905 closeKey(); /* indicate end of this key processing */
909 /******************************************************************************
910 * This funtion is the main entry point to the deletetValue type of action. It
911 * receives the currently read line and dispatch the work depending on the
912 * context.
914 static void doDeleteValue(LPSTR line) {
915 printf ("regapi: deleteValue not yet implemented\n");
917 /******************************************************************************
918 * This funtion is the main entry point to the deleteKey type of action. It
919 * receives the currently read line and dispatch the work depending on the
920 * context.
922 static void doDeleteKey(LPSTR line) {
923 printf ("regapi: deleteKey not yet implemented\n");
925 /******************************************************************************
926 * This funtion is the main entry point to the createKey type of action. It
927 * receives the currently read line and dispatch the work depending on the
928 * context.
930 static void doCreateKey(LPSTR line) {
931 printf ("regapi: createKey not yet implemented\n");
934 /******************************************************************************
935 * This funtion is the main entry point to the registerDLL action. It
936 * receives the currently read line, then loads and registers the requested DLLs
938 static void doRegisterDLL(LPSTR stdInput) {
939 HMODULE theLib = 0;
940 UINT retVal = 0;
942 /* Check for valid input */
943 if (stdInput == NULL)
944 return;
946 /* Load and register the library, then free it */
947 theLib = LoadLibrary(stdInput);
948 if (theLib)
950 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
951 if (lpfnDLLRegProc)
952 retVal = (*lpfnDLLRegProc)();
953 else
954 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput);
956 if (retVal != S_OK)
957 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal, stdInput);
959 FreeLibrary(theLib);
961 else
963 printf("regapi: Could not load DLL '%s'.\n", stdInput);
967 /******************************************************************************
968 * This funtion is the main entry point to the unregisterDLL action. It
969 * receives the currently read line, then loads and unregisters the requested DLLs
971 static void doUnregisterDLL(LPSTR stdInput) {
972 HMODULE theLib = 0;
973 UINT retVal = 0;
975 /* Check for valid input */
976 if (stdInput == NULL)
977 return;
979 /* Load and unregister the library, then free it */
980 theLib = LoadLibrary(stdInput);
981 if (theLib)
983 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
984 if (lpfnDLLRegProc)
985 retVal = (*lpfnDLLRegProc)();
986 else
987 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput);
989 if (retVal != S_OK)
990 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal, stdInput);
992 FreeLibrary(theLib);
994 else
996 printf("regapi: Could not load DLL '%s'.\n", stdInput);
1000 /******************************************************************************
1001 * MAIN - The main simply validate the first parameter (command to perform)
1002 * It then read the STDIN lines by lines forwarding their processing
1003 * to the appropriate method.
1005 int PASCAL WinMain (HANDLE inst, HANDLE prev, LPSTR cmdline, int show)
1007 LPSTR token = NULL; /* current token analized */
1008 LPSTR stdInput = NULL; /* line read from stdin */
1009 INT cmdIndex = -1; /* index of the command in array */
1010 LPSTR nextLine = NULL;
1011 ULONG currentSize = STDIN_MAX_LEN;
1013 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1014 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1016 if (stdInput == NULL || nextLine== NULL)
1017 return NOT_ENOUGH_MEMORY;
1020 * get the command, should be the first arg (modify cmdLine)
1022 token = strsep(&cmdline, " ");
1023 if (token != NULL)
1025 cmdIndex = getCommand(token);
1026 if (cmdIndex == COMMAND_NOT_FOUND)
1028 printf("regapi: Command \"%s\" is not supported.\n", token);
1029 printf(helpText);
1030 return COMMAND_NOT_SUPPORTED;
1033 else
1035 printf(
1036 "regapi: The first item on the command line must be the command name.\n");
1037 printf(helpText);
1038 return COMMAND_NOT_SUPPORTED;
1042 * check to see weather we force the action
1043 * (meaning differ depending on the command performed)
1045 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
1046 if ( strstr(cmdline, "-force") != NULL )
1047 bForce = TRUE;
1049 printf("Processing stdin...\n");
1051 while ( TRUE )
1054 * read a line
1056 ULONG curSize=STDIN_MAX_LEN;
1057 char* s=NULL;
1059 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
1060 fseek(stdin,-curSize,SEEK_CUR+1);
1061 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
1064 * Make some handy generic stuff here...
1066 if ( stdInput != NULL )
1068 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
1070 if( stdInput[0] == '#' ) /* this is a comment, skip */
1071 continue;
1073 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1074 /* that this line is not complete and we have to get */
1075 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
1077 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1079 nextLine[strlen(nextLine)-1] = '\0';
1081 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1083 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1085 currentSize+=STDIN_MAX_LEN;
1088 strcat(stdInput,nextLine+2);
1093 * We process every lines even the NULL (last) line, to indicate the
1094 * end of the processing to the specific process.
1096 commandAPIs[cmdIndex](stdInput);
1098 if (stdInput == NULL) /* EOF encountered */
1099 break;
1102 #if 0
1104 * Save the registry only if it was modified
1106 if ( commandSaveRegistry[cmdIndex] != FALSE )
1107 SHELL_SaveRegistry();
1108 #endif
1109 HeapFree(GetProcessHeap(), 0, nextLine);
1111 HeapFree(GetProcessHeap(), 0, stdInput);
1113 return SUCCESS;