2 * Command line Registry implementation
4 * Copyright 1999 Sylvain St-Germain
6 * Note: Please consult the README file for more information.
19 /******************************************************************************
23 #define COMMAND_COUNT 7
25 #define KEY_MAX_LEN 1024
26 #define STDIN_MAX_LEN 2048
29 #define COMMAND_NOT_FOUND -1
31 #define NOT_ENOUGH_MEMORY 1
32 #define KEY_VALUE_ALREADY_SET 2
33 #define COMMAND_NOT_SUPPORTED 3
36 static BOOL bForce
= FALSE
; /* Is set to TRUE when -force is
37 passed on the command line */
39 /* Globals used by the api setValue, queryValue */
40 static LPSTR currentKeyName
= NULL
;
41 static HKEY currentKeyClass
= 0;
42 static HKEY currentKeyHandle
= 0;
43 static BOOL bTheKeyIsOpen
= FALSE
;
45 /* Delimiters used to parse the "value"="data" pair for setValue*/
46 #define SET_VALUE_MAX_ARGS 2
47 /* Delimiters used to parse the "value" to query queryValue*/
48 #define QUERY_VALUE_MAX_ARGS 1
50 static const char *setValueDelim
[SET_VALUE_MAX_ARGS
] = {"=", ""};
51 static const char *queryValueDelim
[QUERY_VALUE_MAX_ARGS
] = {""};
53 /* Array used to extract the data type from a string in getDataType. */
54 typedef struct tagDataTypeMap
60 static const dataTypeMap typeMap
[] =
62 {"hex:", REG_BINARY
},/* could be REG_NONE (?) */
63 {"dword:", REG_DWORD
},
64 {"hex(0):", REG_NONE
},
66 {"hex(2):", REG_EXPAND_SZ
},
67 {"hex(3):", REG_BINARY
},
68 {"hex(4):", REG_DWORD
},
69 {"hex(5):", REG_DWORD_BIG_ENDIAN
},
70 {"hex(6):", REG_LINK
},
71 {"hex(7):", REG_MULTI_SZ
},
72 {"hex(8):", REG_RESOURCE_LIST
},
73 {"hex(9):", REG_FULL_RESOURCE_DESCRIPTOR
},
74 {"hex(10):", REG_RESOURCE_REQUIREMENTS_LIST
},
75 {"hex(80000000):", 0x80000000},
76 {"hex(80000001):", 0x80000001},
77 {"hex(80000002):", 0x80000002},
78 {"hex(80000003):", 0x80000003},
79 {"hex(80000004):", 0x80000004},
80 {"hex(80000005):", 0x80000005},
81 {"hex(80000006):", 0x80000006},
82 {"hex(80000007):", 0x80000007},
83 {"hex(80000008):", 0x80000008},
84 {"hex(80000009):", 0x80000000},
85 {"hex(8000000a):", 0x8000000A}
87 const static int LAST_TYPE_MAP
= sizeof(typeMap
)/sizeof(dataTypeMap
);
93 typedef void (*commandAPI
)(LPSTR lpsLine
);
95 static void doSetValue(LPSTR lpsLine
);
96 static void doDeleteValue(LPSTR lpsLine
);
97 static void doCreateKey(LPSTR lpsLine
);
98 static void doDeleteKey(LPSTR lpsLine
);
99 static void doQueryValue(LPSTR lpsLine
);
100 static void doRegisterDLL(LPSTR lpsLine
);
101 static void doUnregisterDLL(LPSTR lpsLine
);
104 * current supported api
106 static const char* commandNames
[COMMAND_COUNT
] = {
117 * Pointers to processing entry points
119 static const commandAPI commandAPIs
[COMMAND_COUNT
] = {
130 * This array controls the registry saving needs at the end of the process
132 static const BOOL commandSaveRegistry
[COMMAND_COUNT
] = {
145 static HKEY
getDataType(LPSTR
*lpValue
);
146 static LPSTR
getRegKeyName(LPSTR lpLine
);
147 static HKEY
getRegClass(LPSTR lpLine
);
148 static LPSTR
getArg(LPSTR arg
);
149 static INT
getCommand(LPSTR commandName
);
150 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
);
151 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
);
152 static LPSTR
convertHexToHexCSV( BYTE
*buf
, ULONG len
);
153 static LPSTR
convertHexToDWORDStr( BYTE
*buf
, ULONG len
);
154 static HRESULT
openKey(LPSTR stdInput
);
155 static void closeKey();
158 * api setValue prototypes
160 static void processSetValue(LPSTR cmdline
);
161 static HRESULT
setValue(LPSTR
*argv
);
164 * api queryValue prototypes
166 static void processQueryValue(LPSTR cmdline
);
169 * Help Text displayed when invalid parameters are provided
171 static char helpText
[] =
173 " regapi - provide a command line interface to the wine registry.\n"
176 " regapi commandName [-force] < file\n"
179 " regapi allows editing the wine registry. It processes the given\n"
180 " commandName for every line in the stdin data stream. Input data\n"
181 " format may vary depending on the commandName see INPUT FILE FORMAT.\n"
185 " Instruct regapi about what action to perform on the data stream.\n"
186 " Currently, only setValue and queryValue are supported and\n"
190 " When provided the action will be performed anyway. This may\n"
191 " have a different meaning depending on the context. For example,\n"
192 " when providing -force to setValue, the value is set even if it\n"
193 " was previously set to another value.\n"
196 " STDIN channel, provide a file name with line of the appropriate\n"
199 "INPUT FILE FORMAT\n"
202 " The input file format required by the setValue command is similar\n"
203 " to the one obtained from regedit.exe export option. The only\n"
204 " difference is that multi line values are not supported, the\n"
205 " value data must be on a single line.\n"
207 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
208 " \"Value1\"=\"Data1\"\n"
209 " \"Value2\"=\"Data2\"\n"
210 " \"Valuen\"=\"Datan\"\n"
214 " The input file format required by the queryValue command is\n"
215 " similar to the one required by setValue. The only\n"
216 " difference is that you only provide the value name.\n"
218 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
224 " The input file format is a list of DLLs to register\n"
227 " The input file format is a list of DLLs to unregister\n"
232 /******************************************************************************
233 * This function returns the HKEY associated with the data type encoded in the
234 * value. It modify the input parameter (key value) in order to skip this
235 * "now useless" data type information.
237 HKEY
getDataType(LPSTR
*lpValue
)
240 DWORD dwReturn
= REG_SZ
;
242 for (; counter
< LAST_TYPE_MAP
; counter
++)
244 LONG len
= strlen(typeMap
[counter
].mask
);
245 if ( strncasecmp( *lpValue
, typeMap
[counter
].mask
, len
) == IDENTICAL
)
248 * We found it, modify the value's pointer in order to skip the data
249 * type identifier, set the return value and exit the loop.
252 dwReturn
= typeMap
[counter
].dataType
;
259 /******************************************************************************
260 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
261 * after the first '\' and end before the ']'
263 LPSTR
getRegKeyName(LPSTR lpLine
)
265 LPSTR keyNameBeg
= NULL
;
266 LPSTR keyNameEnd
= NULL
;
267 char lpLineCopy
[KEY_MAX_LEN
];
272 strcpy(lpLineCopy
, lpLine
);
274 keyNameBeg
= strstr(lpLineCopy
, "\\"); /* The key name start by '\' */
275 keyNameBeg
++; /* but is not part of the key name */
276 keyNameEnd
= strstr(lpLineCopy
, "]"); /* The key name end by ']' */
277 *keyNameEnd
= '\0'; /* Isolate the key name */
279 currentKeyName
= HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg
)+1);
280 if (currentKeyName
!= NULL
)
281 strcpy(currentKeyName
, keyNameBeg
);
283 return currentKeyName
;
286 /******************************************************************************
287 * Extracts from a [HKEY/some/key/path] type of line the key class (what
288 * starts after the '[' and end before the first '\'
290 static HKEY
getRegClass(LPSTR lpClass
)
295 char lpClassCopy
[KEY_MAX_LEN
];
298 return ERROR_INVALID_PARAMETER
;
300 strcpy(lpClassCopy
, lpClass
);
302 classNameEnd
= strstr(lpClassCopy
, "\\"); /* The class name end by '\' */
303 *classNameEnd
= '\0'; /* Isolate the class name */
304 classNameBeg
= &lpClassCopy
[1]; /* Skip the '[' */
306 if (strcmp( classNameBeg
, "HKEY_LOCAL_MACHINE") == IDENTICAL
)
307 return HKEY_LOCAL_MACHINE
;
308 else if (strcmp( classNameBeg
, "HKEY_USERS") == IDENTICAL
)
310 else if (strcmp( classNameBeg
, "HKEY_CLASSES_ROOT") == IDENTICAL
)
311 return HKEY_CLASSES_ROOT
;
312 else if (strcmp( classNameBeg
, "HKEY_CURRENT_CONFIG") == IDENTICAL
)
313 return HKEY_CURRENT_CONFIG
;
314 else if (strcmp( classNameBeg
, "HKEY_CURRENT_USER") == IDENTICAL
)
315 return HKEY_CURRENT_USER
;
317 return ERROR_INVALID_PARAMETER
;
320 /******************************************************************************
321 * Returns an allocated buffer with a cleaned copy (removed the surrounding
322 * dbl quotes) of the passed value.
324 static LPSTR
getArg( LPSTR arg
)
333 * Get rid of surrounding quotes
337 if( arg
[len
-1] == '\"' ) arg
[len
-1] = '\0';
338 if( arg
[0] == '\"' ) arg
++;
340 tmp
= HeapAlloc(GetProcessHeap(), 0, strlen(arg
)+1);
346 /******************************************************************************
347 * Returns the index in the commands array of the command to process.
349 static INT
getCommand(LPSTR commandName
)
352 for (count
=0; count
< COMMAND_COUNT
; count
++)
353 if ( strcmp(commandName
, commandNames
[count
]) == IDENTICAL
)
356 return COMMAND_NOT_FOUND
;
359 /******************************************************************************
360 * Converts a hex representation of a DWORD into a DWORD.
362 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
)
364 char *s
= str
; /* Pointer to current */
365 char *b
= buf
; /* Pointer to result */
370 while (strPos
< 4) /* 8 byte in a DWORD */
375 memcpy(xbuf
,s
,2); xbuf
[2]='\0';
376 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
377 *b
++ =(unsigned char)wc
;
383 return 4; /* always 4 byte for the word */
386 /******************************************************************************
387 * Converts a hex buffer into a hex comma separated values
389 static char* convertHexToHexCSV(BYTE
*buf
, ULONG bufLen
)
397 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
+1)*2);
398 memset(str
, 0, (bufLen
+1)*2);
399 ptrStr
= str
; /* Pointer to result */
400 ptrBuf
= buf
; /* Pointer to current */
402 while (current
< bufLen
)
404 BYTE bCur
= ptrBuf
[current
++];
407 sprintf(res
, "%02x", (unsigned int)*&bCur
);
412 /* Get rid of the last comma */
413 str
[strlen(str
)-1] = '\0';
417 /******************************************************************************
418 * Converts a hex buffer into a DWORD string
420 static char* convertHexToDWORDStr(BYTE
*buf
, ULONG bufLen
)
428 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
*2)+1);
429 memset(str
, 0, (bufLen
*2)+1);
430 ptrStr
= str
; /* Pointer to result */
431 ptrBuf
= buf
; /* Pointer to current */
433 while (current
< bufLen
)
435 BYTE bCur
= ptrBuf
[current
++];
438 sprintf(res
, "%02x", (unsigned int)*&bCur
);
442 /* Get rid of the last comma */
445 /******************************************************************************
446 * Converts a hex comma separated values list into a hex list.
448 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
)
450 char *s
= str
; /* Pointer to current */
451 char *b
= buf
; /* Pointer to result */
453 ULONG strLen
= strlen(str
);
457 memset(buf
, 0, bufLen
);
460 * warn the user if we are here with a string longer than 2 bytes that does
461 * not contains ",". It is more likely because the data is invalid.
463 if ( ( strlen(str
) > 2) && ( strstr(str
, ",") == NULL
) )
464 printf("regapi: WARNING converting CSV hex stream with no comma, "
465 "input data seems invalid.\n");
467 while (strPos
< strLen
)
472 memcpy(xbuf
,s
,2); xbuf
[3]='\0';
473 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
474 *b
++ =(unsigned char)wc
;
485 /******************************************************************************
486 * Sets the value in argv[0] to the data in argv[1] for the currently
489 static HRESULT
setValue(LPSTR
*argv
)
492 DWORD dwSize
= KEY_MAX_LEN
;
496 LPSTR lpsCurrentValue
;
498 LPSTR keyValue
= argv
[0];
499 LPSTR keyData
= argv
[1];
501 /* Make some checks */
502 if ( (keyValue
== NULL
) || (keyData
== NULL
) )
503 return ERROR_INVALID_PARAMETER
;
505 lpsCurrentValue
=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN
);
507 * Default registry values are encoded in the input stream as '@' but as
508 * blank in the wine registry.
510 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
513 /* Get the data type stored into the value field */
514 dwDataType
= getDataType(&keyData
);
516 memset(lpsCurrentValue
, 0, KEY_MAX_LEN
);
517 hRes
= RegQueryValueExA(
522 (LPBYTE
)lpsCurrentValue
,
525 while(hRes
==ERROR_MORE_DATA
){
527 lpsCurrentValue
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsCurrentValue
,dwSize
);
528 hRes
= RegQueryValueExA(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpsCurrentValue
,&dwSize
);
531 if( ( strlen(lpsCurrentValue
) == 0 ) || /* The value is not existing */
532 ( bForce
)) /* -force option */
535 BYTE convert
[KEY_MAX_LEN
];
538 if ( dwDataType
== REG_SZ
) /* no convertion for string */
540 dwLen
= strlen(keyData
);
543 else if (dwDataType
== REG_DWORD
) /* Convert the dword types */
545 dwLen
= convertHexToDWord(keyData
, convert
);
548 else /* Convert the hexadecimal types */
550 dwLen
= convertHexCSVToHex(keyData
, convert
, KEY_MAX_LEN
);
554 hRes
= RegSetValueEx(
564 /* return the current value data into argv[1] */
567 HeapFree(GetProcessHeap(), 0, argv
[1]);
568 argv
[1] = HeapAlloc(GetProcessHeap(), 0, dwSize
+1);
570 if ( argv
[1] != NULL
) {
571 strncpy(argv
[1], lpsCurrentValue
, dwSize
);
572 argv
[1][dwSize
]='\0';
576 return KEY_VALUE_ALREADY_SET
;
582 /******************************************************************************
585 static HRESULT
openKey( LPSTR stdInput
)
591 if (stdInput
== NULL
)
592 return ERROR_INVALID_PARAMETER
;
594 /* Get the registry class */
595 currentKeyClass
= getRegClass(stdInput
); /* Sets global variable */
596 if (currentKeyClass
== ERROR_INVALID_PARAMETER
)
597 return ERROR_INVALID_PARAMETER
;
599 /* Get the key name */
600 currentKeyName
= getRegKeyName(stdInput
); /* Sets global variable */
601 if (currentKeyName
== NULL
)
602 return ERROR_INVALID_PARAMETER
;
604 hRes
= RegCreateKeyEx(
605 currentKeyClass
, /* Class */
606 currentKeyName
, /* Sub Key */
608 NULL
, /* object type */
609 REG_OPTION_NON_VOLATILE
, /* option, REG_OPTION_NON_VOLATILE ... */
610 KEY_ALL_ACCESS
, /* access mask, KEY_ALL_ACCESS */
611 NULL
, /* security attribute */
612 ¤tKeyHandle
, /* result */
613 &dwDisp
); /* disposition, REG_CREATED_NEW_KEY or
614 REG_OPENED_EXISTING_KEY */
616 if (hRes
== ERROR_SUCCESS
)
617 bTheKeyIsOpen
= TRUE
;
622 /******************************************************************************
623 * This function is a wrapper arround the setValue function. It prepares the
624 * land and clean the area once completed.
626 static void processSetValue(LPSTR cmdline
)
628 LPSTR argv
[SET_VALUE_MAX_ARGS
]; /* args storage */
630 LPSTR token
= NULL
; /* current token analized */
631 ULONG argCounter
= 0; /* counter of args */
636 * Init storage and parse the line
638 for (counter
=0; counter
<SET_VALUE_MAX_ARGS
; counter
++)
641 while( (token
= strsep(&cmdline
, setValueDelim
[argCounter
])) != NULL
)
643 argv
[argCounter
++] = getArg(token
);
645 if (argCounter
== SET_VALUE_MAX_ARGS
)
646 break; /* Stop processing args no matter what */
649 hRes
= setValue(argv
);
650 if ( hRes
== ERROR_SUCCESS
)
652 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
657 else if ( hRes
== KEY_VALUE_ALREADY_SET
)
659 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
665 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
673 for (counter
=0; counter
<argCounter
; counter
++)
674 if (argv
[counter
] != NULL
)
675 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
678 /******************************************************************************
679 * This function is a wrapper arround the queryValue function. It prepares the
680 * land and clean the area once completed.
682 static void processQueryValue(LPSTR cmdline
)
684 LPSTR argv
[QUERY_VALUE_MAX_ARGS
];/* args storage */
685 LPSTR token
= NULL
; /* current token analized */
686 ULONG argCounter
= 0; /* counter of args */
689 LPSTR keyValue
= NULL
;
693 * Init storage and parse the line
695 for (counter
=0; counter
<QUERY_VALUE_MAX_ARGS
; counter
++)
698 while( (token
= strsep(&cmdline
, queryValueDelim
[argCounter
])) != NULL
)
700 argv
[argCounter
++] = getArg(token
);
702 if (argCounter
== QUERY_VALUE_MAX_ARGS
)
703 break; /* Stop processing args no matter what */
706 /* The value we look for is the first token on the line */
707 if ( argv
[0] == NULL
)
708 return; /* SHOULD NOT OCCURS */
712 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
714 LONG lLen
= KEY_MAX_LEN
;
715 CHAR
* lpsData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
717 * We need to query the key default value
719 hRes
= RegQueryValue(
725 if (hRes
==ERROR_MORE_DATA
) {
726 lpsData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsData
,lLen
);
727 hRes
= RegQueryValue(currentKeyHandle
,currentKeyName
,(LPBYTE
)lpsData
,&lLen
);
730 if (hRes
== ERROR_SUCCESS
)
732 lpsRes
= HeapAlloc( GetProcessHeap(), 0, lLen
);
733 strncpy(lpsRes
, lpsData
, lLen
);
739 DWORD dwLen
= KEY_MAX_LEN
;
740 BYTE
* lpbData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
743 * We need to query a specific value for the key
745 hRes
= RegQueryValueEx(
753 if (hRes
==ERROR_MORE_DATA
) {
754 lpbData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpbData
,dwLen
);
755 hRes
= RegQueryValueEx(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpbData
,&dwLen
);
758 if (hRes
== ERROR_SUCCESS
)
761 * Convert the returned data to a displayable format
768 lpsRes
= HeapAlloc( GetProcessHeap(), 0, dwLen
);
769 strncpy(lpsRes
, lpbData
, dwLen
);
770 lpsRes
[dwLen
-1]='\0';
775 lpsRes
= convertHexToDWORDStr(lpbData
, dwLen
);
780 lpsRes
= convertHexToHexCSV(lpbData
, dwLen
);
786 HeapFree(GetProcessHeap(), 0, lpbData
);
790 if ( hRes
== ERROR_SUCCESS
)
792 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
798 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
805 for (counter
=0; counter
<argCounter
; counter
++)
806 if (argv
[counter
] != NULL
)
807 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
810 HeapFree(GetProcessHeap(), 0, lpsRes
);
814 /******************************************************************************
815 * Close the currently opened key.
817 static void closeKey()
819 RegCloseKey(currentKeyHandle
);
821 HeapFree(GetProcessHeap(), 0, currentKeyName
); /* Allocated by getKeyName */
823 bTheKeyIsOpen
= FALSE
;
825 currentKeyName
= NULL
;
827 currentKeyHandle
= 0;
830 /******************************************************************************
831 * This funtion is the main entry point to the setValue type of action. It
832 * receives the currently read line and dispatch the work depending on the
835 static void doSetValue(LPSTR stdInput
)
838 * We encoutered the end of the file, make sure we
839 * close the opened key and exit
841 if (stdInput
== NULL
)
843 if (bTheKeyIsOpen
!= FALSE
)
849 if ( stdInput
[0] == '[') /* We are reading a new key */
851 if ( bTheKeyIsOpen
!= FALSE
)
852 closeKey(); /* Close the previous key before */
854 if ( openKey(stdInput
) != ERROR_SUCCESS
)
855 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
857 else if( ( bTheKeyIsOpen
) &&
858 (( stdInput
[0] == '@') || /* reading a default @=data pair */
859 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
861 processSetValue(stdInput
);
863 else /* since we are assuming that the */
864 { /* file format is valid we must */
865 if ( bTheKeyIsOpen
) /* be reading a blank line which */
866 closeKey(); /* indicate end of this key processing */
870 /******************************************************************************
871 * This funtion is the main entry point to the queryValue type of action. It
872 * receives the currently read line and dispatch the work depending on the
875 static void doQueryValue(LPSTR stdInput
) {
877 * We encoutered the end of the file, make sure we
878 * close the opened key and exit
880 if (stdInput
== NULL
)
882 if (bTheKeyIsOpen
!= FALSE
)
888 if ( stdInput
[0] == '[') /* We are reading a new key */
890 if ( bTheKeyIsOpen
!= FALSE
)
891 closeKey(); /* Close the previous key before */
893 if ( openKey(stdInput
) != ERROR_SUCCESS
)
894 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
896 else if( ( bTheKeyIsOpen
) &&
897 (( stdInput
[0] == '@') || /* reading a default @=data pair */
898 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
900 processQueryValue(stdInput
);
902 else /* since we are assuming that the */
903 { /* file format is valid we must */
904 if ( bTheKeyIsOpen
) /* be reading a blank line which */
905 closeKey(); /* indicate end of this key processing */
909 /******************************************************************************
910 * This funtion is the main entry point to the deletetValue type of action. It
911 * receives the currently read line and dispatch the work depending on the
914 static void doDeleteValue(LPSTR line
) {
915 printf ("regapi: deleteValue not yet implemented\n");
917 /******************************************************************************
918 * This funtion is the main entry point to the deleteKey type of action. It
919 * receives the currently read line and dispatch the work depending on the
922 static void doDeleteKey(LPSTR line
) {
923 printf ("regapi: deleteKey not yet implemented\n");
925 /******************************************************************************
926 * This funtion is the main entry point to the createKey type of action. It
927 * receives the currently read line and dispatch the work depending on the
930 static void doCreateKey(LPSTR line
) {
931 printf ("regapi: createKey not yet implemented\n");
934 /******************************************************************************
935 * This funtion is the main entry point to the registerDLL action. It
936 * receives the currently read line, then loads and registers the requested DLLs
938 static void doRegisterDLL(LPSTR stdInput
) {
942 /* Check for valid input */
943 if (stdInput
== NULL
)
946 /* Load and register the library, then free it */
947 theLib
= LoadLibrary(stdInput
);
950 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllRegisterServer");
952 retVal
= (*lpfnDLLRegProc
)();
954 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput
);
957 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
963 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
967 /******************************************************************************
968 * This funtion is the main entry point to the unregisterDLL action. It
969 * receives the currently read line, then loads and unregisters the requested DLLs
971 static void doUnregisterDLL(LPSTR stdInput
) {
975 /* Check for valid input */
976 if (stdInput
== NULL
)
979 /* Load and unregister the library, then free it */
980 theLib
= LoadLibrary(stdInput
);
983 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllUnregisterServer");
985 retVal
= (*lpfnDLLRegProc
)();
987 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput
);
990 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
996 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
1000 /******************************************************************************
1001 * MAIN - The main simply validate the first parameter (command to perform)
1002 * It then read the STDIN lines by lines forwarding their processing
1003 * to the appropriate method.
1005 int PASCAL
WinMain (HANDLE inst
, HANDLE prev
, LPSTR cmdline
, int show
)
1007 LPSTR token
= NULL
; /* current token analized */
1008 LPSTR stdInput
= NULL
; /* line read from stdin */
1009 INT cmdIndex
= -1; /* index of the command in array */
1010 LPSTR nextLine
= NULL
;
1011 ULONG currentSize
= STDIN_MAX_LEN
;
1013 stdInput
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1014 nextLine
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1016 if (stdInput
== NULL
|| nextLine
== NULL
)
1017 return NOT_ENOUGH_MEMORY
;
1020 * get the command, should be the first arg (modify cmdLine)
1022 token
= strsep(&cmdline
, " ");
1025 cmdIndex
= getCommand(token
);
1026 if (cmdIndex
== COMMAND_NOT_FOUND
)
1028 printf("regapi: Command \"%s\" is not supported.\n", token
);
1030 return COMMAND_NOT_SUPPORTED
;
1036 "regapi: The first item on the command line must be the command name.\n");
1038 return COMMAND_NOT_SUPPORTED
;
1042 * check to see weather we force the action
1043 * (meaning differ depending on the command performed)
1045 if ( cmdline
!= NULL
) /* will be NULL if '-force' is not provided */
1046 if ( strstr(cmdline
, "-force") != NULL
)
1049 printf("Processing stdin...\n");
1056 ULONG curSize
=STDIN_MAX_LEN
;
1059 while((NULL
!=(stdInput
=fgets(stdInput
,curSize
,stdin
))) && (NULL
==(s
=strchr(stdInput
,'\n'))) ){
1060 fseek(stdin
,-curSize
,SEEK_CUR
+1);
1061 stdInput
=HeapReAlloc(GetProcessHeap(), 0,stdInput
,curSize
+=STDIN_MAX_LEN
);
1064 * Make some handy generic stuff here...
1066 if ( stdInput
!= NULL
)
1068 stdInput
[strlen(stdInput
) -1] = '\0'; /* get rid of new line */
1070 if( stdInput
[0] == '#' ) /* this is a comment, skip */
1073 while( stdInput
[strlen(stdInput
) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1074 /* that this line is not complete and we have to get */
1075 stdInput
[strlen(stdInput
) -1]= '\0'; /* the rest in the next lines */
1077 nextLine
= fgets(nextLine
, STDIN_MAX_LEN
, stdin
);
1079 nextLine
[strlen(nextLine
)-1] = '\0';
1081 if ( (strlen(stdInput
)+strlen(nextLine
)) > currentSize
){
1083 stdInput
=HeapReAlloc(GetProcessHeap(),0,stdInput
,strlen(stdInput
)+STDIN_MAX_LEN
);
1085 currentSize
+=STDIN_MAX_LEN
;
1088 strcat(stdInput
,nextLine
+2);
1093 * We process every lines even the NULL (last) line, to indicate the
1094 * end of the processing to the specific process.
1096 commandAPIs
[cmdIndex
](stdInput
);
1098 if (stdInput
== NULL
) /* EOF encountered */
1104 * Save the registry only if it was modified
1106 if ( commandSaveRegistry
[cmdIndex
] != FALSE
)
1107 SHELL_SaveRegistry();
1109 HeapFree(GetProcessHeap(), 0, nextLine
);
1111 HeapFree(GetProcessHeap(), 0, stdInput
);