Implemented ReportEventA/W.
[wine/testsucceed.git] / programs / regapi / regapi.c
blob9abaa3c50eaa964c2f457c9871982ec0e276cf44
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] = {""};
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 * Generic prototypes
109 static DWORD getDataType(LPSTR *lpValue, DWORD* parse_type);
110 static LPSTR getRegKeyName(LPSTR lpLine);
111 static HKEY getRegClass(LPSTR lpLine);
112 static LPSTR getArg(LPSTR arg);
113 static INT getCommand(LPSTR commandName);
114 static DWORD convertHexToDWord(char *str, BYTE *buf);
115 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
116 static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
117 static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
118 static HRESULT openKey(LPSTR stdInput);
119 static void closeKey();
122 * api setValue prototypes
124 static void processSetValue(LPSTR cmdline);
125 static HRESULT setValue(LPSTR *argv);
128 * api queryValue prototypes
130 static void processQueryValue(LPSTR cmdline);
133 * Help Text displayed when invalid parameters are provided
135 static char helpText[] =
136 "NAME\n"
137 " regapi - perform certain actions on the wine registry.\n"
138 "\n"
139 "SYNOPSIS\n"
140 " regapi commandName [-force] < file\n"
141 "\n"
142 "DESCRIPTION\n"
143 " regapi modifies settings in the wine registry. It processes\n"
144 " the given commandName for every line in the stdin data stream.\n"
145 " Input data format may vary depending on the commandName\n"
146 " (see INPUT FILE FORMAT).\n"
147 "\n"
148 "OPTIONS\n"
149 " commandName\n"
150 " Instruct regapi about what action to perform on the data stream.\n"
151 " Currently, only setValue and queryValue are supported and\n"
152 " implemented.\n"
153 "\n"
154 " -force\n"
155 " When provided the action will be performed anyway. This may\n"
156 " have a different meaning depending on the context. For example,\n"
157 " when providing -force to setValue, the value is set even if it\n"
158 " was previously set to another value.\n"
159 "\n"
160 " < file\n"
161 " STDIN channel, provide a file name with line of the appropriate\n"
162 " format.\n"
163 "\n"
164 "INPUT FILE FORMAT\n"
165 "\n"
166 " setValue\n"
167 " The input file is in format, obtained from regedit.exe export.\n"
168 "\n"
169 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
170 " \"Value1\"=\"Data1\"\n"
171 " \"Value2\"=\"Data2\"\n"
172 " \"Valuen\"=\"Datan\"\n"
173 " ...\n"
174 "\n"
175 " queryValue\n"
176 " The input file format required by the queryValue command is\n"
177 " similar to the one required by setValue. The only\n"
178 " difference is that you only provide the value name.\n"
179 "\n"
180 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
181 " \"Value1\"\n"
182 " \"Value2\"\n"
183 " \"Valuen\"\n"
184 " ...\n"
185 " registerDLL\n"
186 " The input file format is a list of DLLs to register\n"
187 "\n"
188 " unregisterDLL\n"
189 " The input file format is a list of DLLs to unregister\n"
190 " February 1999.\n"
194 /******************************************************************************
195 * This function returns the HKEY associated with the data type encoded in the
196 * value. It modifies the input parameter (key value) in order to skip this
197 * "now useless" data type information.
199 * Note: Updated based on the algorithm used in 'server/registry.c'
201 DWORD getDataType(LPSTR *lpValue, DWORD* parse_type)
203 struct data_type { const char *tag; int len; int type; int parse_type; };
205 static const struct data_type data_types[] =
206 { /* actual type */ /* type to assume for parsing */
207 { "\"", 1, REG_SZ, REG_SZ },
208 { "str:\"", 5, REG_SZ, REG_SZ },
209 { "str(2):\"", 8, REG_EXPAND_SZ, REG_SZ },
210 { "str(7):\"", 8, REG_MULTI_SZ, REG_SZ },
211 { "hex:", 4, REG_BINARY, REG_BINARY },
212 { "dword:", 6, REG_DWORD, REG_DWORD },
213 { "hex(", 4, -1, REG_BINARY },
214 { NULL, 0, 0, 0 }
217 const struct data_type *ptr;
218 int type;
220 for (ptr = data_types; ptr->tag; ptr++)
222 if (memcmp( ptr->tag, *lpValue, ptr->len ))
223 continue;
225 /* Found! */
226 *parse_type = ptr->parse_type;
227 type=ptr->type;
228 *lpValue+=ptr->len;
229 if (type == -1) {
230 char* end;
231 /* "hex(xx):" is special */
232 *lpValue += 4;
233 type = (int)strtoul( *lpValue , &end, 16 );
234 if (**lpValue=='\0' || *end!=')' || *(end+1)!=':') {
235 type=REG_NONE;
236 } else {
237 *lpValue=end+2;
240 return type;
242 return (**lpValue=='\0'?REG_SZ:REG_NONE);
245 /******************************************************************************
246 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
247 * after the first '\' and end before the ']'
249 LPSTR getRegKeyName(LPSTR lpLine)
251 LPSTR keyNameBeg = NULL;
252 LPSTR keyNameEnd = NULL;
253 char lpLineCopy[KEY_MAX_LEN];
255 if (lpLine == NULL)
256 return NULL;
258 strcpy(lpLineCopy, lpLine);
260 keyNameBeg = strstr(lpLineCopy, "\\"); /* The key name start by '\' */
261 keyNameBeg++; /* but is not part of the key name */
262 keyNameEnd = strstr(lpLineCopy, "]"); /* The key name end by ']' */
263 *keyNameEnd = '\0'; /* Isolate the key name */
265 currentKeyName = HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg)+1);
266 if (currentKeyName != NULL)
267 strcpy(currentKeyName, keyNameBeg);
269 return currentKeyName;
272 /******************************************************************************
273 * Extracts from a [HKEY/some/key/path] type of line the key class (what
274 * starts after the '[' and ends before the first '\'
276 static HKEY getRegClass(LPSTR lpClass)
278 LPSTR classNameEnd;
279 LPSTR classNameBeg;
281 char lpClassCopy[KEY_MAX_LEN];
283 if (lpClass == NULL)
284 return (HKEY)ERROR_INVALID_PARAMETER;
286 strcpy(lpClassCopy, lpClass);
288 classNameEnd = strstr(lpClassCopy, "\\"); /* The class name end by '\' */
289 *classNameEnd = '\0'; /* Isolate the class name */
290 classNameBeg = &lpClassCopy[1]; /* Skip the '[' */
292 if (strcmp( classNameBeg, "HKEY_LOCAL_MACHINE") == IDENTICAL )
293 return HKEY_LOCAL_MACHINE;
294 else if (strcmp( classNameBeg, "HKEY_USERS") == IDENTICAL )
295 return HKEY_USERS;
296 else if (strcmp( classNameBeg, "HKEY_CLASSES_ROOT") == IDENTICAL )
297 return HKEY_CLASSES_ROOT;
298 else if (strcmp( classNameBeg, "HKEY_CURRENT_CONFIG") == IDENTICAL )
299 return HKEY_CURRENT_CONFIG;
300 else if (strcmp( classNameBeg, "HKEY_CURRENT_USER") == IDENTICAL )
301 return HKEY_CURRENT_USER;
302 else
303 return (HKEY)ERROR_INVALID_PARAMETER;
306 /******************************************************************************
307 * This is a replacement for strsep which is not portable (missing on Solaris).
309 static char* getToken(char** str, const char* delims)
311 char* token;
313 if (*str==NULL) {
314 /* No more tokens */
315 return NULL;
318 token=*str;
319 while (**str!='\0') {
320 if (strchr(delims,**str)!=NULL) {
321 **str='\0';
322 (*str)++;
323 return token;
325 (*str)++;
327 /* There is no other token */
328 *str=NULL;
329 return token;
332 /******************************************************************************
333 * Returns an allocated buffer with a cleaned copy (removed the surrounding
334 * dbl quotes) of the passed value.
336 static LPSTR getArg( LPSTR arg)
338 LPSTR tmp = NULL;
339 ULONG len;
341 if (arg == NULL)
342 return NULL;
345 * Get rid of surrounding quotes
347 len = strlen(arg);
349 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
350 if( arg[0] == '\"' ) arg++;
352 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
353 strcpy(tmp, arg);
355 return tmp;
358 /******************************************************************************
359 * Returns the index in the commands array of the command to process.
361 static INT getCommand(LPSTR commandName)
363 INT count;
364 for (count=0; count < COMMAND_COUNT; count++)
365 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
366 return count;
368 return COMMAND_NOT_FOUND;
371 /******************************************************************************
372 * Converts a hex representation of a DWORD into a DWORD.
374 static DWORD convertHexToDWord(char *str, BYTE *buf)
376 DWORD dw;
377 char xbuf[9];
379 memcpy(xbuf,str,8);
380 xbuf[8]='\0';
381 sscanf(xbuf,"%08lx",&dw);
382 memcpy(buf,&dw,sizeof(DWORD));
383 return sizeof(DWORD);
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 DWORD dw;
425 if ( bufLen != sizeof(DWORD) ) return NULL;
427 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
429 memcpy(&dw,buf,sizeof(DWORD));
430 sprintf(str, "%08lx", dw);
432 /* Get rid of the last comma */
433 return str;
435 /******************************************************************************
436 * Converts a hex comma separated values list into a hex list.
438 static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
440 char *s = str; /* Pointer to current */
441 char *b = buf; /* Pointer to result */
443 ULONG strLen = strlen(str);
444 ULONG strPos = 0;
445 DWORD byteCount = 0;
447 memset(buf, 0, bufLen);
450 * warn the user if we are here with a string longer than 2 bytes that does
451 * not contains ",". It is more likely because the data is invalid.
453 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
454 printf("regapi: WARNING converting CSV hex stream with no comma, "
455 "input data seems invalid.\n");
457 while (strPos < strLen)
459 char xbuf[3];
460 char wc;
462 memcpy(xbuf,s,2); xbuf[3]='\0';
463 sscanf(xbuf,"%02x",(UINT*)&wc);
464 *b++ =(unsigned char)wc;
466 s+=3;
467 strPos+=3;
468 byteCount++;
471 return byteCount;
475 /******************************************************************************
476 * Sets the value in argv[0] to the data in argv[1] for the currently
477 * opened key.
479 static HRESULT setValue(LPSTR *argv)
481 HRESULT hRes;
482 DWORD dwSize = KEY_MAX_LEN;
483 DWORD dwType = 0;
484 DWORD dwDataType,dwParseType;
486 LPSTR lpsCurrentValue;
488 LPSTR keyValue = getArg(argv[0]);
489 LPSTR keyData = argv[1];
491 /* Make some checks */
492 if ( (keyValue == NULL) || (keyData == NULL) )
493 return ERROR_INVALID_PARAMETER;
495 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
497 * Default registry values are encoded in the input stream as '@' but as
498 * blank in the wine registry.
500 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
501 keyValue[0] = '\0';
503 /* Get the data type stored into the value field */
504 dwDataType = getDataType(&keyData,&dwParseType);
506 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
507 hRes = RegQueryValueExA(
508 currentKeyHandle,
509 keyValue,
510 NULL,
511 &dwType,
512 (LPBYTE)lpsCurrentValue,
513 &dwSize);
515 while(hRes==ERROR_MORE_DATA){
516 dwSize+=KEY_MAX_LEN;
517 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
518 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
521 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
522 ( bForce )) /* -force option */
524 LPBYTE lpbData;
525 BYTE convert[KEY_MAX_LEN];
526 DWORD dwLen;
528 if ( dwParseType == REG_SZ) /* no conversion for string */
530 dwLen = strlen(keyData);
531 if (dwLen>0 && keyData[dwLen-1]=='"')
533 dwLen--;
534 keyData[dwLen]='\0';
536 lpbData = keyData;
538 else if (dwParseType == REG_DWORD) /* Convert the dword types */
540 dwLen = convertHexToDWord(keyData, convert);
541 lpbData = convert;
543 else /* Convert the hexadecimal types */
545 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
546 lpbData = convert;
549 hRes = RegSetValueEx(
550 currentKeyHandle,
551 keyValue,
552 0, /* Reserved */
553 dwDataType,
554 lpbData,
555 dwLen);
557 else
559 /* return the current value data into argv[1] */
560 if (argv[1] != NULL)
562 HeapFree(GetProcessHeap(), 0, argv[1]);
563 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
565 if ( argv[1] != NULL ) {
566 strncpy(argv[1], lpsCurrentValue, dwSize);
567 argv[1][dwSize]='\0';
571 hRes=KEY_VALUE_ALREADY_SET;
573 if (keyValue != NULL)
574 HeapFree(GetProcessHeap(), 0, keyValue);
575 return hRes;
579 /******************************************************************************
580 * Open the key
582 static HRESULT openKey( LPSTR stdInput)
584 DWORD dwDisp;
585 HRESULT hRes;
587 /* Sanity checks */
588 if (stdInput == NULL)
589 return ERROR_INVALID_PARAMETER;
591 /* Get the registry class */
592 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
593 if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
594 return (HRESULT)ERROR_INVALID_PARAMETER;
596 /* Get the key name */
597 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
598 if (currentKeyName == NULL)
599 return ERROR_INVALID_PARAMETER;
601 hRes = RegCreateKeyEx(
602 currentKeyClass, /* Class */
603 currentKeyName, /* Sub Key */
604 0, /* MUST BE 0 */
605 NULL, /* object type */
606 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
607 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
608 NULL, /* security attribute */
609 &currentKeyHandle, /* result */
610 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
611 REG_OPENED_EXISTING_KEY */
613 if (hRes == ERROR_SUCCESS)
614 bTheKeyIsOpen = TRUE;
616 return hRes;
619 /******************************************************************************
620 * This function is a wrapper for the setValue function. It prepares the
621 * land and clean the area once completed.
623 static void processSetValue(LPSTR cmdline)
625 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
627 LPSTR token = NULL; /* current token analyzed */
628 ULONG argCounter = 0; /* counter of args */
629 INT counter;
630 HRESULT hRes = 0;
633 * Init storage and parse the line
635 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
636 argv[counter]=NULL;
638 while( (token = getToken(&cmdline, setValueDelim[argCounter])) != NULL )
640 argv[argCounter++] = token;
642 if (argCounter == SET_VALUE_MAX_ARGS)
643 break; /* Stop processing args no matter what */
646 hRes = setValue(argv);
647 if ( hRes == ERROR_SUCCESS )
648 printf(
649 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
650 argv[0],
651 argv[1],
652 currentKeyName);
654 else if ( hRes == KEY_VALUE_ALREADY_SET )
655 printf(
656 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
657 argv[0],
658 argv[1],
659 currentKeyName);
661 else
662 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
663 currentKeyName,
664 argv[0],
665 argv[1]);
668 /******************************************************************************
669 * This function is a wrapper for the queryValue function. It prepares the
670 * land and clean the area once completed.
672 static void processQueryValue(LPSTR cmdline)
674 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
675 LPSTR token = NULL; /* current token analyzed */
676 ULONG argCounter = 0; /* counter of args */
677 INT counter;
678 HRESULT hRes = 0;
679 LPSTR keyValue = NULL;
680 LPSTR lpsRes = NULL;
683 * Init storage and parse the line
685 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
686 argv[counter]=NULL;
688 while( (token = getToken(&cmdline, queryValueDelim[argCounter])) != NULL )
690 argv[argCounter++] = getArg(token);
692 if (argCounter == QUERY_VALUE_MAX_ARGS)
693 break; /* Stop processing args no matter what */
696 /* The value we look for is the first token on the line */
697 if ( argv[0] == NULL )
698 return; /* SHOULD NOT HAPPEN */
699 else
700 keyValue = argv[0];
702 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
704 LONG lLen = KEY_MAX_LEN;
705 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
707 * We need to query the key default value
709 hRes = RegQueryValue(
710 currentKeyHandle,
711 currentKeyName,
712 (LPBYTE)lpsData,
713 &lLen);
715 if (hRes==ERROR_MORE_DATA) {
716 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
717 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
720 if (hRes == ERROR_SUCCESS)
722 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
723 strncpy(lpsRes, lpsData, lLen);
724 lpsRes[lLen-1]='\0';
726 HeapFree(GetProcessHeap(), 0, lpsData);
728 else
730 DWORD dwLen = KEY_MAX_LEN;
731 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
732 DWORD dwType;
734 * We need to query a specific value for the key
736 hRes = RegQueryValueEx(
737 currentKeyHandle,
738 keyValue,
740 &dwType,
741 (LPBYTE)lpbData,
742 &dwLen);
744 if (hRes==ERROR_MORE_DATA) {
745 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
746 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
749 if (hRes == ERROR_SUCCESS)
752 * Convert the returned data to a displayable format
754 switch ( dwType )
756 case REG_SZ:
757 case REG_EXPAND_SZ:
759 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
760 strncpy(lpsRes, lpbData, dwLen);
761 lpsRes[dwLen-1]='\0';
762 break;
764 case REG_DWORD:
766 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
767 break;
769 default:
771 lpsRes = convertHexToHexCSV(lpbData, dwLen);
772 break;
777 HeapFree(GetProcessHeap(), 0, lpbData);
781 if ( hRes == ERROR_SUCCESS )
782 printf(
783 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
784 keyValue,
785 lpsRes,
786 currentKeyName);
788 else
789 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
790 keyValue,
791 currentKeyName);
794 * Do some cleanup
796 for (counter=0; counter<argCounter; counter++)
797 if (argv[counter] != NULL)
798 HeapFree(GetProcessHeap(), 0, argv[counter]);
800 if (lpsRes != NULL)
801 HeapFree(GetProcessHeap(), 0, lpsRes);
805 /******************************************************************************
806 * Close the currently opened key.
808 static void closeKey()
810 RegCloseKey(currentKeyHandle);
812 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
814 bTheKeyIsOpen = FALSE;
816 currentKeyName = NULL;
817 currentKeyClass = 0;
818 currentKeyHandle = 0;
821 /******************************************************************************
822 * This funtion is the main entry point to the setValue type of action. It
823 * receives the currently read line and dispatch the work depending on the
824 * context.
826 static void doSetValue(LPSTR stdInput)
829 * We encoutered the end of the file, make sure we
830 * close the opened key and exit
832 if (stdInput == NULL)
834 if (bTheKeyIsOpen != FALSE)
835 closeKey();
837 return;
840 if ( stdInput[0] == '[') /* We are reading a new key */
842 if ( bTheKeyIsOpen != FALSE )
843 closeKey(); /* Close the previous key before */
845 if ( openKey(stdInput) != ERROR_SUCCESS )
846 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
848 else if( ( bTheKeyIsOpen ) &&
849 (( stdInput[0] == '@') || /* reading a default @=data pair */
850 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
852 processSetValue(stdInput);
854 else /* since we are assuming that the */
855 { /* file format is valid we must */
856 if ( bTheKeyIsOpen ) /* be reading a blank line which */
857 closeKey(); /* indicate end of this key processing */
861 /******************************************************************************
862 * This funtion is the main entry point to the queryValue type of action. It
863 * receives the currently read line and dispatch the work depending on the
864 * context.
866 static void doQueryValue(LPSTR stdInput) {
868 * We encoutered the end of the file, make sure we
869 * close the opened key and exit
871 if (stdInput == NULL)
873 if (bTheKeyIsOpen != FALSE)
874 closeKey();
876 return;
879 if ( stdInput[0] == '[') /* We are reading a new key */
881 if ( bTheKeyIsOpen != FALSE )
882 closeKey(); /* Close the previous key before */
884 if ( openKey(stdInput) != ERROR_SUCCESS )
885 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
887 else if( ( bTheKeyIsOpen ) &&
888 (( stdInput[0] == '@') || /* reading a default @=data pair */
889 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
891 processQueryValue(stdInput);
893 else /* since we are assuming that the */
894 { /* file format is valid we must */
895 if ( bTheKeyIsOpen ) /* be reading a blank line which */
896 closeKey(); /* indicate end of this key processing */
900 /******************************************************************************
901 * This funtion is the main entry point to the deletetValue type of action. It
902 * receives the currently read line and dispatch the work depending on the
903 * context.
905 static void doDeleteValue(LPSTR line) {
906 printf ("regapi: deleteValue not yet implemented\n");
908 /******************************************************************************
909 * This funtion is the main entry point to the deleteKey type of action. It
910 * receives the currently read line and dispatch the work depending on the
911 * context.
913 static void doDeleteKey(LPSTR line) {
914 printf ("regapi: deleteKey not yet implemented\n");
916 /******************************************************************************
917 * This funtion is the main entry point to the createKey type of action. It
918 * receives the currently read line and dispatch the work depending on the
919 * context.
921 static void doCreateKey(LPSTR line) {
922 printf ("regapi: createKey not yet implemented\n");
925 /******************************************************************************
926 * This funtion is the main entry point to the registerDLL action. It
927 * receives the currently read line, then loads and registers the requested DLLs
929 static void doRegisterDLL(LPSTR stdInput) {
930 HMODULE theLib = 0;
931 UINT retVal = 0;
933 /* Check for valid input */
934 if (stdInput == NULL)
935 return;
937 /* Load and register the library, then free it */
938 theLib = LoadLibrary(stdInput);
939 if (theLib)
941 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
942 if (lpfnDLLRegProc)
943 retVal = (*lpfnDLLRegProc)();
944 else
945 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput);
947 if (retVal != S_OK)
948 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal, stdInput);
950 FreeLibrary(theLib);
952 else
954 printf("regapi: Could not load DLL '%s'.\n", stdInput);
958 /******************************************************************************
959 * This funtion is the main entry point to the unregisterDLL action. It
960 * receives the currently read line, then loads and unregisters the requested DLLs
962 static void doUnregisterDLL(LPSTR stdInput) {
963 HMODULE theLib = 0;
964 UINT retVal = 0;
966 /* Check for valid input */
967 if (stdInput == NULL)
968 return;
970 /* Load and unregister the library, then free it */
971 theLib = LoadLibrary(stdInput);
972 if (theLib)
974 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
975 if (lpfnDLLRegProc)
976 retVal = (*lpfnDLLRegProc)();
977 else
978 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput);
980 if (retVal != S_OK)
981 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal, stdInput);
983 FreeLibrary(theLib);
985 else
987 printf("regapi: Could not load DLL '%s'.\n", stdInput);
991 /******************************************************************************
992 * MAIN - WinMain simply validates the first parameter (command to perform)
993 * It then reads the STDIN line by line forwarding their processing
994 * to the appropriate method.
996 int PASCAL WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
998 LPSTR token = NULL; /* current token analyzed */
999 LPSTR stdInput = NULL; /* line read from stdin */
1000 INT cmdIndex = -1; /* index of the command in array */
1001 LPSTR nextLine = NULL;
1002 ULONG currentSize = STDIN_MAX_LEN;
1004 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1005 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1007 if (stdInput == NULL || nextLine== NULL)
1008 return NOT_ENOUGH_MEMORY;
1011 * get the command, should be the first arg (modify cmdLine)
1013 token = getToken(&cmdline, " ");
1014 if (token != NULL)
1016 cmdIndex = getCommand(token);
1017 if (cmdIndex == COMMAND_NOT_FOUND)
1019 printf("regapi: Command \"%s\" is not supported.\n", token);
1020 printf(helpText);
1021 return COMMAND_NOT_SUPPORTED;
1024 else
1026 printf(
1027 "regapi: The first item on the command line must be the command name.\n");
1028 printf(helpText);
1029 return COMMAND_NOT_SUPPORTED;
1033 * check to see wether we force the action
1034 * (meaning differs depending on the command performed)
1036 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
1037 if ( strstr(cmdline, "-force") != NULL )
1038 bForce = TRUE;
1040 printf("Processing stdin...\n");
1042 while ( TRUE )
1045 * read a line
1047 ULONG curSize=STDIN_MAX_LEN;
1048 char* s=NULL;
1050 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
1051 fseek(stdin,-curSize,SEEK_CUR+1);
1052 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
1055 * Make some handy generic stuff here...
1057 if ( stdInput != NULL )
1059 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
1061 if( stdInput[0] == '#' ) /* this is a comment, skip */
1062 continue;
1064 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1065 /* that this line is not complete and we have to get */
1066 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
1068 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1070 nextLine[strlen(nextLine)-1] = '\0';
1072 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1074 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1076 currentSize+=STDIN_MAX_LEN;
1079 strcat(stdInput,nextLine+2);
1085 * We process every line, even the NULL (last) line, to indicate the
1086 * end of the processing to the specific process.
1088 commandAPIs[cmdIndex](stdInput);
1090 if (stdInput == NULL) /* EOF encountered */
1091 break;
1094 #if 0
1096 * Save the registry only if it was modified
1098 if ( commandSaveRegistry[cmdIndex] != FALSE )
1099 SHELL_SaveRegistry();
1100 #endif
1101 HeapFree(GetProcessHeap(), 0, nextLine);
1103 HeapFree(GetProcessHeap(), 0, stdInput);
1105 return SUCCESS;