2 * Command line Registry implementation
4 * Copyright 1999 Sylvain St-Germain
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Note: Please consult the README file for more information.
32 /******************************************************************************
36 #define COMMAND_COUNT 7
38 #define KEY_MAX_LEN 1024
39 #define STDIN_MAX_LEN 102400
42 #define COMMAND_NOT_FOUND -1
44 #define NOT_ENOUGH_MEMORY 1
45 #define KEY_VALUE_ALREADY_SET 2
46 #define COMMAND_NOT_SUPPORTED 3
49 static BOOL bForce
= FALSE
; /* Is set to TRUE when -force is
50 passed on the command line */
52 /* Globals used by the api setValue, queryValue */
53 static LPSTR currentKeyName
= NULL
;
54 static HKEY currentKeyClass
= 0;
55 static HKEY currentKeyHandle
= 0;
56 static BOOL bTheKeyIsOpen
= FALSE
;
58 /* Delimiters used to parse the "value"="data" pair for setValue*/
59 #define SET_VALUE_MAX_ARGS 2
60 /* Delimiters used to parse the "value" to query queryValue*/
61 #define QUERY_VALUE_MAX_ARGS 1
63 static const char *setValueDelim
[SET_VALUE_MAX_ARGS
] = {"=", ""};
64 static const char *queryValueDelim
[QUERY_VALUE_MAX_ARGS
] = {""};
70 typedef void (*commandAPI
)(LPSTR lpsLine
);
72 static void doSetValue(LPSTR lpsLine
);
73 static void doDeleteValue(LPSTR lpsLine
);
74 static void doCreateKey(LPSTR lpsLine
);
75 static void doDeleteKey(LPSTR lpsLine
);
76 static void doQueryValue(LPSTR lpsLine
);
77 static void doRegisterDLL(LPSTR lpsLine
);
78 static void doUnregisterDLL(LPSTR lpsLine
);
81 * Currently supported api
83 static const char* commandNames
[COMMAND_COUNT
] = {
94 * Pointers to processing entry points
96 static const commandAPI commandAPIs
[COMMAND_COUNT
] = {
109 static DWORD
getDataType(LPSTR
*lpValue
, DWORD
* parse_type
);
110 static LPSTR
getRegKeyName(LPSTR lpLine
);
111 static HKEY
getRegClass(LPSTR lpLine
);
112 static LPSTR
getArg(LPSTR arg
);
113 static INT
getCommand(LPSTR commandName
);
114 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
);
115 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
);
116 static LPSTR
convertHexToHexCSV( BYTE
*buf
, ULONG len
);
117 static LPSTR
convertHexToDWORDStr( BYTE
*buf
, ULONG len
);
118 static HRESULT
openKey(LPSTR stdInput
);
119 static void closeKey();
122 * api setValue prototypes
124 static void processSetValue(LPSTR cmdline
);
125 static HRESULT
setValue(LPSTR
*argv
);
128 * api queryValue prototypes
130 static void processQueryValue(LPSTR cmdline
);
133 * Help Text displayed when invalid parameters are provided
135 static char helpText
[] =
137 " regapi - perform certain actions on the wine registry.\n"
140 " regapi commandName [-force] < file\n"
143 " regapi modifies settings in the wine registry. It processes\n"
144 " the given commandName for every line in the stdin data stream.\n"
145 " Input data format may vary depending on the commandName\n"
146 " (see INPUT FILE FORMAT).\n"
150 " Instruct regapi about what action to perform on the data stream.\n"
151 " Currently, only setValue and queryValue are supported and\n"
155 " When provided the action will be performed anyway. This may\n"
156 " have a different meaning depending on the context. For example,\n"
157 " when providing -force to setValue, the value is set even if it\n"
158 " was previously set to another value.\n"
161 " STDIN channel, provide a file name with line of the appropriate\n"
164 "INPUT FILE FORMAT\n"
167 " The input file is in format, obtained from regedit.exe export.\n"
169 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
170 " \"Value1\"=\"Data1\"\n"
171 " \"Value2\"=\"Data2\"\n"
172 " \"Valuen\"=\"Datan\"\n"
176 " The input file format required by the queryValue command is\n"
177 " similar to the one required by setValue. The only\n"
178 " difference is that you only provide the value name.\n"
180 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
186 " The input file format is a list of DLLs to register\n"
189 " The input file format is a list of DLLs to unregister\n"
194 /******************************************************************************
195 * This function returns the HKEY associated with the data type encoded in the
196 * value. It modifies the input parameter (key value) in order to skip this
197 * "now useless" data type information.
199 * Note: Updated based on the algorithm used in 'server/registry.c'
201 DWORD
getDataType(LPSTR
*lpValue
, DWORD
* parse_type
)
203 struct data_type
{ const char *tag
; int len
; int type
; int parse_type
; };
205 static const struct data_type data_types
[] =
206 { /* actual type */ /* type to assume for parsing */
207 { "\"", 1, REG_SZ
, REG_SZ
},
208 { "str:\"", 5, REG_SZ
, REG_SZ
},
209 { "str(2):\"", 8, REG_EXPAND_SZ
, REG_SZ
},
210 { "str(7):\"", 8, REG_MULTI_SZ
, REG_SZ
},
211 { "hex:", 4, REG_BINARY
, REG_BINARY
},
212 { "dword:", 6, REG_DWORD
, REG_DWORD
},
213 { "hex(", 4, -1, REG_BINARY
},
217 const struct data_type
*ptr
;
220 for (ptr
= data_types
; ptr
->tag
; ptr
++)
222 if (memcmp( ptr
->tag
, *lpValue
, ptr
->len
))
226 *parse_type
= ptr
->parse_type
;
231 /* "hex(xx):" is special */
233 type
= (int)strtoul( *lpValue
, &end
, 16 );
234 if (**lpValue
=='\0' || *end
!=')' || *(end
+1)!=':') {
242 return (**lpValue
=='\0'?REG_SZ
:REG_NONE
);
245 /******************************************************************************
246 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
247 * after the first '\' and end before the ']'
249 LPSTR
getRegKeyName(LPSTR lpLine
)
251 LPSTR keyNameBeg
= NULL
;
252 LPSTR keyNameEnd
= NULL
;
253 char lpLineCopy
[KEY_MAX_LEN
];
258 strcpy(lpLineCopy
, lpLine
);
260 keyNameBeg
= strstr(lpLineCopy
, "\\"); /* The key name start by '\' */
261 keyNameBeg
++; /* but is not part of the key name */
262 keyNameEnd
= strstr(lpLineCopy
, "]"); /* The key name end by ']' */
263 *keyNameEnd
= '\0'; /* Isolate the key name */
265 currentKeyName
= HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg
)+1);
266 if (currentKeyName
!= NULL
)
267 strcpy(currentKeyName
, keyNameBeg
);
269 return currentKeyName
;
272 /******************************************************************************
273 * Extracts from a [HKEY/some/key/path] type of line the key class (what
274 * starts after the '[' and ends before the first '\'
276 static HKEY
getRegClass(LPSTR lpClass
)
281 char lpClassCopy
[KEY_MAX_LEN
];
284 return (HKEY
)ERROR_INVALID_PARAMETER
;
286 strcpy(lpClassCopy
, lpClass
);
288 classNameEnd
= strstr(lpClassCopy
, "\\"); /* The class name end by '\' */
289 *classNameEnd
= '\0'; /* Isolate the class name */
290 classNameBeg
= &lpClassCopy
[1]; /* Skip the '[' */
292 if (strcmp( classNameBeg
, "HKEY_LOCAL_MACHINE") == IDENTICAL
)
293 return HKEY_LOCAL_MACHINE
;
294 else if (strcmp( classNameBeg
, "HKEY_USERS") == IDENTICAL
)
296 else if (strcmp( classNameBeg
, "HKEY_CLASSES_ROOT") == IDENTICAL
)
297 return HKEY_CLASSES_ROOT
;
298 else if (strcmp( classNameBeg
, "HKEY_CURRENT_CONFIG") == IDENTICAL
)
299 return HKEY_CURRENT_CONFIG
;
300 else if (strcmp( classNameBeg
, "HKEY_CURRENT_USER") == IDENTICAL
)
301 return HKEY_CURRENT_USER
;
303 return (HKEY
)ERROR_INVALID_PARAMETER
;
306 /******************************************************************************
307 * This is a replacement for strsep which is not portable (missing on Solaris).
309 static char* getToken(char** str
, const char* delims
)
319 while (**str
!='\0') {
320 if (strchr(delims
,**str
)!=NULL
) {
327 /* There is no other token */
332 /******************************************************************************
333 * Returns an allocated buffer with a cleaned copy (removed the surrounding
334 * dbl quotes) of the passed value.
336 static LPSTR
getArg( LPSTR arg
)
345 * Get rid of surrounding quotes
349 if( arg
[len
-1] == '\"' ) arg
[len
-1] = '\0';
350 if( arg
[0] == '\"' ) arg
++;
352 tmp
= HeapAlloc(GetProcessHeap(), 0, strlen(arg
)+1);
358 /******************************************************************************
359 * Returns the index in the commands array of the command to process.
361 static INT
getCommand(LPSTR commandName
)
364 for (count
=0; count
< COMMAND_COUNT
; count
++)
365 if ( strcmp(commandName
, commandNames
[count
]) == IDENTICAL
)
368 return COMMAND_NOT_FOUND
;
371 /******************************************************************************
372 * Converts a hex representation of a DWORD into a DWORD.
374 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
)
381 sscanf(xbuf
,"%08lx",&dw
);
382 memcpy(buf
,&dw
,sizeof(DWORD
));
383 return sizeof(DWORD
);
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
)
425 if ( bufLen
!= sizeof(DWORD
) ) return NULL
;
427 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
*2)+1);
429 memcpy(&dw
,buf
,sizeof(DWORD
));
430 sprintf(str
, "%08lx", dw
);
432 /* Get rid of the last comma */
435 /******************************************************************************
436 * Converts a hex comma separated values list into a hex list.
438 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
)
440 char *s
= str
; /* Pointer to current */
441 char *b
= buf
; /* Pointer to result */
443 ULONG strLen
= strlen(str
);
447 memset(buf
, 0, bufLen
);
450 * warn the user if we are here with a string longer than 2 bytes that does
451 * not contains ",". It is more likely because the data is invalid.
453 if ( ( strlen(str
) > 2) && ( strstr(str
, ",") == NULL
) )
454 printf("regapi: WARNING converting CSV hex stream with no comma, "
455 "input data seems invalid.\n");
457 while (strPos
< strLen
)
462 memcpy(xbuf
,s
,2); xbuf
[3]='\0';
463 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
464 *b
++ =(unsigned char)wc
;
475 /******************************************************************************
476 * Sets the value in argv[0] to the data in argv[1] for the currently
479 static HRESULT
setValue(LPSTR
*argv
)
482 DWORD dwSize
= KEY_MAX_LEN
;
484 DWORD dwDataType
,dwParseType
;
486 LPSTR lpsCurrentValue
;
488 LPSTR keyValue
= getArg(argv
[0]);
489 LPSTR keyData
= argv
[1];
491 /* Make some checks */
492 if ( (keyValue
== NULL
) || (keyData
== NULL
) )
493 return ERROR_INVALID_PARAMETER
;
495 lpsCurrentValue
=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN
);
497 * Default registry values are encoded in the input stream as '@' but as
498 * blank in the wine registry.
500 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
503 /* Get the data type stored into the value field */
504 dwDataType
= getDataType(&keyData
,&dwParseType
);
506 memset(lpsCurrentValue
, 0, KEY_MAX_LEN
);
507 hRes
= RegQueryValueExA(
512 (LPBYTE
)lpsCurrentValue
,
515 while(hRes
==ERROR_MORE_DATA
){
517 lpsCurrentValue
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsCurrentValue
,dwSize
);
518 hRes
= RegQueryValueExA(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpsCurrentValue
,&dwSize
);
521 if( ( strlen(lpsCurrentValue
) == 0 ) || /* The value is not existing */
522 ( bForce
)) /* -force option */
525 BYTE convert
[KEY_MAX_LEN
];
528 if ( dwParseType
== REG_SZ
) /* no conversion for string */
530 dwLen
= strlen(keyData
);
531 if (dwLen
>0 && keyData
[dwLen
-1]=='"')
538 else if (dwParseType
== REG_DWORD
) /* Convert the dword types */
540 dwLen
= convertHexToDWord(keyData
, convert
);
543 else /* Convert the hexadecimal types */
545 dwLen
= convertHexCSVToHex(keyData
, convert
, KEY_MAX_LEN
);
549 hRes
= RegSetValueEx(
559 /* return the current value data into argv[1] */
562 HeapFree(GetProcessHeap(), 0, argv
[1]);
563 argv
[1] = HeapAlloc(GetProcessHeap(), 0, dwSize
+1);
565 if ( argv
[1] != NULL
) {
566 strncpy(argv
[1], lpsCurrentValue
, dwSize
);
567 argv
[1][dwSize
]='\0';
571 hRes
=KEY_VALUE_ALREADY_SET
;
573 if (keyValue
!= NULL
)
574 HeapFree(GetProcessHeap(), 0, keyValue
);
579 /******************************************************************************
582 static HRESULT
openKey( LPSTR stdInput
)
588 if (stdInput
== NULL
)
589 return ERROR_INVALID_PARAMETER
;
591 /* Get the registry class */
592 currentKeyClass
= getRegClass(stdInput
); /* Sets global variable */
593 if (currentKeyClass
== (HKEY
)ERROR_INVALID_PARAMETER
)
594 return (HRESULT
)ERROR_INVALID_PARAMETER
;
596 /* Get the key name */
597 currentKeyName
= getRegKeyName(stdInput
); /* Sets global variable */
598 if (currentKeyName
== NULL
)
599 return ERROR_INVALID_PARAMETER
;
601 hRes
= RegCreateKeyEx(
602 currentKeyClass
, /* Class */
603 currentKeyName
, /* Sub Key */
605 NULL
, /* object type */
606 REG_OPTION_NON_VOLATILE
, /* option, REG_OPTION_NON_VOLATILE ... */
607 KEY_ALL_ACCESS
, /* access mask, KEY_ALL_ACCESS */
608 NULL
, /* security attribute */
609 ¤tKeyHandle
, /* result */
610 &dwDisp
); /* disposition, REG_CREATED_NEW_KEY or
611 REG_OPENED_EXISTING_KEY */
613 if (hRes
== ERROR_SUCCESS
)
614 bTheKeyIsOpen
= TRUE
;
619 /******************************************************************************
620 * This function is a wrapper for the setValue function. It prepares the
621 * land and clean the area once completed.
623 static void processSetValue(LPSTR cmdline
)
625 LPSTR argv
[SET_VALUE_MAX_ARGS
]; /* args storage */
627 LPSTR token
= NULL
; /* current token analyzed */
628 ULONG argCounter
= 0; /* counter of args */
633 * Init storage and parse the line
635 for (counter
=0; counter
<SET_VALUE_MAX_ARGS
; counter
++)
638 while( (token
= getToken(&cmdline
, setValueDelim
[argCounter
])) != NULL
)
640 argv
[argCounter
++] = token
;
642 if (argCounter
== SET_VALUE_MAX_ARGS
)
643 break; /* Stop processing args no matter what */
646 hRes
= setValue(argv
);
647 if ( hRes
== ERROR_SUCCESS
)
649 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
654 else if ( hRes
== KEY_VALUE_ALREADY_SET
)
656 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
662 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
668 /******************************************************************************
669 * This function is a wrapper for the queryValue function. It prepares the
670 * land and clean the area once completed.
672 static void processQueryValue(LPSTR cmdline
)
674 LPSTR argv
[QUERY_VALUE_MAX_ARGS
];/* args storage */
675 LPSTR token
= NULL
; /* current token analyzed */
676 ULONG argCounter
= 0; /* counter of args */
679 LPSTR keyValue
= NULL
;
683 * Init storage and parse the line
685 for (counter
=0; counter
<QUERY_VALUE_MAX_ARGS
; counter
++)
688 while( (token
= getToken(&cmdline
, queryValueDelim
[argCounter
])) != NULL
)
690 argv
[argCounter
++] = getArg(token
);
692 if (argCounter
== QUERY_VALUE_MAX_ARGS
)
693 break; /* Stop processing args no matter what */
696 /* The value we look for is the first token on the line */
697 if ( argv
[0] == NULL
)
698 return; /* SHOULD NOT HAPPEN */
702 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
704 LONG lLen
= KEY_MAX_LEN
;
705 CHAR
* lpsData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
707 * We need to query the key default value
709 hRes
= RegQueryValue(
715 if (hRes
==ERROR_MORE_DATA
) {
716 lpsData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsData
,lLen
);
717 hRes
= RegQueryValue(currentKeyHandle
,currentKeyName
,(LPBYTE
)lpsData
,&lLen
);
720 if (hRes
== ERROR_SUCCESS
)
722 lpsRes
= HeapAlloc( GetProcessHeap(), 0, lLen
);
723 strncpy(lpsRes
, lpsData
, lLen
);
726 HeapFree(GetProcessHeap(), 0, lpsData
);
730 DWORD dwLen
= KEY_MAX_LEN
;
731 BYTE
* lpbData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
734 * We need to query a specific value for the key
736 hRes
= RegQueryValueEx(
744 if (hRes
==ERROR_MORE_DATA
) {
745 lpbData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpbData
,dwLen
);
746 hRes
= RegQueryValueEx(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpbData
,&dwLen
);
749 if (hRes
== ERROR_SUCCESS
)
752 * Convert the returned data to a displayable format
759 lpsRes
= HeapAlloc( GetProcessHeap(), 0, dwLen
);
760 strncpy(lpsRes
, lpbData
, dwLen
);
761 lpsRes
[dwLen
-1]='\0';
766 lpsRes
= convertHexToDWORDStr(lpbData
, dwLen
);
771 lpsRes
= convertHexToHexCSV(lpbData
, dwLen
);
777 HeapFree(GetProcessHeap(), 0, lpbData
);
781 if ( hRes
== ERROR_SUCCESS
)
783 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
789 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
796 for (counter
=0; counter
<argCounter
; counter
++)
797 if (argv
[counter
] != NULL
)
798 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
801 HeapFree(GetProcessHeap(), 0, lpsRes
);
805 /******************************************************************************
806 * Close the currently opened key.
808 static void closeKey()
810 RegCloseKey(currentKeyHandle
);
812 HeapFree(GetProcessHeap(), 0, currentKeyName
); /* Allocated by getKeyName */
814 bTheKeyIsOpen
= FALSE
;
816 currentKeyName
= NULL
;
818 currentKeyHandle
= 0;
821 /******************************************************************************
822 * This funtion is the main entry point to the setValue type of action. It
823 * receives the currently read line and dispatch the work depending on the
826 static void doSetValue(LPSTR stdInput
)
829 * We encoutered the end of the file, make sure we
830 * close the opened key and exit
832 if (stdInput
== NULL
)
834 if (bTheKeyIsOpen
!= FALSE
)
840 if ( stdInput
[0] == '[') /* We are reading a new key */
842 if ( bTheKeyIsOpen
!= FALSE
)
843 closeKey(); /* Close the previous key before */
845 if ( openKey(stdInput
) != ERROR_SUCCESS
)
846 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
848 else if( ( bTheKeyIsOpen
) &&
849 (( stdInput
[0] == '@') || /* reading a default @=data pair */
850 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
852 processSetValue(stdInput
);
854 else /* since we are assuming that the */
855 { /* file format is valid we must */
856 if ( bTheKeyIsOpen
) /* be reading a blank line which */
857 closeKey(); /* indicate end of this key processing */
861 /******************************************************************************
862 * This funtion is the main entry point to the queryValue type of action. It
863 * receives the currently read line and dispatch the work depending on the
866 static void doQueryValue(LPSTR stdInput
) {
868 * We encoutered the end of the file, make sure we
869 * close the opened key and exit
871 if (stdInput
== NULL
)
873 if (bTheKeyIsOpen
!= FALSE
)
879 if ( stdInput
[0] == '[') /* We are reading a new key */
881 if ( bTheKeyIsOpen
!= FALSE
)
882 closeKey(); /* Close the previous key before */
884 if ( openKey(stdInput
) != ERROR_SUCCESS
)
885 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
887 else if( ( bTheKeyIsOpen
) &&
888 (( stdInput
[0] == '@') || /* reading a default @=data pair */
889 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
891 processQueryValue(stdInput
);
893 else /* since we are assuming that the */
894 { /* file format is valid we must */
895 if ( bTheKeyIsOpen
) /* be reading a blank line which */
896 closeKey(); /* indicate end of this key processing */
900 /******************************************************************************
901 * This funtion is the main entry point to the deletetValue type of action. It
902 * receives the currently read line and dispatch the work depending on the
905 static void doDeleteValue(LPSTR line
) {
906 printf ("regapi: deleteValue not yet implemented\n");
908 /******************************************************************************
909 * This funtion is the main entry point to the deleteKey type of action. It
910 * receives the currently read line and dispatch the work depending on the
913 static void doDeleteKey(LPSTR line
) {
914 printf ("regapi: deleteKey not yet implemented\n");
916 /******************************************************************************
917 * This funtion is the main entry point to the createKey type of action. It
918 * receives the currently read line and dispatch the work depending on the
921 static void doCreateKey(LPSTR line
) {
922 printf ("regapi: createKey not yet implemented\n");
925 /******************************************************************************
926 * This funtion is the main entry point to the registerDLL action. It
927 * receives the currently read line, then loads and registers the requested DLLs
929 static void doRegisterDLL(LPSTR stdInput
) {
933 /* Check for valid input */
934 if (stdInput
== NULL
)
937 /* Load and register the library, then free it */
938 theLib
= LoadLibrary(stdInput
);
941 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllRegisterServer");
943 retVal
= (*lpfnDLLRegProc
)();
945 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput
);
948 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
954 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
958 /******************************************************************************
959 * This funtion is the main entry point to the unregisterDLL action. It
960 * receives the currently read line, then loads and unregisters the requested DLLs
962 static void doUnregisterDLL(LPSTR stdInput
) {
966 /* Check for valid input */
967 if (stdInput
== NULL
)
970 /* Load and unregister the library, then free it */
971 theLib
= LoadLibrary(stdInput
);
974 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllUnregisterServer");
976 retVal
= (*lpfnDLLRegProc
)();
978 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput
);
981 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
987 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
991 /******************************************************************************
992 * MAIN - WinMain simply validates the first parameter (command to perform)
993 * It then reads the STDIN line by line forwarding their processing
994 * to the appropriate method.
996 int PASCAL
WinMain(HINSTANCE inst
, HINSTANCE prev
, LPSTR cmdline
, int show
)
998 LPSTR token
= NULL
; /* current token analyzed */
999 LPSTR stdInput
= NULL
; /* line read from stdin */
1000 INT cmdIndex
= -1; /* index of the command in array */
1001 LPSTR nextLine
= NULL
;
1002 ULONG currentSize
= STDIN_MAX_LEN
;
1004 stdInput
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1005 nextLine
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1007 if (stdInput
== NULL
|| nextLine
== NULL
)
1008 return NOT_ENOUGH_MEMORY
;
1011 * get the command, should be the first arg (modify cmdLine)
1013 token
= getToken(&cmdline
, " ");
1016 cmdIndex
= getCommand(token
);
1017 if (cmdIndex
== COMMAND_NOT_FOUND
)
1019 printf("regapi: Command \"%s\" is not supported.\n", token
);
1021 return COMMAND_NOT_SUPPORTED
;
1027 "regapi: The first item on the command line must be the command name.\n");
1029 return COMMAND_NOT_SUPPORTED
;
1033 * check to see wether we force the action
1034 * (meaning differs depending on the command performed)
1036 if ( cmdline
!= NULL
) /* will be NULL if '-force' is not provided */
1037 if ( strstr(cmdline
, "-force") != NULL
)
1040 printf("Processing stdin...\n");
1047 ULONG curSize
=STDIN_MAX_LEN
;
1050 while((NULL
!=(stdInput
=fgets(stdInput
,curSize
,stdin
))) && (NULL
==(s
=strchr(stdInput
,'\n'))) ){
1051 fseek(stdin
,-curSize
,SEEK_CUR
+1);
1052 stdInput
=HeapReAlloc(GetProcessHeap(), 0,stdInput
,curSize
+=STDIN_MAX_LEN
);
1055 * Make some handy generic stuff here...
1057 if ( stdInput
!= NULL
)
1059 stdInput
[strlen(stdInput
) -1] = '\0'; /* get rid of new line */
1061 if( stdInput
[0] == '#' ) /* this is a comment, skip */
1064 while( stdInput
[strlen(stdInput
) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1065 /* that this line is not complete and we have to get */
1066 stdInput
[strlen(stdInput
) -1]= '\0'; /* the rest in the next lines */
1068 nextLine
= fgets(nextLine
, STDIN_MAX_LEN
, stdin
);
1070 nextLine
[strlen(nextLine
)-1] = '\0';
1072 if ( (strlen(stdInput
)+strlen(nextLine
)) > currentSize
){
1074 stdInput
=HeapReAlloc(GetProcessHeap(),0,stdInput
,strlen(stdInput
)+STDIN_MAX_LEN
);
1076 currentSize
+=STDIN_MAX_LEN
;
1079 strcat(stdInput
,nextLine
+2);
1085 * We process every line, even the NULL (last) line, to indicate the
1086 * end of the processing to the specific process.
1088 commandAPIs
[cmdIndex
](stdInput
);
1090 if (stdInput
== NULL
) /* EOF encountered */
1096 * Save the registry only if it was modified
1098 if ( commandSaveRegistry
[cmdIndex
] != FALSE
)
1099 SHELL_SaveRegistry();
1101 HeapFree(GetProcessHeap(), 0, nextLine
);
1103 HeapFree(GetProcessHeap(), 0, stdInput
);