source: trunk/tools/regedit/regapi.c@ 21531

Last change on this file since 21531 was 21531, checked in by dmik, 15 years ago

regapi.exe: Made it work with REGEDIT4 files generated by regedit2.exe on OS/2.

File size: 31.7 KB
Line 
1/*
2 * Command line Registry implementation
3 *
4 * Copyright 1999 Sylvain St-Germain
5 *
6 * Note: Please consult the README file for more information.
7 *
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <ctype.h>
13
14#include <windows.h>
15#include <winreg.h>
16#include <winerror.h>
17#include <winnt.h>
18#include <string.h>
19
20#ifdef __WIN32OS2__
21#include <heapstring.h>
22#define strncasecmp lstrncmpiA
23#undef PASCAL
24#define PASCAL WIN32API
25
26static char *strsep(char **string, char *token)
27{
28 char *ret = strchr(*string, *token);
29 char *ret1;
30
31 if(ret) {
32 *ret = (char)0;
33 ret++;
34 (*string) = ret;
35 ret1 = strchr(ret, *token);
36 if(ret1) *ret1 = 0;
37 }
38 return ret;
39}
40
41typedef HRESULT (* __stdcall lpfnDLLRegProc)(void);
42#endif
43
44/******************************************************************************
45 * Defines and consts
46 */
47#define IDENTICAL 0
48#define COMMAND_COUNT 7
49
50#define KEY_MAX_LEN 1024
51#define STDIN_MAX_LEN 2048
52
53/* Return values */
54#define COMMAND_NOT_FOUND -1
55#define SUCCESS 0
56#define NOT_ENOUGH_MEMORY 1
57#define KEY_VALUE_ALREADY_SET 2
58#define COMMAND_NOT_SUPPORTED 3
59
60/* Generic global */
61static BOOL bForce = FALSE; /* Is set to TRUE when -force is
62 passed on the command line */
63
64/* Globals used by the api setValue, queryValue */
65static LPSTR currentKeyName = NULL;
66static HKEY currentKeyClass = 0;
67static HKEY currentKeyHandle = 0;
68static BOOL bTheKeyIsOpen = FALSE;
69
70/* Delimiters used to parse the "value"="data" pair for setValue*/
71#define SET_VALUE_MAX_ARGS 2
72/* Delimiters used to parse the "value" to query queryValue*/
73#define QUERY_VALUE_MAX_ARGS 1
74
75static const char *setValueDelim[SET_VALUE_MAX_ARGS] = {"=", ""};
76static const char *queryValueDelim[QUERY_VALUE_MAX_ARGS] = {""};
77
78
79/*
80 * Forward declaration
81 */
82typedef void (*commandAPI)(LPSTR lpsLine);
83
84static void doSetValue(LPSTR lpsLine);
85static void doDeleteValue(LPSTR lpsLine);
86static void doCreateKey(LPSTR lpsLine);
87static void doDeleteKey(LPSTR lpsLine);
88static void doQueryValue(LPSTR lpsLine);
89static void doRegisterDLL(LPSTR lpsLine);
90static void doUnregisterDLL(LPSTR lpsLine);
91
92/*
93 * Currently supported api
94 */
95static const char* commandNames[COMMAND_COUNT] = {
96 "setValue",
97 "deleteValue",
98 "createKey",
99 "deleteKey",
100 "queryValue",
101 "registerDLL",
102 "unregisterDLL"
103};
104
105/*
106 * Pointers to processing entry points
107 */
108static const commandAPI commandAPIs[COMMAND_COUNT] = {
109 doSetValue,
110 doDeleteValue,
111 doCreateKey,
112 doDeleteKey,
113 doQueryValue,
114 doRegisterDLL,
115 doUnregisterDLL
116};
117
118/*
119 * This array controls the registry saving needs at the end of the process
120 */
121static const BOOL commandSaveRegistry[COMMAND_COUNT] = {
122 TRUE,
123 TRUE,
124 TRUE,
125 TRUE,
126 FALSE,
127 TRUE,
128 TRUE
129};
130
131/*
132 * Generic prototypes
133 */
134static DWORD getDataType(LPSTR *lpValue, DWORD* parse_type);
135static LPSTR getRegKeyName(LPSTR lpLine);
136static HKEY getRegClass(LPSTR lpLine);
137static LPSTR getArg(LPSTR arg);
138static INT getCommand(LPSTR commandName);
139static DWORD convertHexToDWord(char *str, BYTE *buf);
140static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen);
141static LPSTR convertHexToHexCSV( BYTE *buf, ULONG len);
142static LPSTR convertHexToDWORDStr( BYTE *buf, ULONG len);
143static HRESULT openKey(LPSTR stdInput);
144static void closeKey(void);
145
146/*
147 * api setValue prototypes
148 */
149static void processSetValue(LPSTR cmdline);
150static HRESULT setValue(LPSTR *argv);
151
152/*
153 * api queryValue prototypes
154 */
155static void processQueryValue(LPSTR cmdline);
156
157/*
158 * Help Text displayed when invalid parameters are provided
159 */
160static char helpText[] =
161"NAME\n"
162" regapi - perform certain actions on the wine registry.\n"
163"\n"
164"SYNOPSIS\n"
165" regapi commandName [-force] < file\n"
166"\n"
167"DESCRIPTION\n"
168" regapi modifies settings in the wine registry. It processes\n"
169" the given commandName for every line in the stdin data stream.\n"
170" Input data format may vary depending on the commandName\n"
171" (see INPUT FILE FORMAT).\n"
172"\n"
173"OPTIONS\n"
174" commandName\n"
175" Instruct regapi about what action to perform on the data stream.\n"
176" Currently, only setValue and queryValue are supported and\n"
177" implemented.\n"
178"\n"
179" -force\n"
180" When provided the action will be performed anyway. This may\n"
181" have a different meaning depending on the context. For example,\n"
182" when providing -force to setValue, the value is set even if it\n"
183" was previously set to another value.\n"
184"\n"
185" < file\n"
186" STDIN channel, provide a file name with line of the appropriate\n"
187" format.\n"
188"\n"
189"INPUT FILE FORMAT\n"
190"\n"
191" setValue\n"
192" The input file format required by the setValue command is similar\n"
193" to the one obtained from regedit.exe export option. The only\n"
194" difference is that multi line values are not supported, the\n"
195" value data must be on a single line.\n"
196"\n"
197" [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
198" \"Value1\"=\"Data1\"\n"
199" \"Value2\"=\"Data2\"\n"
200" \"Valuen\"=\"Datan\"\n"
201" ...\n"
202"\n"
203" queryValue\n"
204" The input file format required by the queryValue command is\n"
205" similar to the one required by setValue. The only\n"
206" difference is that you only provide the value name.\n"
207"\n"
208" [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
209" \"Value1\"\n"
210" \"Value2\"\n"
211" \"Valuen\"\n"
212" ...\n"
213" registerDLL\n"
214" The input file format is a list of DLLs to register\n"
215"\n"
216" unregisterDLL\n"
217" The input file format is a list of DLLs to unregister\n"
218" February 1999.\n"
219;
220
221
222/******************************************************************************
223 * This function returns the HKEY associated with the data type encoded in the
224 * value. It modifies the input parameter (key value) in order to skip this
225 * "now useless" data type information.
226 *
227 * Note: Updated based on the algorithm used in 'server/registry.c'
228 */
229DWORD getDataType(LPSTR *lpValue, DWORD* parse_type)
230{
231 struct data_type { const char *tag; int len; int type; int parse_type; };
232
233 static const struct data_type data_types[] =
234 { /* actual type */ /* type to assume for parsing */
235 { "\"", 1, REG_SZ, REG_SZ },
236 { "str:\"", 5, REG_SZ, REG_SZ },
237 { "str(2):\"", 8, REG_EXPAND_SZ, REG_SZ },
238 { "str(7):\"", 8, REG_MULTI_SZ, REG_SZ },
239 { "hex:", 4, REG_BINARY, REG_BINARY },
240 { "dword:", 6, REG_DWORD, REG_DWORD },
241 { "hex(", 4, -1, REG_BINARY },
242 { NULL, 0, 0, 0 }
243 };
244
245 const struct data_type *ptr;
246 int type;
247
248 for (ptr = data_types; ptr->tag; ptr++)
249 {
250 if (memcmp( ptr->tag, *lpValue, ptr->len ))
251 continue;
252
253 /* Found! */
254 *parse_type = ptr->parse_type;
255 type=ptr->type;
256 *lpValue+=ptr->len;
257 if (type == -1) {
258 char* end;
259 /* "hex(xx):" is special */
260 *lpValue += 4;
261 type = (int)strtoul( *lpValue , &end, 16 );
262 if (**lpValue=='\0' || *end!=')' || *(end+1)!=':') {
263 type=REG_NONE;
264 } else {
265 *lpValue=end+2;
266 }
267 }
268 return type;
269 }
270 return (**lpValue=='\0'?REG_SZ:REG_NONE);
271}
272
273/******************************************************************************
274 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
275 * after the first '\' and end before the ']'
276 */
277LPSTR getRegKeyName(LPSTR lpLine)
278{
279 LPSTR keyNameBeg = NULL;
280 LPSTR keyNameEnd = NULL;
281 char lpLineCopy[KEY_MAX_LEN];
282
283 if (lpLine == NULL)
284 return NULL;
285
286 strcpy(lpLineCopy, lpLine);
287
288 keyNameBeg = strstr(lpLineCopy, "\\"); /* The key name start by '\' */
289 keyNameBeg++; /* but is not part of the key name */
290 keyNameEnd = strstr(lpLineCopy, "]"); /* The key name end by ']' */
291 *keyNameEnd = '\0'; /* Isolate the key name */
292
293 currentKeyName = HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg)+1);
294 if (currentKeyName != NULL)
295 strcpy(currentKeyName, keyNameBeg);
296
297 return currentKeyName;
298}
299
300/******************************************************************************
301 * Extracts from a [HKEY/some/key/path] type of line the key class (what
302 * starts after the '[' and ends before the first '\'
303 */
304static HKEY getRegClass(LPSTR lpClass)
305{
306 LPSTR classNameEnd;
307 LPSTR classNameBeg;
308
309 char lpClassCopy[KEY_MAX_LEN];
310
311 if (lpClass == NULL)
312 return (HKEY)ERROR_INVALID_PARAMETER;
313
314 strcpy(lpClassCopy, lpClass);
315
316 classNameEnd = strstr(lpClassCopy, "\\"); /* The class name end by '\' */
317 *classNameEnd = '\0'; /* Isolate the class name */
318 classNameBeg = &lpClassCopy[1]; /* Skip the '[' */
319
320 if (strcmp( classNameBeg, "HKEY_LOCAL_MACHINE") == IDENTICAL )
321 return HKEY_LOCAL_MACHINE;
322 else if (strcmp( classNameBeg, "HKEY_USERS") == IDENTICAL )
323 return HKEY_USERS;
324 else if (strcmp( classNameBeg, "HKEY_CLASSES_ROOT") == IDENTICAL )
325 return HKEY_CLASSES_ROOT;
326 else if (strcmp( classNameBeg, "HKEY_CURRENT_CONFIG") == IDENTICAL )
327 return HKEY_CURRENT_CONFIG;
328 else if (strcmp( classNameBeg, "HKEY_CURRENT_USER") == IDENTICAL )
329 return HKEY_CURRENT_USER;
330 else
331 return (HKEY)ERROR_INVALID_PARAMETER;
332}
333
334/******************************************************************************
335 * This is a replacement for strsep which is not portable (missing on Solaris).
336 */
337static char* getToken(char** str, const char* delims)
338{
339 char* token;
340
341 if (*str==NULL) {
342 /* No more tokens */
343 return NULL;
344 }
345
346 token=*str;
347 while (**str!='\0') {
348 if (strchr(delims,**str)!=NULL) {
349 **str='\0';
350 (*str)++;
351 return token;
352 }
353 (*str)++;
354 }
355 /* There is no other token */
356 *str=NULL;
357 return token;
358}
359
360/******************************************************************************
361 * Returns an allocated buffer with a cleaned copy (removed the surrounding
362 * dbl quotes) of the passed value.
363 */
364static LPSTR getArg( LPSTR arg)
365{
366 LPSTR tmp = NULL;
367 ULONG len;
368
369 if (arg == NULL)
370 return NULL;
371
372 /*
373 * Get rid of surrounding quotes
374 */
375 len = strlen(arg);
376
377 if( arg[len-1] == '\"' ) arg[len-1] = '\0';
378 if( arg[0] == '\"' ) arg++;
379
380 tmp = HeapAlloc(GetProcessHeap(), 0, strlen(arg)+1);
381 strcpy(tmp, arg);
382
383 return tmp;
384}
385
386/******************************************************************************
387 * Returns the index in the commands array of the command to process.
388 */
389static INT getCommand(LPSTR commandName)
390{
391 INT count;
392 for (count=0; count < COMMAND_COUNT; count++)
393 if ( strcmp(commandName, commandNames[count]) == IDENTICAL)
394 return count;
395
396 return COMMAND_NOT_FOUND;
397}
398
399/******************************************************************************
400 * Converts a hex representation of a DWORD into a DWORD.
401 */
402static DWORD convertHexToDWord(char *str, BYTE *buf)
403{
404 DWORD dw;
405 char xbuf[9];
406
407 memcpy(xbuf,str,8);
408 xbuf[8]='\0';
409 sscanf(xbuf,"%08lx",&dw);
410 memcpy(buf,&dw,sizeof(DWORD));
411 return sizeof(DWORD);
412}
413
414/******************************************************************************
415 * Converts a hex buffer into a hex comma separated values
416 */
417static char* convertHexToHexCSV(BYTE *buf, ULONG bufLen)
418{
419 char* str;
420 char* ptrStr;
421 BYTE* ptrBuf;
422
423 ULONG current = 0;
424
425 str = HeapAlloc(GetProcessHeap(), 0, (bufLen+1)*2);
426 memset(str, 0, (bufLen+1)*2);
427 ptrStr = str; /* Pointer to result */
428 ptrBuf = buf; /* Pointer to current */
429
430 while (current < bufLen)
431 {
432 BYTE bCur = ptrBuf[current++];
433 char res[3];
434
435 sprintf(res, "%02x", (unsigned int)*&bCur);
436 strcat(str, res);
437 strcat(str, ",");
438 }
439
440 /* Get rid of the last comma */
441 str[strlen(str)-1] = '\0';
442 return str;
443}
444
445/******************************************************************************
446 * Converts a hex buffer into a DWORD string
447 */
448static char* convertHexToDWORDStr(BYTE *buf, ULONG bufLen)
449{
450 char* str;
451 DWORD dw;
452
453 if ( bufLen != sizeof(DWORD) ) return NULL;
454
455 str = HeapAlloc(GetProcessHeap(), 0, (bufLen*2)+1);
456
457 memcpy(&dw,buf,sizeof(DWORD));
458 sprintf(str, "%08lx", dw);
459
460 /* Get rid of the last comma */
461 return str;
462}
463/******************************************************************************
464 * Converts a hex comma separated values list into a hex list.
465 */
466static DWORD convertHexCSVToHex(char *str, BYTE *buf, ULONG bufLen)
467{
468 char *s = str; /* Pointer to current */
469 char *b = buf; /* Pointer to result */
470
471 ULONG strLen = strlen(str);
472 ULONG strPos = 0;
473 DWORD byteCount = 0;
474
475 memset(buf, 0, bufLen);
476
477 /*
478 * warn the user if we are here with a string longer than 2 bytes that does
479 * not contains ",". It is more likely because the data is invalid.
480 */
481 if ( ( strlen(str) > 2) && ( strstr(str, ",") == NULL) )
482 printf("regapi: WARNING converting CSV hex stream with no comma, "
483 "input data seems invalid.\n");
484
485 while (strPos < strLen)
486 {
487 char xbuf[3];
488 char wc;
489
490 memcpy(xbuf,s,2); xbuf[3]='\0';
491 sscanf(xbuf,"%02x",(UINT*)&wc);
492 *b++ =(unsigned char)wc;
493
494 s+=3;
495 strPos+=3;
496 byteCount++;
497 }
498
499 return byteCount;
500}
501
502
503/******************************************************************************
504 * Sets the value in argv[0] to the data in argv[1] for the currently
505 * opened key.
506 */
507static HRESULT setValue(LPSTR *argv)
508{
509 HRESULT hRes;
510 DWORD dwSize = KEY_MAX_LEN;
511 DWORD dwType = 0;
512 DWORD dwDataType,dwParseType;
513
514 LPSTR lpsCurrentValue;
515
516 LPSTR keyValue = getArg(argv[0]);
517 LPSTR keyData = argv[1];
518
519 /* Make some checks */
520 if ( (keyValue == NULL) || (keyData == NULL) )
521 return ERROR_INVALID_PARAMETER;
522
523 lpsCurrentValue=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN);
524 /*
525 * Default registry values are encoded in the input stream as '@' but as
526 * blank in the wine registry.
527 */
528 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
529 keyValue[0] = '\0';
530
531 /* Get the data type stored into the value field */
532 dwDataType = getDataType(&keyData,&dwParseType);
533
534 memset(lpsCurrentValue, 0, KEY_MAX_LEN);
535 hRes = RegQueryValueExA(
536 currentKeyHandle,
537 keyValue,
538 NULL,
539 &dwType,
540 (LPBYTE)lpsCurrentValue,
541 &dwSize);
542
543 while(hRes==ERROR_MORE_DATA){
544 dwSize+=KEY_MAX_LEN;
545 lpsCurrentValue=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsCurrentValue,dwSize);
546 hRes = RegQueryValueExA(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpsCurrentValue,&dwSize);
547 }
548
549 if( ( strlen(lpsCurrentValue) == 0 ) || /* The value is not existing */
550 ( bForce )) /* -force option */
551 {
552 LPBYTE lpbData;
553 BYTE convert[KEY_MAX_LEN];
554 DWORD dwLen;
555
556 if ( dwParseType == REG_SZ) /* no conversion for string */
557 {
558 dwLen = strlen(keyData);
559 lpbData = keyData;
560 if (dwLen>0)
561 {
562 if (keyData[dwLen-1]=='"')
563 {
564 dwLen--;
565 keyData[dwLen]='\0';
566 }
567 if (keyData[0]=='"')
568 {
569 dwLen--;
570 lpbData++;
571 }
572 }
573 }
574 else if (dwParseType == REG_DWORD) /* Convert the dword types */
575 {
576 dwLen = convertHexToDWord(keyData, convert);
577 lpbData = convert;
578 }
579 else /* Convert the hexadecimal types */
580 {
581 dwLen = convertHexCSVToHex(keyData, convert, KEY_MAX_LEN);
582 lpbData = convert;
583 }
584
585 hRes = RegSetValueEx(
586 currentKeyHandle,
587 keyValue,
588 0, /* Reserved */
589 dwDataType,
590 lpbData,
591 dwLen);
592 }
593 else
594 {
595 /* return the current value data into argv[1] */
596 if (argv[1] != NULL)
597 {
598 HeapFree(GetProcessHeap(), 0, argv[1]);
599 argv[1] = HeapAlloc(GetProcessHeap(), 0, dwSize+1);
600
601 if ( argv[1] != NULL ) {
602 strncpy(argv[1], lpsCurrentValue, dwSize);
603 argv[1][dwSize]='\0';
604 }
605 }
606
607 hRes=KEY_VALUE_ALREADY_SET;
608 }
609 if (keyValue != NULL)
610 HeapFree(GetProcessHeap(), 0, keyValue);
611 return hRes;
612}
613
614
615/******************************************************************************
616 * Open the key
617 */
618static HRESULT openKey( LPSTR stdInput)
619{
620 DWORD dwDisp;
621 HRESULT hRes;
622
623 /* Sanity checks */
624 if (stdInput == NULL)
625 return ERROR_INVALID_PARAMETER;
626
627 /* Get the registry class */
628 currentKeyClass = getRegClass(stdInput); /* Sets global variable */
629 if (currentKeyClass == (HKEY)ERROR_INVALID_PARAMETER)
630 return (HRESULT)ERROR_INVALID_PARAMETER;
631
632 /* Get the key name */
633 currentKeyName = getRegKeyName(stdInput); /* Sets global variable */
634 if (currentKeyName == NULL)
635 return ERROR_INVALID_PARAMETER;
636
637 hRes = RegCreateKeyEx(
638 currentKeyClass, /* Class */
639 currentKeyName, /* Sub Key */
640 0, /* MUST BE 0 */
641 NULL, /* object type */
642 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */
643 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */
644 NULL, /* security attribute */
645 &currentKeyHandle, /* result */
646 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or
647 REG_OPENED_EXISTING_KEY */
648
649 if (hRes == ERROR_SUCCESS)
650 bTheKeyIsOpen = TRUE;
651
652 return hRes;
653
654}
655/******************************************************************************
656 * This function is a wrapper for the setValue function. It prepares the
657 * land and clean the area once completed.
658 */
659static void processSetValue(LPSTR cmdline)
660{
661 LPSTR argv[SET_VALUE_MAX_ARGS]; /* args storage */
662
663 LPSTR token = NULL; /* current token analized */
664 ULONG argCounter = 0; /* counter of args */
665 INT counter;
666 HRESULT hRes = 0;
667
668 /*
669 * Init storage and parse the line
670 */
671 for (counter=0; counter<SET_VALUE_MAX_ARGS; counter++)
672 argv[counter]=NULL;
673
674 while( (token = getToken(&cmdline, setValueDelim[argCounter])) != NULL )
675 {
676 argv[argCounter++] = token;
677
678 if (argCounter == SET_VALUE_MAX_ARGS)
679 break; /* Stop processing args no matter what */
680 }
681
682 hRes = setValue(argv);
683 if ( hRes == ERROR_SUCCESS )
684 printf(
685 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
686 argv[0],
687 argv[1],
688 currentKeyName);
689
690 else if ( hRes == KEY_VALUE_ALREADY_SET )
691 printf(
692 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
693 argv[0],
694 argv[1],
695 currentKeyName);
696
697 else
698 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
699 currentKeyName,
700 argv[0],
701 argv[1]);
702}
703
704/******************************************************************************
705 * This function is a wrapper for the queryValue function. It prepares the
706 * land and clean the area once completed.
707 */
708static void processQueryValue(LPSTR cmdline)
709{
710 LPSTR argv[QUERY_VALUE_MAX_ARGS];/* args storage */
711 LPSTR token = NULL; /* current token analized */
712 ULONG argCounter = 0; /* counter of args */
713 INT counter;
714 HRESULT hRes = 0;
715 LPSTR keyValue = NULL;
716 LPSTR lpsRes = NULL;
717
718 /*
719 * Init storage and parse the line
720 */
721 for (counter=0; counter<QUERY_VALUE_MAX_ARGS; counter++)
722 argv[counter]=NULL;
723
724 while( (token = getToken(&cmdline, queryValueDelim[argCounter])) != NULL )
725 {
726 argv[argCounter++] = getArg(token);
727
728 if (argCounter == QUERY_VALUE_MAX_ARGS)
729 break; /* Stop processing args no matter what */
730 }
731
732 /* The value we look for is the first token on the line */
733 if ( argv[0] == NULL )
734 return; /* SHOULD NOT HAPPEN */
735 else
736 keyValue = argv[0];
737
738 if( (keyValue[0] == '@') && (strlen(keyValue) == 1) )
739 {
740 LONG lLen = KEY_MAX_LEN;
741 CHAR* lpsData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
742 /*
743 * We need to query the key default value
744 */
745 hRes = RegQueryValue(
746 currentKeyHandle,
747 currentKeyName,
748 (LPBYTE)lpsData,
749 &lLen);
750
751 if (hRes==ERROR_MORE_DATA) {
752 lpsData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpsData,lLen);
753 hRes = RegQueryValue(currentKeyHandle,currentKeyName,(LPBYTE)lpsData,&lLen);
754 }
755
756 if (hRes == ERROR_SUCCESS)
757 {
758 lpsRes = HeapAlloc( GetProcessHeap(), 0, lLen);
759 strncpy(lpsRes, lpsData, lLen);
760 lpsRes[lLen-1]='\0';
761 }
762 }
763 else
764 {
765 DWORD dwLen = KEY_MAX_LEN;
766 BYTE* lpbData=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,KEY_MAX_LEN);
767 DWORD dwType;
768 /*
769 * We need to query a specific value for the key
770 */
771 hRes = RegQueryValueEx(
772 currentKeyHandle,
773 keyValue,
774 0,
775 &dwType,
776 (LPBYTE)lpbData,
777 &dwLen);
778
779 if (hRes==ERROR_MORE_DATA) {
780 lpbData=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,lpbData,dwLen);
781 hRes = RegQueryValueEx(currentKeyHandle,keyValue,NULL,&dwType,(LPBYTE)lpbData,&dwLen);
782 }
783
784 if (hRes == ERROR_SUCCESS)
785 {
786 /*
787 * Convert the returned data to a displayable format
788 */
789 switch ( dwType )
790 {
791 case REG_SZ:
792 case REG_EXPAND_SZ:
793 {
794 lpsRes = HeapAlloc( GetProcessHeap(), 0, dwLen);
795 strncpy(lpsRes, lpbData, dwLen);
796 lpsRes[dwLen-1]='\0';
797 break;
798 }
799 case REG_DWORD:
800 {
801 lpsRes = convertHexToDWORDStr(lpbData, dwLen);
802 break;
803 }
804 default:
805 {
806 lpsRes = convertHexToHexCSV(lpbData, dwLen);
807 break;
808 }
809 }
810 }
811
812 HeapFree(GetProcessHeap(), 0, lpbData);
813 }
814
815
816 if ( hRes == ERROR_SUCCESS )
817 printf(
818 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
819 keyValue,
820 lpsRes,
821 currentKeyName);
822
823 else
824 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
825 keyValue,
826 currentKeyName);
827
828 /*
829 * Do some cleanup
830 */
831 for (counter=0; counter<argCounter; counter++)
832 if (argv[counter] != NULL)
833 HeapFree(GetProcessHeap(), 0, argv[counter]);
834
835 if (lpsRes != NULL)
836 HeapFree(GetProcessHeap(), 0, lpsRes);
837
838}
839
840/******************************************************************************
841 * Close the currently opened key.
842 */
843static void closeKey(void)
844{
845 RegCloseKey(currentKeyHandle);
846
847 HeapFree(GetProcessHeap(), 0, currentKeyName); /* Allocated by getKeyName */
848
849 bTheKeyIsOpen = FALSE;
850
851 currentKeyName = NULL;
852 currentKeyClass = 0;
853 currentKeyHandle = 0;
854}
855
856/******************************************************************************
857 * This funtion is the main entry point to the setValue type of action. It
858 * receives the currently read line and dispatch the work depending on the
859 * context.
860 */
861static void doSetValue(LPSTR stdInput)
862{
863 /*
864 * We encoutered the end of the file, make sure we
865 * close the opened key and exit
866 */
867 if (stdInput == NULL)
868 {
869 if (bTheKeyIsOpen != FALSE)
870 closeKey();
871
872 return;
873 }
874
875 if ( stdInput[0] == '[') /* We are reading a new key */
876 {
877 if ( bTheKeyIsOpen != FALSE )
878 closeKey(); /* Close the previous key before */
879
880 if ( openKey(stdInput) != ERROR_SUCCESS )
881 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
882 }
883 else if( ( bTheKeyIsOpen ) &&
884 (( stdInput[0] == '@') || /* reading a default @=data pair */
885 ( stdInput[0] == '\"') ||
886 ( isalpha(stdInput[0])))) /* reading a new value=data pair */
887 {
888 processSetValue(stdInput);
889 }
890 else /* since we are assuming that the */
891 { /* file format is valid we must */
892 if ( bTheKeyIsOpen ) /* be reading a blank line which */
893 closeKey(); /* indicate end of this key processing */
894 }
895}
896
897/******************************************************************************
898 * This funtion is the main entry point to the queryValue type of action. It
899 * receives the currently read line and dispatch the work depending on the
900 * context.
901 */
902static void doQueryValue(LPSTR stdInput) {
903 /*
904 * We encoutered the end of the file, make sure we
905 * close the opened key and exit
906 */
907 if (stdInput == NULL)
908 {
909 if (bTheKeyIsOpen != FALSE)
910 closeKey();
911
912 return;
913 }
914
915 if ( stdInput[0] == '[') /* We are reading a new key */
916 {
917 if ( bTheKeyIsOpen != FALSE )
918 closeKey(); /* Close the previous key before */
919
920 if ( openKey(stdInput) != ERROR_SUCCESS )
921 printf ("regapi: doSetValue failed to open key %s\n", stdInput);
922 }
923 else if( ( bTheKeyIsOpen ) &&
924 (( stdInput[0] == '@') || /* reading a default @=data pair */
925 ( stdInput[0] == '\"'))) /* reading a new value=data pair */
926 {
927 processQueryValue(stdInput);
928 }
929 else /* since we are assuming that the */
930 { /* file format is valid we must */
931 if ( bTheKeyIsOpen ) /* be reading a blank line which */
932 closeKey(); /* indicate end of this key processing */
933 }
934}
935
936/******************************************************************************
937 * This funtion is the main entry point to the deletetValue type of action. It
938 * receives the currently read line and dispatch the work depending on the
939 * context.
940 */
941static void doDeleteValue(LPSTR line) {
942 printf ("regapi: deleteValue not yet implemented\n");
943}
944/******************************************************************************
945 * This funtion is the main entry point to the deleteKey type of action. It
946 * receives the currently read line and dispatch the work depending on the
947 * context.
948 */
949static void doDeleteKey(LPSTR line) {
950 printf ("regapi: deleteKey not yet implemented\n");
951}
952/******************************************************************************
953 * This funtion is the main entry point to the createKey type of action. It
954 * receives the currently read line and dispatch the work depending on the
955 * context.
956 */
957static void doCreateKey(LPSTR line) {
958 printf ("regapi: createKey not yet implemented\n");
959}
960
961/******************************************************************************
962 * This funtion is the main entry point to the registerDLL action. It
963 * receives the currently read line, then loads and registers the requested DLLs
964 */
965static void doRegisterDLL(LPSTR stdInput) {
966 HMODULE theLib = 0;
967 UINT retVal = 0;
968
969 /* Check for valid input */
970 if (stdInput == NULL)
971 return;
972
973 /* Load and register the library, then free it */
974 theLib = LoadLibrary(stdInput);
975 if (theLib)
976 {
977 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllRegisterServer");
978 if (lpfnDLLRegProc)
979 retVal = lpfnDLLRegProc();
980 else
981 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput);
982
983 if (retVal != S_OK)
984 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal, stdInput);
985
986 FreeLibrary(theLib);
987 }
988 else
989 {
990 printf("regapi: Could not load DLL '%s'.\n", stdInput);
991 }
992}
993
994/******************************************************************************
995 * This funtion is the main entry point to the unregisterDLL action. It
996 * receives the currently read line, then loads and unregisters the requested DLLs
997 */
998static void doUnregisterDLL(LPSTR stdInput) {
999 HMODULE theLib = 0;
1000 UINT retVal = 0;
1001
1002 /* Check for valid input */
1003 if (stdInput == NULL)
1004 return;
1005
1006 /* Load and unregister the library, then free it */
1007 theLib = LoadLibrary(stdInput);
1008 if (theLib)
1009 {
1010 FARPROC lpfnDLLRegProc = GetProcAddress(theLib, "DllUnregisterServer");
1011 if (lpfnDLLRegProc)
1012 retVal = lpfnDLLRegProc();
1013 else
1014 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput);
1015
1016 if (retVal != S_OK)
1017 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal, stdInput);
1018
1019 FreeLibrary(theLib);
1020 }
1021 else
1022 {
1023 printf("regapi: Could not load DLL '%s'.\n", stdInput);
1024 }
1025}
1026
1027/******************************************************************************
1028 * MAIN - WinMain simply validates the first parameter (command to perform)
1029 * It then reads the STDIN line by line forwarding their processing
1030 * to the appropriate method.
1031 */
1032int PASCAL WinMain (HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
1033{
1034 LPSTR token = NULL; /* current token analized */
1035 LPSTR stdInput = NULL; /* line read from stdin */
1036 INT cmdIndex = -1; /* index of the command in array */
1037 LPSTR nextLine = NULL;
1038 ULONG currentSize = STDIN_MAX_LEN;
1039
1040 stdInput = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1041 nextLine = HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN);
1042
1043 if (stdInput == NULL || nextLine== NULL)
1044 return NOT_ENOUGH_MEMORY;
1045
1046 /*
1047 * get the command, should be the first arg (modify cmdLine)
1048 */
1049#ifdef __WIN32OS2__
1050 token = "setValue";
1051#else
1052 token = getToken(&cmdline, " ");
1053#endif
1054 if (token != NULL)
1055 {
1056 cmdIndex = getCommand(token);
1057 if (cmdIndex == COMMAND_NOT_FOUND)
1058 {
1059 printf("regapi: Command \"%s\" is not supported.\n", token);
1060 printf(helpText);
1061 return COMMAND_NOT_SUPPORTED;
1062 }
1063 }
1064 else
1065 {
1066 printf(
1067 "regapi: The first item on the command line must be the command name.\n");
1068 printf(helpText);
1069 return COMMAND_NOT_SUPPORTED;
1070 }
1071
1072 /*
1073 * check to see wether we force the action
1074 * (meaning differs depending on the command performed)
1075 */
1076 if ( cmdline != NULL ) /* will be NULL if '-force' is not provided */
1077 if ( strstr(cmdline, "-force") != NULL )
1078 bForce = TRUE;
1079
1080 printf("Processing stdin...\n");
1081
1082 while ( TRUE )
1083 {
1084 /*
1085 * read a line
1086 */
1087 ULONG curSize=STDIN_MAX_LEN;
1088 char* s=NULL;
1089
1090 while((NULL!=(stdInput=fgets(stdInput,curSize,stdin))) && (NULL==(s=strchr(stdInput,'\n'))) ){
1091 fseek(stdin,-curSize,SEEK_CUR+1);
1092 stdInput=HeapReAlloc(GetProcessHeap(), 0,stdInput,curSize+=STDIN_MAX_LEN);
1093 }
1094 /*
1095 * Make some handy generic stuff here...
1096 */
1097 if ( stdInput != NULL )
1098 {
1099 stdInput[strlen(stdInput) -1] = '\0'; /* get rid of new line */
1100
1101 if( stdInput[0] == '#' ) /* this is a comment, skip */
1102 continue;
1103
1104 while( stdInput[strlen(stdInput) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1105 /* that this line is not complete and we have to get */
1106 stdInput[strlen(stdInput) -1]= '\0'; /* the rest in the next lines */
1107
1108 nextLine = fgets(nextLine, STDIN_MAX_LEN, stdin);
1109
1110 nextLine[strlen(nextLine)-1] = '\0';
1111
1112 if ( (strlen(stdInput)+strlen(nextLine)) > currentSize){
1113
1114 stdInput=HeapReAlloc(GetProcessHeap(),0,stdInput,strlen(stdInput)+STDIN_MAX_LEN);
1115
1116 currentSize+=STDIN_MAX_LEN;
1117 }
1118
1119 strcat(stdInput,nextLine+2);
1120 }
1121 }
1122
1123 /*
1124 * We process every lines even the NULL (last) line, to indicate the
1125 * end of the processing to the specific process.
1126 */
1127 commandAPIs[cmdIndex](stdInput);
1128
1129 if (stdInput == NULL) /* EOF encountered */
1130 break;
1131 }
1132
1133#if 0
1134 /*
1135 * Save the registry only if it was modified
1136 */
1137 if ( commandSaveRegistry[cmdIndex] != FALSE )
1138 SHELL_SaveRegistry();
1139#endif
1140 HeapFree(GetProcessHeap(), 0, nextLine);
1141
1142 HeapFree(GetProcessHeap(), 0, stdInput);
1143
1144 return SUCCESS;
1145}
Note: See TracBrowser for help on using the repository browser.