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

Last change on this file since 21916 was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

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