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

Last change on this file since 10366 was 7933, checked in by sandervl, 24 years ago

Wine update

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