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

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

updates

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