Removed shell.h. Cleaned up the nested includes mess in wine/obj_*.h.
[wine.git] / programs / regapi / regapi.c
blob9c8e91023b5cd74712357c450fd17d809f19c2fa
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>
18 /******************************************************************************
19 * Defines and consts
21 #define IDENTICAL 0
22 #define COMMAND_COUNT 7
24 #define KEY_MAX_LEN 1024
25 #define STDIN_MAX_LEN 2048
27 /* Return values */
28 #define COMMAND_NOT_FOUND -1
29 #define SUCCESS 0
30 #define NOT_ENOUGH_MEMORY 1
31 #define KEY_VALUE_ALREADY_SET 2
32 #define COMMAND_NOT_SUPPORTED 3
34 /* Generic global */
35 static BOOL bForce = FALSE; /* Is set to TRUE when -force is
36 passed on the command line */
38 /* Globals used by the api setValue, queryValue */
39 static LPSTR currentKeyName = NULL;
40 static HKEY currentKeyClass = 0;
41 static HKEY currentKeyHandle = 0;
42 static BOOL bTheKeyIsOpen = FALSE;
44 /* Delimiters used to parse the "value"="data" pair for setValue*/
45 #define SET_VALUE_MAX_ARGS 2
46 /* Delimiters used to parse the "value" to query queryValue*/
47 #define QUERY_VALUE_MAX_ARGS 1
49 static const char *setValueDelim[SET_VALUE_MAX_ARGS] = {"=", ""};
50 static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS] = {""};
52 /* Array used to extract the data type from a string in getDataType. */
53 typedef struct tagDataTypeMap
55 char mask[15];
56 DWORD dataType;
57 } dataTypeMap;
59 static const dataTypeMap typeMap[] =
61 {"hex:", REG_BINARY},/* could be REG_NONE (?) */
62 {"dword:", REG_DWORD},
63 {"hex(0):", REG_NONE},
64 {"hex(1):", REG_SZ},
65 {"hex(2):", REG_EXPAND_SZ},
66 {"hex(3):", REG_BINARY},
67 {"hex(4):", REG_DWORD},
68 {"hex(5):", REG_DWORD_BIG_ENDIAN},
69 {"hex(6):", REG_LINK},
70 {"hex(7):", REG_MULTI_SZ},
71 {"hex(8):", REG_RESOURCE_LIST},
72 {"hex(9):", REG_FULL_RESOURCE_DESCRIPTOR},
73 {"hex(10):", REG_RESOURCE_REQUIREMENTS_LIST},
74 {"hex(80000000):", 0x80000000},
75 {"hex(80000001):", 0x80000001},
76 {"hex(80000002):", 0x80000002},
77 {"hex(80000003):", 0x80000003},
78 {"hex(80000004):", 0x80000004},
79 {"hex(80000005):", 0x80000005},
80 {"hex(80000006):", 0x80000006},
81 {"hex(80000007):", 0x80000007},
82 {"hex(80000008):", 0x80000008},
83 {"hex(80000009):", 0x80000000},
84 {"hex(8000000a):", 0x8000000A}
86 const static int LAST_TYPE_MAP = sizeof(typeMap)/sizeof(dataTypeMap);
89 /*
90 * Forward declaration
92 typedef void (*commandAPI)(LPSTR lpsLine);
94 static void doSetValue(LPSTR lpsLine);
95 static void doDeleteValue(LPSTR lpsLine);
96 static void doCreateKey(LPSTR lpsLine);
97 static void doDeleteKey(LPSTR lpsLine);
98 static void doQueryValue(LPSTR lpsLine);
99 static void doRegisterDLL(LPSTR lpsLine);
100 static void doUnregisterDLL(LPSTR lpsLine);
103 * current supported api
105 static const char* commandNames[COMMAND_COUNT] = {
106 "setValue",
107 "deleteValue",
108 "createKey",
109 "deleteKey",
110 "queryValue",
111 "registerDLL",
112 "unregisterDLL"
116 * Pointers to processing entry points
118 static const commandAPI commandAPIs[COMMAND_COUNT] = {
119 doSetValue,
120 doDeleteValue,
121 doCreateKey,
122 doDeleteKey,
123 doQueryValue,
124 doRegisterDLL,
125 doUnregisterDLL
129 * This array controls the registry saving needs at the end of the process
131 static const BOOL commandSaveRegistry[COMMAND_COUNT] = {
132 TRUE,
133 TRUE,
134 TRUE,
135 TRUE,
136 FALSE,
137 TRUE,
138 TRUE
142 * Generic prototyes
144 static DWORD getDataType(LPSTR *lpValue);
145 static LPSTR getRegKeyName(LPSTR lpLine);
146 static HKEY getRegClass(LPSTR lpLine);
147 static LPSTR getArg(LPSTR arg);
148 static INT getCommand(LPSTR commandName);
149 static DWORD convertHexToDWord(char *str, BYTE *buf);
150 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
151 static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
152 static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
153 static HRESULT openKey(LPSTR stdInput);
154 static void closeKey();
157 * api setValue prototypes
159 static void processSetValue(LPSTR cmdline);
160 static HRESULT setValue(LPSTR *argv);
163 * api queryValue prototypes
165 static void processQueryValue(LPSTR cmdline);
168 * Help Text displayed when invalid parameters are provided
170 static char helpText[] =
171 "NAME\n"
172 " regapi - provide a command line interface to the wine registry.\n"
173 "\n"
174 "SYNOPSIS\n"
175 " regapi commandName [-force] < file\n"
176 "\n"
177 "DESCRIPTION\n"
178 " regapi allows editing the wine registry. It processes the given\n"
179 " commandName for every line in the stdin data stream. Input data\n"
180 " format may vary depending on the commandName see INPUT FILE FORMAT.\n"
181 "\n"
182 "OPTIONS\n"
183 " commandName\n"
184 " Instruct regapi about what action to perform on the data stream.\n"
185 " Currently, only setValue and queryValue are supported and\n"
186 " implemented.\n"
187 "\n"
188 " -force\n"
189 " When provided the action will be performed anyway. This may\n"
190 " have a different meaning depending on the context. For example,\n"
191 " when providing -force to setValue, the value is set even if it\n"
192 " was previously set to another value.\n"
193 "\n"
194 " < file\n"
195 " STDIN channel, provide a file name with line of the appropriate\n"
196 " format.\n"
197 "\n"
198 "INPUT FILE FORMAT\n"
199 "\n"
200 " setValue\n"
201 " The input file format required by the setValue command is similar\n"
202 " to the one obtained from regedit.exe export option. The only\n"
203 " difference is that multi line values are not supported, the\n"
204 " value data must be on a single line.\n"
205 "\n"
206 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
207 " \"Value1\"=\"Data1\"\n"
208 " \"Value2\"=\"Data2\"\n"
209 " \"Valuen\"=\"Datan\"\n"
210 " ...\n"
211 "\n"
212 " queryValue\n"
213 " The input file format required by the queryValue command is\n"
214 " similar to the one required by setValue. The only\n"
215 " difference is that you only provide the value name.\n"
216 "\n"
217 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
218 " \"Value1\"\n"
219 " \"Value2\"\n"
220 " \"Valuen\"\n"
221 " ...\n"
222 " registerDLL\n"
223 " The input file format is a list of DLLs to register\n"
224 "\n"
225 " unregisterDLL\n"
226 " The input file format is a list of DLLs to unregister\n"
227 " February 1999.\n"
231 /******************************************************************************
232 * This function returns the HKEY associated with the data type encoded in the
233 * value. It modifies the input parameter (key value) in order to skip this
234 * "now useless" data type information.
236 DWORD getDataType(LPSTR *lpValue)
238 INT counter = 0;
239 DWORD dwReturn = REG_SZ;
241 for (; counter < LAST_TYPE_MAP; counter++)
243 LONG len = strlen(typeMap[counter].mask);
244 if ( strncasecmp( *lpValue, typeMap[counter].mask, len) == IDENTICAL)
247 * We found it, modify the value's pointer in order to skip the data
248 * type identifier, set the return value and exit the loop.
250 (*lpValue) += len;
251 dwReturn = typeMap[counter].dataType;
252 break;
256 return dwReturn;
258 /******************************************************************************
259 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
260 * after the first '\' and end before the ']'
262 LPSTR getRegKeyName(LPSTR lpLine)
264 LPSTR keyNameBeg = NULL;
265 LPSTR keyNameEnd = NULL;
266 char lpLineCopy[KEY_MAX_LEN];
268 if (lpLine == NULL)
269 return NULL;
271 strcpy(lpLineCopy, lpLine);
273 keyNameBeg = strstr(lpLineCopy, "\\"); /* The key name start by '\' */
274 keyNameBeg++; /* but is not part of the key name */
275 keyNameEnd = strstr(lpLineCopy, "]"); /* The key name end by ']' */
276 *keyNameEnd = '\0'; /* Isolate the key name */
278 currentKeyName = HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg)+1);
279 if (currentKeyName != NULL)
280 strcpy(currentKeyName, keyNameBeg);
282 return currentKeyName;
285 /******************************************************************************
286 * Extracts from a [HKEY/some/key/path] type of line the key class (what
287 * starts after the '[' and ends before the first '\'
289 static HKEY getRegClass(LPSTR lpClass)
291 LPSTR classNameEnd;
292 LPSTR classNameBeg;
294 char lpClassCopy[KEY_MAX_LEN];
296 if (lpClass == NULL)
297 return (HKEY)ERROR_INVALID_PARAMETER;
299 strcpy(lpClassCopy, lpClass);
301 classNameEnd = strstr(lpClassCopy, "\\"); /* The class name end by '\' */
302 *classNameEnd = '\0'; /* Isolate the class name */
303 classNameBeg = &lpClassCopy[1]; /* Skip the '[' */
305 if (strcmp( classNameBeg, "HKEY_LOCAL_MACHINE") == IDENTICAL )
306 return HKEY_LOCAL_MACHINE;
307 else if (strcmp( classNameBeg, "HKEY_USERS") == IDENTICAL )
308 return HKEY_USERS;
309 else if (strcmp( classNameBeg, "HKEY_CLASSES_ROOT") == IDENTICAL )
310 return HKEY_CLASSES_ROOT;
311 else if (strcmp( classNameBeg, "HKEY_CURRENT_CONFIG") == IDENTICAL )
312 return HKEY_CURRENT_CONFIG;
313 else if (strcmp( classNameBeg, "HKEY_CURRENT_USER") == IDENTICAL )
314 return HKEY_CURRENT_USER;
315 else
316 return (HKEY)ERROR_INVALID_PARAMETER;
319 /******************************************************************************
320 * Returns an allocated buffer with a cleaned copy (removed the surrounding
321 * dbl quotes) of the passed value.
323 static LPSTR getArg( LPSTR arg)
325 LPSTR tmp = NULL;
326 ULONG len;
328 if (arg == NULL)
329 return NULL;
332 * Get rid of surrounding quotes
334 len = strlen(arg);
336 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
337 if( arg[0] == '\"' ) arg++;
339 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
340 strcpy(tmp, arg);
342 return tmp;
345 /******************************************************************************
346 * Returns the index in the commands array of the command to process.
348 static INT getCommand(LPSTR commandName)
350 INT count;
351 for (count=0; count < COMMAND_COUNT; count++)
352 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
353 return count;
355 return COMMAND_NOT_FOUND;
358 /******************************************************************************
359 * Converts a hex representation of a DWORD into a DWORD.
361 static DWORD convertHexToDWord(char *str, BYTE *buf)
363 char *s = str; /* Pointer to current */
364 char *b = buf; /* Pointer to result */
365 ULONG strPos = 0;
367 memset(buf, 0, 4);
369 while (strPos < 4) /* 8 byte in a DWORD */
371 char xbuf[3];
372 char wc;
374 memcpy(xbuf,s,2); xbuf[2]='\0';
375 sscanf(xbuf,"%02x",(UINT*)&wc);
376 *b++ =(unsigned char)wc;
378 s+=2;
379 strPos+=1;
382 return 4; /* always 4 byte for the word */
385 /******************************************************************************
386 * Converts a hex buffer into a hex comma separated values
388 static char* convertHexToHexCSV(BYTE *buf, ULONG bufLen)
390 char* str;
391 char* ptrStr;
392 BYTE* ptrBuf;
394 ULONG current = 0;
396 str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2);
397 memset(str, 0, (bufLen+1)*2);
398 ptrStr = str; /* Pointer to result */
399 ptrBuf = buf; /* Pointer to current */
401 while (current < bufLen)
403 BYTE bCur = ptrBuf[current++];
404 char res[3];
406 sprintf(res, "%02x", (unsigned int)*&bCur);
407 strcat(str, res);
408 strcat(str, ",");
411 /* Get rid of the last comma */
412 str[strlen(str)-1] = '\0';
413 return str;
416 /******************************************************************************
417 * Converts a hex buffer into a DWORD string
419 static char* convertHexToDWORDStr(BYTE *buf, ULONG bufLen)
421 char* str;
422 char* ptrStr;
423 BYTE* ptrBuf;
425 ULONG current = 0;
427 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
428 memset(str, 0, (bufLen*2)+1);
429 ptrStr = str; /* Pointer to result */
430 ptrBuf = buf; /* Pointer to current */
432 while (current < bufLen)
434 BYTE bCur = ptrBuf[current++];
435 char res[3];
437 sprintf(res, "%02x", (unsigned int)*&bCur);
438 strcat(str, res);
441 /* Get rid of the last comma */
442 return str;
444 /******************************************************************************
445 * Converts a hex comma separated values list into a hex list.
447 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
449 char *s = str; /* Pointer to current */
450 char *b = buf; /* Pointer to result */
452 ULONG strLen = strlen(str);
453 ULONG strPos = 0;
454 DWORD byteCount = 0;
456 memset(buf, 0, bufLen);
459 * warn the user if we are here with a string longer than 2 bytes that does
460 * not contains ",". It is more likely because the data is invalid.
462 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
463 printf("regapi: WARNING converting CSV hex stream with no comma, "
464 "input data seems invalid.\n");
466 while (strPos < strLen)
468 char xbuf[3];
469 char wc;
471 memcpy(xbuf,s,2); xbuf[3]='\0';
472 sscanf(xbuf,"%02x",(UINT*)&wc);
473 *b++ =(unsigned char)wc;
475 s+=3;
476 strPos+=3;
477 byteCount++;
480 return byteCount;
484 /******************************************************************************
485 * Sets the value in argv[0] to the data in argv[1] for the currently
486 * opened key.
488 static HRESULT setValue(LPSTR *argv)
490 HRESULT hRes;
491 DWORD dwSize = KEY_MAX_LEN;
492 DWORD dwType = 0;
493 DWORD dwDataType;
495 LPSTR lpsCurrentValue;
497 LPSTR keyValue = argv[0];
498 LPSTR keyData = argv[1];
500 /* Make some checks */
501 if ( (keyValue == NULL) || (keyData == NULL) )
502 return ERROR_INVALID_PARAMETER;
504 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
506 * Default registry values are encoded in the input stream as '@' but as
507 * blank in the wine registry.
509 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
510 keyValue[0] = '\0';
512 /* Get the data type stored into the value field */
513 dwDataType = getDataType(&keyData);
515 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
516 hRes = RegQueryValueExA(
517 currentKeyHandle,
518 keyValue,
519 NULL,
520 &dwType,
521 (LPBYTE)lpsCurrentValue,
522 &dwSize);
524 while(hRes==ERROR_MORE_DATA){
525 dwSize+=KEY_MAX_LEN;
526 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
527 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
530 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
531 ( bForce )) /* -force option */
533 LPBYTE lpbData;
534 BYTE convert[KEY_MAX_LEN];
535 DWORD dwLen;
537 if ( dwDataType == REG_SZ ) /* no convertion for string */
539 dwLen = strlen(keyData);
540 lpbData = keyData;
542 else if (dwDataType == REG_DWORD) /* Convert the dword types */
544 dwLen = convertHexToDWord(keyData, convert);
545 lpbData = convert;
547 else /* Convert the hexadecimal types */
549 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
550 lpbData = convert;
553 hRes = RegSetValueEx(
554 currentKeyHandle,
555 keyValue,
556 0, /* Reserved */
557 dwDataType,
558 lpbData,
559 dwLen);
561 else
563 /* return the current value data into argv[1] */
564 if (argv[1] != NULL)
566 HeapFree(GetProcessHeap(), 0, argv[1]);
567 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
569 if ( argv[1] != NULL ) {
570 strncpy(argv[1], lpsCurrentValue, dwSize);
571 argv[1][dwSize]='\0';
575 return KEY_VALUE_ALREADY_SET;
577 return hRes;
581 /******************************************************************************
582 * Open the key
584 static HRESULT openKey( LPSTR stdInput)
586 DWORD dwDisp;
587 HRESULT hRes;
589 /* Sanity checks */
590 if (stdInput == NULL)
591 return ERROR_INVALID_PARAMETER;
593 /* Get the registry class */
594 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
595 if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
596 return (HRESULT)ERROR_INVALID_PARAMETER;
598 /* Get the key name */
599 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
600 if (currentKeyName == NULL)
601 return ERROR_INVALID_PARAMETER;
603 hRes = RegCreateKeyEx(
604 currentKeyClass, /* Class */
605 currentKeyName, /* Sub Key */
606 0, /* MUST BE 0 */
607 NULL, /* object type */
608 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
609 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
610 NULL, /* security attribute */
611 &currentKeyHandle, /* result */
612 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
613 REG_OPENED_EXISTING_KEY */
615 if (hRes == ERROR_SUCCESS)
616 bTheKeyIsOpen = TRUE;
618 return hRes;
621 /******************************************************************************
622 * This function is a wrapper arround the setValue function. It prepares the
623 * land and clean the area once completed.
625 static void processSetValue(LPSTR cmdline)
627 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
629 LPSTR token = NULL; /* current token analized */
630 ULONG argCounter = 0; /* counter of args */
631 INT counter;
632 HRESULT hRes = 0;
635 * Init storage and parse the line
637 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
638 argv[counter]=NULL;
640 while( (token = strsep(&cmdline, setValueDelim[argCounter])) != NULL )
642 argv[argCounter++] = getArg(token);
644 if (argCounter == SET_VALUE_MAX_ARGS)
645 break; /* Stop processing args no matter what */
648 hRes = setValue(argv);
649 if ( hRes == ERROR_SUCCESS )
650 printf(
651 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
652 argv[0],
653 argv[1],
654 currentKeyName);
656 else if ( hRes == KEY_VALUE_ALREADY_SET )
657 printf(
658 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
659 argv[0],
660 argv[1],
661 currentKeyName);
663 else
664 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
665 currentKeyName,
666 argv[0],
667 argv[1]);
670 * Do some cleanup
672 for (counter=0; counter<argCounter; counter++)
673 if (argv[counter] != NULL)
674 HeapFree(GetProcessHeap(), 0, argv[counter]);
677 /******************************************************************************
678 * This function is a wrapper arround the queryValue function. It prepares the
679 * land and clean the area once completed.
681 static void processQueryValue(LPSTR cmdline)
683 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
684 LPSTR token = NULL; /* current token analized */
685 ULONG argCounter = 0; /* counter of args */
686 INT counter;
687 HRESULT hRes = 0;
688 LPSTR keyValue = NULL;
689 LPSTR lpsRes = NULL;
692 * Init storage and parse the line
694 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
695 argv[counter]=NULL;
697 while( (token = strsep(&cmdline, queryValueDelim[argCounter])) != NULL )
699 argv[argCounter++] = getArg(token);
701 if (argCounter == QUERY_VALUE_MAX_ARGS)
702 break; /* Stop processing args no matter what */
705 /* The value we look for is the first token on the line */
706 if ( argv[0] == NULL )
707 return; /* SHOULD NOT OCCURS */
708 else
709 keyValue = argv[0];
711 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
713 LONG lLen = KEY_MAX_LEN;
714 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
716 * We need to query the key default value
718 hRes = RegQueryValue(
719 currentKeyHandle,
720 currentKeyName,
721 (LPBYTE)lpsData,
722 &lLen);
724 if (hRes==ERROR_MORE_DATA) {
725 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
726 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
729 if (hRes == ERROR_SUCCESS)
731 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
732 strncpy(lpsRes, lpsData, lLen);
733 lpsRes[lLen-1]='\0';
736 else
738 DWORD dwLen = KEY_MAX_LEN;
739 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
740 DWORD dwType;
742 * We need to query a specific value for the key
744 hRes = RegQueryValueEx(
745 currentKeyHandle,
746 keyValue,
748 &dwType,
749 (LPBYTE)lpbData,
750 &dwLen);
752 if (hRes==ERROR_MORE_DATA) {
753 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
754 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
757 if (hRes == ERROR_SUCCESS)
760 * Convert the returned data to a displayable format
762 switch ( dwType )
764 case REG_SZ:
765 case REG_EXPAND_SZ:
767 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
768 strncpy(lpsRes, lpbData, dwLen);
769 lpsRes[dwLen-1]='\0';
770 break;
772 case REG_DWORD:
774 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
775 break;
777 default:
779 lpsRes = convertHexToHexCSV(lpbData, dwLen);
780 break;
785 HeapFree(GetProcessHeap(), 0, lpbData);
789 if ( hRes == ERROR_SUCCESS )
790 printf(
791 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
792 keyValue,
793 lpsRes,
794 currentKeyName);
796 else
797 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
798 keyValue,
799 currentKeyName);
802 * Do some cleanup
804 for (counter=0; counter<argCounter; counter++)
805 if (argv[counter] != NULL)
806 HeapFree(GetProcessHeap(), 0, argv[counter]);
808 if (lpsRes != NULL)
809 HeapFree(GetProcessHeap(), 0, lpsRes);
813 /******************************************************************************
814 * Close the currently opened key.
816 static void closeKey()
818 RegCloseKey(currentKeyHandle);
820 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
822 bTheKeyIsOpen = FALSE;
824 currentKeyName = NULL;
825 currentKeyClass = 0;
826 currentKeyHandle = 0;
829 /******************************************************************************
830 * This funtion is the main entry point to the setValue type of action. It
831 * receives the currently read line and dispatch the work depending on the
832 * context.
834 static void doSetValue(LPSTR stdInput)
837 * We encoutered the end of the file, make sure we
838 * close the opened key and exit
840 if (stdInput == NULL)
842 if (bTheKeyIsOpen != FALSE)
843 closeKey();
845 return;
848 if ( stdInput[0] == '[') /* We are reading a new key */
850 if ( bTheKeyIsOpen != FALSE )
851 closeKey(); /* Close the previous key before */
853 if ( openKey(stdInput) != ERROR_SUCCESS )
854 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
856 else if( ( bTheKeyIsOpen ) &&
857 (( stdInput[0] == '@') || /* reading a default @=data pair */
858 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
860 processSetValue(stdInput);
862 else /* since we are assuming that the */
863 { /* file format is valid we must */
864 if ( bTheKeyIsOpen ) /* be reading a blank line which */
865 closeKey(); /* indicate end of this key processing */
869 /******************************************************************************
870 * This funtion is the main entry point to the queryValue type of action. It
871 * receives the currently read line and dispatch the work depending on the
872 * context.
874 static void doQueryValue(LPSTR stdInput) {
876 * We encoutered the end of the file, make sure we
877 * close the opened key and exit
879 if (stdInput == NULL)
881 if (bTheKeyIsOpen != FALSE)
882 closeKey();
884 return;
887 if ( stdInput[0] == '[') /* We are reading a new key */
889 if ( bTheKeyIsOpen != FALSE )
890 closeKey(); /* Close the previous key before */
892 if ( openKey(stdInput) != ERROR_SUCCESS )
893 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
895 else if( ( bTheKeyIsOpen ) &&
896 (( stdInput[0] == '@') || /* reading a default @=data pair */
897 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
899 processQueryValue(stdInput);
901 else /* since we are assuming that the */
902 { /* file format is valid we must */
903 if ( bTheKeyIsOpen ) /* be reading a blank line which */
904 closeKey(); /* indicate end of this key processing */
908 /******************************************************************************
909 * This funtion is the main entry point to the deletetValue type of action. It
910 * receives the currently read line and dispatch the work depending on the
911 * context.
913 static void doDeleteValue(LPSTR line) {
914 printf ("regapi: deleteValue not yet implemented\n");
916 /******************************************************************************
917 * This funtion is the main entry point to the deleteKey type of action. It
918 * receives the currently read line and dispatch the work depending on the
919 * context.
921 static void doDeleteKey(LPSTR line) {
922 printf ("regapi: deleteKey not yet implemented\n");
924 /******************************************************************************
925 * This funtion is the main entry point to the createKey type of action. It
926 * receives the currently read line and dispatch the work depending on the
927 * context.
929 static void doCreateKey(LPSTR line) {
930 printf ("regapi: createKey not yet implemented\n");
933 /******************************************************************************
934 * This funtion is the main entry point to the registerDLL action. It
935 * receives the currently read line, then loads and registers the requested DLLs
937 static void doRegisterDLL(LPSTR stdInput) {
938 HMODULE theLib = 0;
939 UINT retVal = 0;
941 /* Check for valid input */
942 if (stdInput == NULL)
943 return;
945 /* Load and register the library, then free it */
946 theLib = LoadLibrary(stdInput);
947 if (theLib)
949 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
950 if (lpfnDLLRegProc)
951 retVal = (*lpfnDLLRegProc)();
952 else
953 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput);
955 if (retVal != S_OK)
956 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal, stdInput);
958 FreeLibrary(theLib);
960 else
962 printf("regapi: Could not load DLL '%s'.\n", stdInput);
966 /******************************************************************************
967 * This funtion is the main entry point to the unregisterDLL action. It
968 * receives the currently read line, then loads and unregisters the requested DLLs
970 static void doUnregisterDLL(LPSTR stdInput) {
971 HMODULE theLib = 0;
972 UINT retVal = 0;
974 /* Check for valid input */
975 if (stdInput == NULL)
976 return;
978 /* Load and unregister the library, then free it */
979 theLib = LoadLibrary(stdInput);
980 if (theLib)
982 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
983 if (lpfnDLLRegProc)
984 retVal = (*lpfnDLLRegProc)();
985 else
986 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput);
988 if (retVal != S_OK)
989 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal, stdInput);
991 FreeLibrary(theLib);
993 else
995 printf("regapi: Could not load DLL '%s'.\n", stdInput);
999 /******************************************************************************
1000 * MAIN - The main simply validate the first parameter (command to perform)
1001 * It then read the STDIN lines by lines forwarding their processing
1002 * to the appropriate method.
1004 int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
1006 LPSTR token = NULL; /* current token analized */
1007 LPSTR stdInput = NULL; /* line read from stdin */
1008 INT cmdIndex = -1; /* index of the command in array */
1009 LPSTR nextLine = NULL;
1010 ULONG currentSize = STDIN_MAX_LEN;
1012 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1013 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1015 if (stdInput == NULL || nextLine== NULL)
1016 return NOT_ENOUGH_MEMORY;
1019 * get the command, should be the first arg (modify cmdLine)
1021 token = strsep(&cmdline, " ");
1022 if (token != NULL)
1024 cmdIndex = getCommand(token);
1025 if (cmdIndex == COMMAND_NOT_FOUND)
1027 printf("regapi: Command \"%s\" is not supported.\n", token);
1028 printf(helpText);
1029 return COMMAND_NOT_SUPPORTED;
1032 else
1034 printf(
1035 "regapi: The first item on the command line must be the command name.\n");
1036 printf(helpText);
1037 return COMMAND_NOT_SUPPORTED;
1041 * check to see weather we force the action
1042 * (meaning differ depending on the command performed)
1044 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
1045 if ( strstr(cmdline, "-force") != NULL )
1046 bForce = TRUE;
1048 printf("Processing stdin...\n");
1050 while ( TRUE )
1053 * read a line
1055 ULONG curSize=STDIN_MAX_LEN;
1056 char* s=NULL;
1058 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
1059 fseek(stdin,-curSize,SEEK_CUR+1);
1060 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
1063 * Make some handy generic stuff here...
1065 if ( stdInput != NULL )
1067 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
1069 if( stdInput[0] == '#' ) /* this is a comment, skip */
1070 continue;
1072 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1073 /* that this line is not complete and we have to get */
1074 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
1076 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1078 nextLine[strlen(nextLine)-1] = '\0';
1080 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1082 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1084 currentSize+=STDIN_MAX_LEN;
1087 strcat(stdInput,nextLine+2);
1092 * We process every lines even the NULL (last) line, to indicate the
1093 * end of the processing to the specific process.
1095 commandAPIs[cmdIndex](stdInput);
1097 if (stdInput == NULL) /* EOF encountered */
1098 break;
1101 #if 0
1103 * Save the registry only if it was modified
1105 if ( commandSaveRegistry[cmdIndex] != FALSE )
1106 SHELL_SaveRegistry();
1107 #endif
1108 HeapFree(GetProcessHeap(), 0, nextLine);
1110 HeapFree(GetProcessHeap(), 0, stdInput);
1112 return SUCCESS;