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

Last change on this file since 3424 was 3424, checked in by sandervl, 25 years ago

added

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