Added LGPL standard comment, and copyright notices where necessary.
[wine/multimedia.git] / programs / regapi / regapi.c
blob79aa54fb542493f97aaf51a3a27993080edb1c57
1 /*
2 * Command line Registry implementation
4 * Copyright 1999 Sylvain St-Germain
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Note: Please consult the README file for more information.
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <windows.h>
27 #include <winreg.h>
28 #include <winerror.h>
29 #include <winnt.h>
30 #include <string.h>
32 /******************************************************************************
33 * Defines and consts
35 #define IDENTICAL 0
36 #define COMMAND_COUNT 7
38 #define KEY_MAX_LEN 1024
39 #define STDIN_MAX_LEN 102400
41 /* Return values */
42 #define COMMAND_NOT_FOUND -1
43 #define SUCCESS 0
44 #define NOT_ENOUGH_MEMORY 1
45 #define KEY_VALUE_ALREADY_SET 2
46 #define COMMAND_NOT_SUPPORTED 3
48 /* Generic global */
49 static BOOL bForce = FALSE; /* Is set to TRUE when -force is
50 passed on the command line */
52 /* Globals used by the api setValue, queryValue */
53 static LPSTR currentKeyName = NULL;
54 static HKEY currentKeyClass = 0;
55 static HKEY currentKeyHandle = 0;
56 static BOOL bTheKeyIsOpen = FALSE;
58 /* Delimiters used to parse the "value"="data" pair for setValue*/
59 #define SET_VALUE_MAX_ARGS 2
60 /* Delimiters used to parse the "value" to query queryValue*/
61 #define QUERY_VALUE_MAX_ARGS 1
63 static const char *setValueDelim[SET_VALUE_MAX_ARGS] = {"=", ""};
64 static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS] = {""};
67 /*
68 * Forward declaration
70 typedef void (*commandAPI)(LPSTR lpsLine);
72 static void doSetValue(LPSTR lpsLine);
73 static void doDeleteValue(LPSTR lpsLine);
74 static void doCreateKey(LPSTR lpsLine);
75 static void doDeleteKey(LPSTR lpsLine);
76 static void doQueryValue(LPSTR lpsLine);
77 static void doRegisterDLL(LPSTR lpsLine);
78 static void doUnregisterDLL(LPSTR lpsLine);
81 * Currently supported api
83 static const char* commandNames[COMMAND_COUNT] = {
84 "setValue",
85 "deleteValue",
86 "createKey",
87 "deleteKey",
88 "queryValue",
89 "registerDLL",
90 "unregisterDLL"
94 * Pointers to processing entry points
96 static const commandAPI commandAPIs[COMMAND_COUNT] = {
97 doSetValue,
98 doDeleteValue,
99 doCreateKey,
100 doDeleteKey,
101 doQueryValue,
102 doRegisterDLL,
103 doUnregisterDLL
107 * This array controls the registry saving needs at the end of the process
109 static const BOOL commandSaveRegistry[COMMAND_COUNT] = {
110 TRUE,
111 TRUE,
112 TRUE,
113 TRUE,
114 FALSE,
115 TRUE,
116 TRUE
120 * Generic prototypes
122 static DWORD getDataType(LPSTR *lpValue, DWORD* parse_type);
123 static LPSTR getRegKeyName(LPSTR lpLine);
124 static HKEY getRegClass(LPSTR lpLine);
125 static LPSTR getArg(LPSTR arg);
126 static INT getCommand(LPSTR commandName);
127 static DWORD convertHexToDWord(char *str, BYTE *buf);
128 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
129 static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
130 static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
131 static HRESULT openKey(LPSTR stdInput);
132 static void closeKey();
135 * api setValue prototypes
137 static void processSetValue(LPSTR cmdline);
138 static HRESULT setValue(LPSTR *argv);
141 * api queryValue prototypes
143 static void processQueryValue(LPSTR cmdline);
146 * Help Text displayed when invalid parameters are provided
148 static char helpText[] =
149 "NAME\n"
150 " regapi - perform certain actions on the wine registry.\n"
151 "\n"
152 "SYNOPSIS\n"
153 " regapi commandName [-force] < file\n"
154 "\n"
155 "DESCRIPTION\n"
156 " regapi modifies settings in the wine registry. It processes\n"
157 " the given commandName for every line in the stdin data stream.\n"
158 " Input data format may vary depending on the commandName\n"
159 " (see INPUT FILE FORMAT).\n"
160 "\n"
161 "OPTIONS\n"
162 " commandName\n"
163 " Instruct regapi about what action to perform on the data stream.\n"
164 " Currently, only setValue and queryValue are supported and\n"
165 " implemented.\n"
166 "\n"
167 " -force\n"
168 " When provided the action will be performed anyway. This may\n"
169 " have a different meaning depending on the context. For example,\n"
170 " when providing -force to setValue, the value is set even if it\n"
171 " was previously set to another value.\n"
172 "\n"
173 " < file\n"
174 " STDIN channel, provide a file name with line of the appropriate\n"
175 " format.\n"
176 "\n"
177 "INPUT FILE FORMAT\n"
178 "\n"
179 " setValue\n"
180 " The input file is in format, obtained from regedit.exe export.\n"
181 "\n"
182 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
183 " \"Value1\"=\"Data1\"\n"
184 " \"Value2\"=\"Data2\"\n"
185 " \"Valuen\"=\"Datan\"\n"
186 " ...\n"
187 "\n"
188 " queryValue\n"
189 " The input file format required by the queryValue command is\n"
190 " similar to the one required by setValue. The only\n"
191 " difference is that you only provide the value name.\n"
192 "\n"
193 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
194 " \"Value1\"\n"
195 " \"Value2\"\n"
196 " \"Valuen\"\n"
197 " ...\n"
198 " registerDLL\n"
199 " The input file format is a list of DLLs to register\n"
200 "\n"
201 " unregisterDLL\n"
202 " The input file format is a list of DLLs to unregister\n"
203 " February 1999.\n"
207 /******************************************************************************
208 * This function returns the HKEY associated with the data type encoded in the
209 * value. It modifies the input parameter (key value) in order to skip this
210 * "now useless" data type information.
212 * Note: Updated based on the algorithm used in 'server/registry.c'
214 DWORD getDataType(LPSTR *lpValue, DWORD* parse_type)
216 struct data_type { const char *tag; int len; int type; int parse_type; };
218 static const struct data_type data_types[] =
219 { /* actual type */ /* type to assume for parsing */
220 { "\"", 1, REG_SZ, REG_SZ },
221 { "str:\"", 5, REG_SZ, REG_SZ },
222 { "str(2):\"", 8, REG_EXPAND_SZ, REG_SZ },
223 { "str(7):\"", 8, REG_MULTI_SZ, REG_SZ },
224 { "hex:", 4, REG_BINARY, REG_BINARY },
225 { "dword:", 6, REG_DWORD, REG_DWORD },
226 { "hex(", 4, -1, REG_BINARY },
227 { NULL, 0, 0, 0 }
230 const struct data_type *ptr;
231 int type;
233 for (ptr = data_types; ptr->tag; ptr++)
235 if (memcmp( ptr->tag, *lpValue, ptr->len ))
236 continue;
238 /* Found! */
239 *parse_type = ptr->parse_type;
240 type=ptr->type;
241 *lpValue+=ptr->len;
242 if (type == -1) {
243 char* end;
244 /* "hex(xx):" is special */
245 *lpValue += 4;
246 type = (int)strtoul( *lpValue , &end, 16 );
247 if (**lpValue=='\0' || *end!=')' || *(end+1)!=':') {
248 type=REG_NONE;
249 } else {
250 *lpValue=end+2;
253 return type;
255 return (**lpValue=='\0'?REG_SZ:REG_NONE);
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 * This is a replacement for strsep which is not portable (missing on Solaris).
322 static char* getToken(char** str, const char* delims)
324 char* token;
326 if (*str==NULL) {
327 /* No more tokens */
328 return NULL;
331 token=*str;
332 while (**str!='\0') {
333 if (strchr(delims,**str)!=NULL) {
334 **str='\0';
335 (*str)++;
336 return token;
338 (*str)++;
340 /* There is no other token */
341 *str=NULL;
342 return token;
345 /******************************************************************************
346 * Returns an allocated buffer with a cleaned copy (removed the surrounding
347 * dbl quotes) of the passed value.
349 static LPSTR getArg( LPSTR arg)
351 LPSTR tmp = NULL;
352 ULONG len;
354 if (arg == NULL)
355 return NULL;
358 * Get rid of surrounding quotes
360 len = strlen(arg);
362 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
363 if( arg[0] == '\"' ) arg++;
365 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
366 strcpy(tmp, arg);
368 return tmp;
371 /******************************************************************************
372 * Returns the index in the commands array of the command to process.
374 static INT getCommand(LPSTR commandName)
376 INT count;
377 for (count=0; count < COMMAND_COUNT; count++)
378 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
379 return count;
381 return COMMAND_NOT_FOUND;
384 /******************************************************************************
385 * Converts a hex representation of a DWORD into a DWORD.
387 static DWORD convertHexToDWord(char *str, BYTE *buf)
389 DWORD dw;
390 char xbuf[9];
392 memcpy(xbuf,str,8);
393 xbuf[8]='\0';
394 sscanf(xbuf,"%08lx",&dw);
395 memcpy(buf,&dw,sizeof(DWORD));
396 return sizeof(DWORD);
399 /******************************************************************************
400 * Converts a hex buffer into a hex comma separated values
402 static char* convertHexToHexCSV(BYTE *buf, ULONG bufLen)
404 char* str;
405 char* ptrStr;
406 BYTE* ptrBuf;
408 ULONG current = 0;
410 str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2);
411 memset(str, 0, (bufLen+1)*2);
412 ptrStr = str; /* Pointer to result */
413 ptrBuf = buf; /* Pointer to current */
415 while (current < bufLen)
417 BYTE bCur = ptrBuf[current++];
418 char res[3];
420 sprintf(res, "%02x", (unsigned int)*&bCur);
421 strcat(str, res);
422 strcat(str, ",");
425 /* Get rid of the last comma */
426 str[strlen(str)-1] = '\0';
427 return str;
430 /******************************************************************************
431 * Converts a hex buffer into a DWORD string
433 static char* convertHexToDWORDStr(BYTE *buf, ULONG bufLen)
435 char* str;
436 DWORD dw;
438 if ( bufLen != sizeof(DWORD) ) return NULL;
440 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
442 memcpy(&dw,buf,sizeof(DWORD));
443 sprintf(str, "%08lx", dw);
445 /* Get rid of the last comma */
446 return str;
448 /******************************************************************************
449 * Converts a hex comma separated values list into a hex list.
451 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
453 char *s = str; /* Pointer to current */
454 char *b = buf; /* Pointer to result */
456 ULONG strLen = strlen(str);
457 ULONG strPos = 0;
458 DWORD byteCount = 0;
460 memset(buf, 0, bufLen);
463 * warn the user if we are here with a string longer than 2 bytes that does
464 * not contains ",". It is more likely because the data is invalid.
466 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
467 printf("regapi: WARNING converting CSV hex stream with no comma, "
468 "input data seems invalid.\n");
470 while (strPos < strLen)
472 char xbuf[3];
473 char wc;
475 memcpy(xbuf,s,2); xbuf[3]='\0';
476 sscanf(xbuf,"%02x",(UINT*)&wc);
477 *b++ =(unsigned char)wc;
479 s+=3;
480 strPos+=3;
481 byteCount++;
484 return byteCount;
488 /******************************************************************************
489 * Sets the value in argv[0] to the data in argv[1] for the currently
490 * opened key.
492 static HRESULT setValue(LPSTR *argv)
494 HRESULT hRes;
495 DWORD dwSize = KEY_MAX_LEN;
496 DWORD dwType = 0;
497 DWORD dwDataType,dwParseType;
499 LPSTR lpsCurrentValue;
501 LPSTR keyValue = getArg(argv[0]);
502 LPSTR keyData = argv[1];
504 /* Make some checks */
505 if ( (keyValue == NULL) || (keyData == NULL) )
506 return ERROR_INVALID_PARAMETER;
508 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
510 * Default registry values are encoded in the input stream as '@' but as
511 * blank in the wine registry.
513 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
514 keyValue[0] = '\0';
516 /* Get the data type stored into the value field */
517 dwDataType = getDataType(&keyData,&dwParseType);
519 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
520 hRes = RegQueryValueExA(
521 currentKeyHandle,
522 keyValue,
523 NULL,
524 &dwType,
525 (LPBYTE)lpsCurrentValue,
526 &dwSize);
528 while(hRes==ERROR_MORE_DATA){
529 dwSize+=KEY_MAX_LEN;
530 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
531 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
534 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
535 ( bForce )) /* -force option */
537 LPBYTE lpbData;
538 BYTE convert[KEY_MAX_LEN];
539 DWORD dwLen;
541 if ( dwParseType == REG_SZ) /* no conversion for string */
543 dwLen = strlen(keyData);
544 if (dwLen>0 && keyData[dwLen-1]=='"')
546 dwLen--;
547 keyData[dwLen]='\0';
549 lpbData = keyData;
551 else if (dwParseType == REG_DWORD) /* Convert the dword types */
553 dwLen = convertHexToDWord(keyData, convert);
554 lpbData = convert;
556 else /* Convert the hexadecimal types */
558 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
559 lpbData = convert;
562 hRes = RegSetValueEx(
563 currentKeyHandle,
564 keyValue,
565 0, /* Reserved */
566 dwDataType,
567 lpbData,
568 dwLen);
570 else
572 /* return the current value data into argv[1] */
573 if (argv[1] != NULL)
575 HeapFree(GetProcessHeap(), 0, argv[1]);
576 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
578 if ( argv[1] != NULL ) {
579 strncpy(argv[1], lpsCurrentValue, dwSize);
580 argv[1][dwSize]='\0';
584 hRes=KEY_VALUE_ALREADY_SET;
586 if (keyValue != NULL)
587 HeapFree(GetProcessHeap(), 0, keyValue);
588 return hRes;
592 /******************************************************************************
593 * Open the key
595 static HRESULT openKey( LPSTR stdInput)
597 DWORD dwDisp;
598 HRESULT hRes;
600 /* Sanity checks */
601 if (stdInput == NULL)
602 return ERROR_INVALID_PARAMETER;
604 /* Get the registry class */
605 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
606 if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
607 return (HRESULT)ERROR_INVALID_PARAMETER;
609 /* Get the key name */
610 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
611 if (currentKeyName == NULL)
612 return ERROR_INVALID_PARAMETER;
614 hRes = RegCreateKeyEx(
615 currentKeyClass, /* Class */
616 currentKeyName, /* Sub Key */
617 0, /* MUST BE 0 */
618 NULL, /* object type */
619 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
620 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
621 NULL, /* security attribute */
622 &currentKeyHandle, /* result */
623 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
624 REG_OPENED_EXISTING_KEY */
626 if (hRes == ERROR_SUCCESS)
627 bTheKeyIsOpen = TRUE;
629 return hRes;
632 /******************************************************************************
633 * This function is a wrapper for the setValue function. It prepares the
634 * land and clean the area once completed.
636 static void processSetValue(LPSTR cmdline)
638 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
640 LPSTR token = NULL; /* current token analized */
641 ULONG argCounter = 0; /* counter of args */
642 INT counter;
643 HRESULT hRes = 0;
646 * Init storage and parse the line
648 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
649 argv[counter]=NULL;
651 while( (token = getToken(&cmdline, setValueDelim[argCounter])) != NULL )
653 argv[argCounter++] = token;
655 if (argCounter == SET_VALUE_MAX_ARGS)
656 break; /* Stop processing args no matter what */
659 hRes = setValue(argv);
660 if ( hRes == ERROR_SUCCESS )
661 printf(
662 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
663 argv[0],
664 argv[1],
665 currentKeyName);
667 else if ( hRes == KEY_VALUE_ALREADY_SET )
668 printf(
669 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
670 argv[0],
671 argv[1],
672 currentKeyName);
674 else
675 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
676 currentKeyName,
677 argv[0],
678 argv[1]);
681 /******************************************************************************
682 * This function is a wrapper for the queryValue function. It prepares the
683 * land and clean the area once completed.
685 static void processQueryValue(LPSTR cmdline)
687 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
688 LPSTR token = NULL; /* current token analized */
689 ULONG argCounter = 0; /* counter of args */
690 INT counter;
691 HRESULT hRes = 0;
692 LPSTR keyValue = NULL;
693 LPSTR lpsRes = NULL;
696 * Init storage and parse the line
698 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
699 argv[counter]=NULL;
701 while( (token = getToken(&cmdline, queryValueDelim[argCounter])) != NULL )
703 argv[argCounter++] = getArg(token);
705 if (argCounter == QUERY_VALUE_MAX_ARGS)
706 break; /* Stop processing args no matter what */
709 /* The value we look for is the first token on the line */
710 if ( argv[0] == NULL )
711 return; /* SHOULD NOT HAPPEN */
712 else
713 keyValue = argv[0];
715 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
717 LONG lLen = KEY_MAX_LEN;
718 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
720 * We need to query the key default value
722 hRes = RegQueryValue(
723 currentKeyHandle,
724 currentKeyName,
725 (LPBYTE)lpsData,
726 &lLen);
728 if (hRes==ERROR_MORE_DATA) {
729 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
730 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
733 if (hRes == ERROR_SUCCESS)
735 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
736 strncpy(lpsRes, lpsData, lLen);
737 lpsRes[lLen-1]='\0';
740 else
742 DWORD dwLen = KEY_MAX_LEN;
743 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
744 DWORD dwType;
746 * We need to query a specific value for the key
748 hRes = RegQueryValueEx(
749 currentKeyHandle,
750 keyValue,
752 &dwType,
753 (LPBYTE)lpbData,
754 &dwLen);
756 if (hRes==ERROR_MORE_DATA) {
757 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
758 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
761 if (hRes == ERROR_SUCCESS)
764 * Convert the returned data to a displayable format
766 switch ( dwType )
768 case REG_SZ:
769 case REG_EXPAND_SZ:
771 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
772 strncpy(lpsRes, lpbData, dwLen);
773 lpsRes[dwLen-1]='\0';
774 break;
776 case REG_DWORD:
778 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
779 break;
781 default:
783 lpsRes = convertHexToHexCSV(lpbData, dwLen);
784 break;
789 HeapFree(GetProcessHeap(), 0, lpbData);
793 if ( hRes == ERROR_SUCCESS )
794 printf(
795 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
796 keyValue,
797 lpsRes,
798 currentKeyName);
800 else
801 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
802 keyValue,
803 currentKeyName);
806 * Do some cleanup
808 for (counter=0; counter<argCounter; counter++)
809 if (argv[counter] != NULL)
810 HeapFree(GetProcessHeap(), 0, argv[counter]);
812 if (lpsRes != NULL)
813 HeapFree(GetProcessHeap(), 0, lpsRes);
817 /******************************************************************************
818 * Close the currently opened key.
820 static void closeKey()
822 RegCloseKey(currentKeyHandle);
824 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
826 bTheKeyIsOpen = FALSE;
828 currentKeyName = NULL;
829 currentKeyClass = 0;
830 currentKeyHandle = 0;
833 /******************************************************************************
834 * This funtion is the main entry point to the setValue type of action. It
835 * receives the currently read line and dispatch the work depending on the
836 * context.
838 static void doSetValue(LPSTR stdInput)
841 * We encoutered the end of the file, make sure we
842 * close the opened key and exit
844 if (stdInput == NULL)
846 if (bTheKeyIsOpen != FALSE)
847 closeKey();
849 return;
852 if ( stdInput[0] == '[') /* We are reading a new key */
854 if ( bTheKeyIsOpen != FALSE )
855 closeKey(); /* Close the previous key before */
857 if ( openKey(stdInput) != ERROR_SUCCESS )
858 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
860 else if( ( bTheKeyIsOpen ) &&
861 (( stdInput[0] == '@') || /* reading a default @=data pair */
862 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
864 processSetValue(stdInput);
866 else /* since we are assuming that the */
867 { /* file format is valid we must */
868 if ( bTheKeyIsOpen ) /* be reading a blank line which */
869 closeKey(); /* indicate end of this key processing */
873 /******************************************************************************
874 * This funtion is the main entry point to the queryValue type of action. It
875 * receives the currently read line and dispatch the work depending on the
876 * context.
878 static void doQueryValue(LPSTR stdInput) {
880 * We encoutered the end of the file, make sure we
881 * close the opened key and exit
883 if (stdInput == NULL)
885 if (bTheKeyIsOpen != FALSE)
886 closeKey();
888 return;
891 if ( stdInput[0] == '[') /* We are reading a new key */
893 if ( bTheKeyIsOpen != FALSE )
894 closeKey(); /* Close the previous key before */
896 if ( openKey(stdInput) != ERROR_SUCCESS )
897 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
899 else if( ( bTheKeyIsOpen ) &&
900 (( stdInput[0] == '@') || /* reading a default @=data pair */
901 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
903 processQueryValue(stdInput);
905 else /* since we are assuming that the */
906 { /* file format is valid we must */
907 if ( bTheKeyIsOpen ) /* be reading a blank line which */
908 closeKey(); /* indicate end of this key processing */
912 /******************************************************************************
913 * This funtion is the main entry point to the deletetValue type of action. It
914 * receives the currently read line and dispatch the work depending on the
915 * context.
917 static void doDeleteValue(LPSTR line) {
918 printf ("regapi: deleteValue not yet implemented\n");
920 /******************************************************************************
921 * This funtion is the main entry point to the deleteKey type of action. It
922 * receives the currently read line and dispatch the work depending on the
923 * context.
925 static void doDeleteKey(LPSTR line) {
926 printf ("regapi: deleteKey not yet implemented\n");
928 /******************************************************************************
929 * This funtion is the main entry point to the createKey type of action. It
930 * receives the currently read line and dispatch the work depending on the
931 * context.
933 static void doCreateKey(LPSTR line) {
934 printf ("regapi: createKey not yet implemented\n");
937 /******************************************************************************
938 * This funtion is the main entry point to the registerDLL action. It
939 * receives the currently read line, then loads and registers the requested DLLs
941 static void doRegisterDLL(LPSTR stdInput) {
942 HMODULE theLib = 0;
943 UINT retVal = 0;
945 /* Check for valid input */
946 if (stdInput == NULL)
947 return;
949 /* Load and register the library, then free it */
950 theLib = LoadLibrary(stdInput);
951 if (theLib)
953 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
954 if (lpfnDLLRegProc)
955 retVal = (*lpfnDLLRegProc)();
956 else
957 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput);
959 if (retVal != S_OK)
960 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal, stdInput);
962 FreeLibrary(theLib);
964 else
966 printf("regapi: Could not load DLL '%s'.\n", stdInput);
970 /******************************************************************************
971 * This funtion is the main entry point to the unregisterDLL action. It
972 * receives the currently read line, then loads and unregisters the requested DLLs
974 static void doUnregisterDLL(LPSTR stdInput) {
975 HMODULE theLib = 0;
976 UINT retVal = 0;
978 /* Check for valid input */
979 if (stdInput == NULL)
980 return;
982 /* Load and unregister the library, then free it */
983 theLib = LoadLibrary(stdInput);
984 if (theLib)
986 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
987 if (lpfnDLLRegProc)
988 retVal = (*lpfnDLLRegProc)();
989 else
990 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput);
992 if (retVal != S_OK)
993 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal, stdInput);
995 FreeLibrary(theLib);
997 else
999 printf("regapi: Could not load DLL '%s'.\n", stdInput);
1003 /******************************************************************************
1004 * MAIN - WinMain simply validates the first parameter (command to perform)
1005 * It then reads the STDIN line by line forwarding their processing
1006 * to the appropriate method.
1008 int PASCAL WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
1010 LPSTR token = NULL; /* current token analized */
1011 LPSTR stdInput = NULL; /* line read from stdin */
1012 INT cmdIndex = -1; /* index of the command in array */
1013 LPSTR nextLine = NULL;
1014 ULONG currentSize = STDIN_MAX_LEN;
1016 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1017 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1019 if (stdInput == NULL || nextLine== NULL)
1020 return NOT_ENOUGH_MEMORY;
1023 * get the command, should be the first arg (modify cmdLine)
1025 token = getToken(&cmdline, " ");
1026 if (token != NULL)
1028 cmdIndex = getCommand(token);
1029 if (cmdIndex == COMMAND_NOT_FOUND)
1031 printf("regapi: Command \"%s\" is not supported.\n", token);
1032 printf(helpText);
1033 return COMMAND_NOT_SUPPORTED;
1036 else
1038 printf(
1039 "regapi: The first item on the command line must be the command name.\n");
1040 printf(helpText);
1041 return COMMAND_NOT_SUPPORTED;
1045 * check to see wether we force the action
1046 * (meaning differs depending on the command performed)
1048 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
1049 if ( strstr(cmdline, "-force") != NULL )
1050 bForce = TRUE;
1052 printf("Processing stdin...\n");
1054 while ( TRUE )
1057 * read a line
1059 ULONG curSize=STDIN_MAX_LEN;
1060 char* s=NULL;
1062 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
1063 fseek(stdin,-curSize,SEEK_CUR+1);
1064 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
1067 * Make some handy generic stuff here...
1069 if ( stdInput != NULL )
1071 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
1073 if( stdInput[0] == '#' ) /* this is a comment, skip */
1074 continue;
1076 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1077 /* that this line is not complete and we have to get */
1078 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
1080 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1082 nextLine[strlen(nextLine)-1] = '\0';
1084 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1086 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1088 currentSize+=STDIN_MAX_LEN;
1091 strcat(stdInput,nextLine+2);
1097 * We process every lines even the NULL (last) line, to indicate the
1098 * end of the processing to the specific process.
1100 commandAPIs[cmdIndex](stdInput);
1102 if (stdInput == NULL) /* EOF encountered */
1103 break;
1106 #if 0
1108 * Save the registry only if it was modified
1110 if ( commandSaveRegistry[cmdIndex] != FALSE )
1111 SHELL_SaveRegistry();
1112 #endif
1113 HeapFree(GetProcessHeap(), 0, nextLine);
1115 HeapFree(GetProcessHeap(), 0, stdInput);
1117 return SUCCESS;