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
] = {
107 * This array controls the registry saving needs at the end of the process
109 static const BOOL commandSaveRegistry
[COMMAND_COUNT
] = {
122 static DWORD
getDataType(LPSTR
*lpValue
, DWORD
* parse_type
);
123 static LPSTR
getRegKeyName(LPSTR lpLine
);
124 static HKEY
getRegClass(LPSTR lpLine
);
125 static LPSTR
getArg(LPSTR arg
);
126 static INT
getCommand(LPSTR commandName
);
127 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
);
128 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
);
129 static LPSTR
convertHexToHexCSV( BYTE
*buf
, ULONG len
);
130 static LPSTR
convertHexToDWORDStr( BYTE
*buf
, ULONG len
);
131 static HRESULT
openKey(LPSTR stdInput
);
132 static void closeKey();
135 * api setValue prototypes
137 static void processSetValue(LPSTR cmdline
);
138 static HRESULT
setValue(LPSTR
*argv
);
141 * api queryValue prototypes
143 static void processQueryValue(LPSTR cmdline
);
146 * Help Text displayed when invalid parameters are provided
148 static char helpText
[] =
150 " regapi - perform certain actions on the wine registry.\n"
153 " regapi commandName [-force] < file\n"
156 " regapi modifies settings in the wine registry. It processes\n"
157 " the given commandName for every line in the stdin data stream.\n"
158 " Input data format may vary depending on the commandName\n"
159 " (see INPUT FILE FORMAT).\n"
163 " Instruct regapi about what action to perform on the data stream.\n"
164 " Currently, only setValue and queryValue are supported and\n"
168 " When provided the action will be performed anyway. This may\n"
169 " have a different meaning depending on the context. For example,\n"
170 " when providing -force to setValue, the value is set even if it\n"
171 " was previously set to another value.\n"
174 " STDIN channel, provide a file name with line of the appropriate\n"
177 "INPUT FILE FORMAT\n"
180 " The input file is in format, obtained from regedit.exe export.\n"
182 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
183 " \"Value1\"=\"Data1\"\n"
184 " \"Value2\"=\"Data2\"\n"
185 " \"Valuen\"=\"Datan\"\n"
189 " The input file format required by the queryValue command is\n"
190 " similar to the one required by setValue. The only\n"
191 " difference is that you only provide the value name.\n"
193 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
199 " The input file format is a list of DLLs to register\n"
202 " The input file format is a list of DLLs to unregister\n"
207 /******************************************************************************
208 * This function returns the HKEY associated with the data type encoded in the
209 * value. It modifies the input parameter (key value) in order to skip this
210 * "now useless" data type information.
212 * Note: Updated based on the algorithm used in 'server/registry.c'
214 DWORD
getDataType(LPSTR
*lpValue
, DWORD
* parse_type
)
216 struct data_type
{ const char *tag
; int len
; int type
; int parse_type
; };
218 static const struct data_type data_types
[] =
219 { /* actual type */ /* type to assume for parsing */
220 { "\"", 1, REG_SZ
, REG_SZ
},
221 { "str:\"", 5, REG_SZ
, REG_SZ
},
222 { "str(2):\"", 8, REG_EXPAND_SZ
, REG_SZ
},
223 { "str(7):\"", 8, REG_MULTI_SZ
, REG_SZ
},
224 { "hex:", 4, REG_BINARY
, REG_BINARY
},
225 { "dword:", 6, REG_DWORD
, REG_DWORD
},
226 { "hex(", 4, -1, REG_BINARY
},
230 const struct data_type
*ptr
;
233 for (ptr
= data_types
; ptr
->tag
; ptr
++)
235 if (memcmp( ptr
->tag
, *lpValue
, ptr
->len
))
239 *parse_type
= ptr
->parse_type
;
244 /* "hex(xx):" is special */
246 type
= (int)strtoul( *lpValue
, &end
, 16 );
247 if (**lpValue
=='\0' || *end
!=')' || *(end
+1)!=':') {
255 return (**lpValue
=='\0'?REG_SZ
:REG_NONE
);
258 /******************************************************************************
259 * Extracts from a [HKEY\some\key\path] type of line the key name (what starts
260 * after the first '\' and end before the ']'
262 LPSTR
getRegKeyName(LPSTR lpLine
)
264 LPSTR keyNameBeg
= NULL
;
265 LPSTR keyNameEnd
= NULL
;
266 char lpLineCopy
[KEY_MAX_LEN
];
271 strcpy(lpLineCopy
, lpLine
);
273 keyNameBeg
= strstr(lpLineCopy
, "\\"); /* The key name start by '\' */
274 keyNameBeg
++; /* but is not part of the key name */
275 keyNameEnd
= strstr(lpLineCopy
, "]"); /* The key name end by ']' */
276 *keyNameEnd
= '\0'; /* Isolate the key name */
278 currentKeyName
= HeapAlloc(GetProcessHeap(), 0, strlen(keyNameBeg
)+1);
279 if (currentKeyName
!= NULL
)
280 strcpy(currentKeyName
, keyNameBeg
);
282 return currentKeyName
;
285 /******************************************************************************
286 * Extracts from a [HKEY/some/key/path] type of line the key class (what
287 * starts after the '[' and ends before the first '\'
289 static HKEY
getRegClass(LPSTR lpClass
)
294 char lpClassCopy
[KEY_MAX_LEN
];
297 return (HKEY
)ERROR_INVALID_PARAMETER
;
299 strcpy(lpClassCopy
, lpClass
);
301 classNameEnd
= strstr(lpClassCopy
, "\\"); /* The class name end by '\' */
302 *classNameEnd
= '\0'; /* Isolate the class name */
303 classNameBeg
= &lpClassCopy
[1]; /* Skip the '[' */
305 if (strcmp( classNameBeg
, "HKEY_LOCAL_MACHINE") == IDENTICAL
)
306 return HKEY_LOCAL_MACHINE
;
307 else if (strcmp( classNameBeg
, "HKEY_USERS") == IDENTICAL
)
309 else if (strcmp( classNameBeg
, "HKEY_CLASSES_ROOT") == IDENTICAL
)
310 return HKEY_CLASSES_ROOT
;
311 else if (strcmp( classNameBeg
, "HKEY_CURRENT_CONFIG") == IDENTICAL
)
312 return HKEY_CURRENT_CONFIG
;
313 else if (strcmp( classNameBeg
, "HKEY_CURRENT_USER") == IDENTICAL
)
314 return HKEY_CURRENT_USER
;
316 return (HKEY
)ERROR_INVALID_PARAMETER
;
319 /******************************************************************************
320 * This is a replacement for strsep which is not portable (missing on Solaris).
322 static char* getToken(char** str
, const char* delims
)
332 while (**str
!='\0') {
333 if (strchr(delims
,**str
)!=NULL
) {
340 /* There is no other token */
345 /******************************************************************************
346 * Returns an allocated buffer with a cleaned copy (removed the surrounding
347 * dbl quotes) of the passed value.
349 static LPSTR
getArg( LPSTR arg
)
358 * Get rid of surrounding quotes
362 if( arg
[len
-1] == '\"' ) arg
[len
-1] = '\0';
363 if( arg
[0] == '\"' ) arg
++;
365 tmp
= HeapAlloc(GetProcessHeap(), 0, strlen(arg
)+1);
371 /******************************************************************************
372 * Returns the index in the commands array of the command to process.
374 static INT
getCommand(LPSTR commandName
)
377 for (count
=0; count
< COMMAND_COUNT
; count
++)
378 if ( strcmp(commandName
, commandNames
[count
]) == IDENTICAL
)
381 return COMMAND_NOT_FOUND
;
384 /******************************************************************************
385 * Converts a hex representation of a DWORD into a DWORD.
387 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
)
394 sscanf(xbuf
,"%08lx",&dw
);
395 memcpy(buf
,&dw
,sizeof(DWORD
));
396 return sizeof(DWORD
);
399 /******************************************************************************
400 * Converts a hex buffer into a hex comma separated values
402 static char* convertHexToHexCSV(BYTE
*buf
, ULONG bufLen
)
410 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
+1)*2);
411 memset(str
, 0, (bufLen
+1)*2);
412 ptrStr
= str
; /* Pointer to result */
413 ptrBuf
= buf
; /* Pointer to current */
415 while (current
< bufLen
)
417 BYTE bCur
= ptrBuf
[current
++];
420 sprintf(res
, "%02x", (unsigned int)*&bCur
);
425 /* Get rid of the last comma */
426 str
[strlen(str
)-1] = '\0';
430 /******************************************************************************
431 * Converts a hex buffer into a DWORD string
433 static char* convertHexToDWORDStr(BYTE
*buf
, ULONG bufLen
)
438 if ( bufLen
!= sizeof(DWORD
) ) return NULL
;
440 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
*2)+1);
442 memcpy(&dw
,buf
,sizeof(DWORD
));
443 sprintf(str
, "%08lx", dw
);
445 /* Get rid of the last comma */
448 /******************************************************************************
449 * Converts a hex comma separated values list into a hex list.
451 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
)
453 char *s
= str
; /* Pointer to current */
454 char *b
= buf
; /* Pointer to result */
456 ULONG strLen
= strlen(str
);
460 memset(buf
, 0, bufLen
);
463 * warn the user if we are here with a string longer than 2 bytes that does
464 * not contains ",". It is more likely because the data is invalid.
466 if ( ( strlen(str
) > 2) && ( strstr(str
, ",") == NULL
) )
467 printf("regapi: WARNING converting CSV hex stream with no comma, "
468 "input data seems invalid.\n");
470 while (strPos
< strLen
)
475 memcpy(xbuf
,s
,2); xbuf
[3]='\0';
476 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
477 *b
++ =(unsigned char)wc
;
488 /******************************************************************************
489 * Sets the value in argv[0] to the data in argv[1] for the currently
492 static HRESULT
setValue(LPSTR
*argv
)
495 DWORD dwSize
= KEY_MAX_LEN
;
497 DWORD dwDataType
,dwParseType
;
499 LPSTR lpsCurrentValue
;
501 LPSTR keyValue
= getArg(argv
[0]);
502 LPSTR keyData
= argv
[1];
504 /* Make some checks */
505 if ( (keyValue
== NULL
) || (keyData
== NULL
) )
506 return ERROR_INVALID_PARAMETER
;
508 lpsCurrentValue
=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN
);
510 * Default registry values are encoded in the input stream as '@' but as
511 * blank in the wine registry.
513 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
516 /* Get the data type stored into the value field */
517 dwDataType
= getDataType(&keyData
,&dwParseType
);
519 memset(lpsCurrentValue
, 0, KEY_MAX_LEN
);
520 hRes
= RegQueryValueExA(
525 (LPBYTE
)lpsCurrentValue
,
528 while(hRes
==ERROR_MORE_DATA
){
530 lpsCurrentValue
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsCurrentValue
,dwSize
);
531 hRes
= RegQueryValueExA(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpsCurrentValue
,&dwSize
);
534 if( ( strlen(lpsCurrentValue
) == 0 ) || /* The value is not existing */
535 ( bForce
)) /* -force option */
538 BYTE convert
[KEY_MAX_LEN
];
541 if ( dwParseType
== REG_SZ
) /* no conversion for string */
543 dwLen
= strlen(keyData
);
544 if (dwLen
>0 && keyData
[dwLen
-1]=='"')
551 else if (dwParseType
== REG_DWORD
) /* Convert the dword types */
553 dwLen
= convertHexToDWord(keyData
, convert
);
556 else /* Convert the hexadecimal types */
558 dwLen
= convertHexCSVToHex(keyData
, convert
, KEY_MAX_LEN
);
562 hRes
= RegSetValueEx(
572 /* return the current value data into argv[1] */
575 HeapFree(GetProcessHeap(), 0, argv
[1]);
576 argv
[1] = HeapAlloc(GetProcessHeap(), 0, dwSize
+1);
578 if ( argv
[1] != NULL
) {
579 strncpy(argv
[1], lpsCurrentValue
, dwSize
);
580 argv
[1][dwSize
]='\0';
584 hRes
=KEY_VALUE_ALREADY_SET
;
586 if (keyValue
!= NULL
)
587 HeapFree(GetProcessHeap(), 0, keyValue
);
592 /******************************************************************************
595 static HRESULT
openKey( LPSTR stdInput
)
601 if (stdInput
== NULL
)
602 return ERROR_INVALID_PARAMETER
;
604 /* Get the registry class */
605 currentKeyClass
= getRegClass(stdInput
); /* Sets global variable */
606 if (currentKeyClass
== (HKEY
)ERROR_INVALID_PARAMETER
)
607 return (HRESULT
)ERROR_INVALID_PARAMETER
;
609 /* Get the key name */
610 currentKeyName
= getRegKeyName(stdInput
); /* Sets global variable */
611 if (currentKeyName
== NULL
)
612 return ERROR_INVALID_PARAMETER
;
614 hRes
= RegCreateKeyEx(
615 currentKeyClass
, /* Class */
616 currentKeyName
, /* Sub Key */
618 NULL
, /* object type */
619 REG_OPTION_NON_VOLATILE
, /* option, REG_OPTION_NON_VOLATILE ... */
620 KEY_ALL_ACCESS
, /* access mask, KEY_ALL_ACCESS */
621 NULL
, /* security attribute */
622 ¤tKeyHandle
, /* result */
623 &dwDisp
); /* disposition, REG_CREATED_NEW_KEY or
624 REG_OPENED_EXISTING_KEY */
626 if (hRes
== ERROR_SUCCESS
)
627 bTheKeyIsOpen
= TRUE
;
632 /******************************************************************************
633 * This function is a wrapper for the setValue function. It prepares the
634 * land and clean the area once completed.
636 static void processSetValue(LPSTR cmdline
)
638 LPSTR argv
[SET_VALUE_MAX_ARGS
]; /* args storage */
640 LPSTR token
= NULL
; /* current token analized */
641 ULONG argCounter
= 0; /* counter of args */
646 * Init storage and parse the line
648 for (counter
=0; counter
<SET_VALUE_MAX_ARGS
; counter
++)
651 while( (token
= getToken(&cmdline
, setValueDelim
[argCounter
])) != NULL
)
653 argv
[argCounter
++] = token
;
655 if (argCounter
== SET_VALUE_MAX_ARGS
)
656 break; /* Stop processing args no matter what */
659 hRes
= setValue(argv
);
660 if ( hRes
== ERROR_SUCCESS
)
662 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
667 else if ( hRes
== KEY_VALUE_ALREADY_SET
)
669 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
675 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
681 /******************************************************************************
682 * This function is a wrapper for the queryValue function. It prepares the
683 * land and clean the area once completed.
685 static void processQueryValue(LPSTR cmdline
)
687 LPSTR argv
[QUERY_VALUE_MAX_ARGS
];/* args storage */
688 LPSTR token
= NULL
; /* current token analized */
689 ULONG argCounter
= 0; /* counter of args */
692 LPSTR keyValue
= NULL
;
696 * Init storage and parse the line
698 for (counter
=0; counter
<QUERY_VALUE_MAX_ARGS
; counter
++)
701 while( (token
= getToken(&cmdline
, queryValueDelim
[argCounter
])) != NULL
)
703 argv
[argCounter
++] = getArg(token
);
705 if (argCounter
== QUERY_VALUE_MAX_ARGS
)
706 break; /* Stop processing args no matter what */
709 /* The value we look for is the first token on the line */
710 if ( argv
[0] == NULL
)
711 return; /* SHOULD NOT HAPPEN */
715 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
717 LONG lLen
= KEY_MAX_LEN
;
718 CHAR
* lpsData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
720 * We need to query the key default value
722 hRes
= RegQueryValue(
728 if (hRes
==ERROR_MORE_DATA
) {
729 lpsData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsData
,lLen
);
730 hRes
= RegQueryValue(currentKeyHandle
,currentKeyName
,(LPBYTE
)lpsData
,&lLen
);
733 if (hRes
== ERROR_SUCCESS
)
735 lpsRes
= HeapAlloc( GetProcessHeap(), 0, lLen
);
736 strncpy(lpsRes
, lpsData
, lLen
);
742 DWORD dwLen
= KEY_MAX_LEN
;
743 BYTE
* lpbData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
746 * We need to query a specific value for the key
748 hRes
= RegQueryValueEx(
756 if (hRes
==ERROR_MORE_DATA
) {
757 lpbData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpbData
,dwLen
);
758 hRes
= RegQueryValueEx(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpbData
,&dwLen
);
761 if (hRes
== ERROR_SUCCESS
)
764 * Convert the returned data to a displayable format
771 lpsRes
= HeapAlloc( GetProcessHeap(), 0, dwLen
);
772 strncpy(lpsRes
, lpbData
, dwLen
);
773 lpsRes
[dwLen
-1]='\0';
778 lpsRes
= convertHexToDWORDStr(lpbData
, dwLen
);
783 lpsRes
= convertHexToHexCSV(lpbData
, dwLen
);
789 HeapFree(GetProcessHeap(), 0, lpbData
);
793 if ( hRes
== ERROR_SUCCESS
)
795 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
801 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
808 for (counter
=0; counter
<argCounter
; counter
++)
809 if (argv
[counter
] != NULL
)
810 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
813 HeapFree(GetProcessHeap(), 0, lpsRes
);
817 /******************************************************************************
818 * Close the currently opened key.
820 static void closeKey()
822 RegCloseKey(currentKeyHandle
);
824 HeapFree(GetProcessHeap(), 0, currentKeyName
); /* Allocated by getKeyName */
826 bTheKeyIsOpen
= FALSE
;
828 currentKeyName
= NULL
;
830 currentKeyHandle
= 0;
833 /******************************************************************************
834 * This funtion is the main entry point to the setValue type of action. It
835 * receives the currently read line and dispatch the work depending on the
838 static void doSetValue(LPSTR stdInput
)
841 * We encoutered the end of the file, make sure we
842 * close the opened key and exit
844 if (stdInput
== NULL
)
846 if (bTheKeyIsOpen
!= FALSE
)
852 if ( stdInput
[0] == '[') /* We are reading a new key */
854 if ( bTheKeyIsOpen
!= FALSE
)
855 closeKey(); /* Close the previous key before */
857 if ( openKey(stdInput
) != ERROR_SUCCESS
)
858 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
860 else if( ( bTheKeyIsOpen
) &&
861 (( stdInput
[0] == '@') || /* reading a default @=data pair */
862 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
864 processSetValue(stdInput
);
866 else /* since we are assuming that the */
867 { /* file format is valid we must */
868 if ( bTheKeyIsOpen
) /* be reading a blank line which */
869 closeKey(); /* indicate end of this key processing */
873 /******************************************************************************
874 * This funtion is the main entry point to the queryValue type of action. It
875 * receives the currently read line and dispatch the work depending on the
878 static void doQueryValue(LPSTR stdInput
) {
880 * We encoutered the end of the file, make sure we
881 * close the opened key and exit
883 if (stdInput
== NULL
)
885 if (bTheKeyIsOpen
!= FALSE
)
891 if ( stdInput
[0] == '[') /* We are reading a new key */
893 if ( bTheKeyIsOpen
!= FALSE
)
894 closeKey(); /* Close the previous key before */
896 if ( openKey(stdInput
) != ERROR_SUCCESS
)
897 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
899 else if( ( bTheKeyIsOpen
) &&
900 (( stdInput
[0] == '@') || /* reading a default @=data pair */
901 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
903 processQueryValue(stdInput
);
905 else /* since we are assuming that the */
906 { /* file format is valid we must */
907 if ( bTheKeyIsOpen
) /* be reading a blank line which */
908 closeKey(); /* indicate end of this key processing */
912 /******************************************************************************
913 * This funtion is the main entry point to the deletetValue type of action. It
914 * receives the currently read line and dispatch the work depending on the
917 static void doDeleteValue(LPSTR line
) {
918 printf ("regapi: deleteValue not yet implemented\n");
920 /******************************************************************************
921 * This funtion is the main entry point to the deleteKey type of action. It
922 * receives the currently read line and dispatch the work depending on the
925 static void doDeleteKey(LPSTR line
) {
926 printf ("regapi: deleteKey not yet implemented\n");
928 /******************************************************************************
929 * This funtion is the main entry point to the createKey type of action. It
930 * receives the currently read line and dispatch the work depending on the
933 static void doCreateKey(LPSTR line
) {
934 printf ("regapi: createKey not yet implemented\n");
937 /******************************************************************************
938 * This funtion is the main entry point to the registerDLL action. It
939 * receives the currently read line, then loads and registers the requested DLLs
941 static void doRegisterDLL(LPSTR stdInput
) {
945 /* Check for valid input */
946 if (stdInput
== NULL
)
949 /* Load and register the library, then free it */
950 theLib
= LoadLibrary(stdInput
);
953 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllRegisterServer");
955 retVal
= (*lpfnDLLRegProc
)();
957 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput
);
960 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
966 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
970 /******************************************************************************
971 * This funtion is the main entry point to the unregisterDLL action. It
972 * receives the currently read line, then loads and unregisters the requested DLLs
974 static void doUnregisterDLL(LPSTR stdInput
) {
978 /* Check for valid input */
979 if (stdInput
== NULL
)
982 /* Load and unregister the library, then free it */
983 theLib
= LoadLibrary(stdInput
);
986 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllUnregisterServer");
988 retVal
= (*lpfnDLLRegProc
)();
990 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput
);
993 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
999 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
1003 /******************************************************************************
1004 * MAIN - WinMain simply validates the first parameter (command to perform)
1005 * It then reads the STDIN line by line forwarding their processing
1006 * to the appropriate method.
1008 int PASCAL
WinMain(HINSTANCE inst
, HINSTANCE prev
, LPSTR cmdline
, int show
)
1010 LPSTR token
= NULL
; /* current token analized */
1011 LPSTR stdInput
= NULL
; /* line read from stdin */
1012 INT cmdIndex
= -1; /* index of the command in array */
1013 LPSTR nextLine
= NULL
;
1014 ULONG currentSize
= STDIN_MAX_LEN
;
1016 stdInput
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1017 nextLine
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1019 if (stdInput
== NULL
|| nextLine
== NULL
)
1020 return NOT_ENOUGH_MEMORY
;
1023 * get the command, should be the first arg (modify cmdLine)
1025 token
= getToken(&cmdline
, " ");
1028 cmdIndex
= getCommand(token
);
1029 if (cmdIndex
== COMMAND_NOT_FOUND
)
1031 printf("regapi: Command \"%s\" is not supported.\n", token
);
1033 return COMMAND_NOT_SUPPORTED
;
1039 "regapi: The first item on the command line must be the command name.\n");
1041 return COMMAND_NOT_SUPPORTED
;
1045 * check to see wether we force the action
1046 * (meaning differs depending on the command performed)
1048 if ( cmdline
!= NULL
) /* will be NULL if '-force' is not provided */
1049 if ( strstr(cmdline
, "-force") != NULL
)
1052 printf("Processing stdin...\n");
1059 ULONG curSize
=STDIN_MAX_LEN
;
1062 while((NULL
!=(stdInput
=fgets(stdInput
,curSize
,stdin
))) && (NULL
==(s
=strchr(stdInput
,'\n'))) ){
1063 fseek(stdin
,-curSize
,SEEK_CUR
+1);
1064 stdInput
=HeapReAlloc(GetProcessHeap(), 0,stdInput
,curSize
+=STDIN_MAX_LEN
);
1067 * Make some handy generic stuff here...
1069 if ( stdInput
!= NULL
)
1071 stdInput
[strlen(stdInput
) -1] = '\0'; /* get rid of new line */
1073 if( stdInput
[0] == '#' ) /* this is a comment, skip */
1076 while( stdInput
[strlen(stdInput
) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1077 /* that this line is not complete and we have to get */
1078 stdInput
[strlen(stdInput
) -1]= '\0'; /* the rest in the next lines */
1080 nextLine
= fgets(nextLine
, STDIN_MAX_LEN
, stdin
);
1082 nextLine
[strlen(nextLine
)-1] = '\0';
1084 if ( (strlen(stdInput
)+strlen(nextLine
)) > currentSize
){
1086 stdInput
=HeapReAlloc(GetProcessHeap(),0,stdInput
,strlen(stdInput
)+STDIN_MAX_LEN
);
1088 currentSize
+=STDIN_MAX_LEN
;
1091 strcat(stdInput
,nextLine
+2);
1097 * We process every lines even the NULL (last) line, to indicate the
1098 * end of the processing to the specific process.
1100 commandAPIs
[cmdIndex
](stdInput
);
1102 if (stdInput
== NULL
) /* EOF encountered */
1108 * Save the registry only if it was modified
1110 if ( commandSaveRegistry
[cmdIndex
] != FALSE
)
1111 SHELL_SaveRegistry();
1113 HeapFree(GetProcessHeap(), 0, nextLine
);
1115 HeapFree(GetProcessHeap(), 0, stdInput
);