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

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

Deduce Windows Time Zone information from the TZ environment variable.

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