2 * Command line Registry implementation
4 * Copyright 1999 Sylvain St-Germain
6 * Note: Please consult the README file for more information.
18 /******************************************************************************
22 #define COMMAND_COUNT 7
24 #define KEY_MAX_LEN 1024
25 #define STDIN_MAX_LEN 2048
28 #define COMMAND_NOT_FOUND -1
30 #define NOT_ENOUGH_MEMORY 1
31 #define KEY_VALUE_ALREADY_SET 2
32 #define COMMAND_NOT_SUPPORTED 3
35 static BOOL bForce
= FALSE
; /* Is set to TRUE when -force is
36 passed on the command line */
38 /* Globals used by the api setValue, queryValue */
39 static LPSTR currentKeyName
= NULL
;
40 static HKEY currentKeyClass
= 0;
41 static HKEY currentKeyHandle
= 0;
42 static BOOL bTheKeyIsOpen
= FALSE
;
44 /* Delimiters used to parse the "value"="data" pair for setValue*/
45 #define SET_VALUE_MAX_ARGS 2
46 /* Delimiters used to parse the "value" to query queryValue*/
47 #define QUERY_VALUE_MAX_ARGS 1
49 static const char *setValueDelim
[SET_VALUE_MAX_ARGS
] = {"=", ""};
50 static const char *queryValueDelim
[QUERY_VALUE_MAX_ARGS
] = {""};
52 /* Array used to extract the data type from a string in getDataType. */
53 typedef struct tagDataTypeMap
59 static const dataTypeMap typeMap
[] =
61 {"hex:", REG_BINARY
},/* could be REG_NONE (?) */
62 {"dword:", REG_DWORD
},
63 {"hex(0):", REG_NONE
},
65 {"hex(2):", REG_EXPAND_SZ
},
66 {"hex(3):", REG_BINARY
},
67 {"hex(4):", REG_DWORD
},
68 {"hex(5):", REG_DWORD_BIG_ENDIAN
},
69 {"hex(6):", REG_LINK
},
70 {"hex(7):", REG_MULTI_SZ
},
71 {"hex(8):", REG_RESOURCE_LIST
},
72 {"hex(9):", REG_FULL_RESOURCE_DESCRIPTOR
},
73 {"hex(10):", REG_RESOURCE_REQUIREMENTS_LIST
},
74 {"hex(80000000):", 0x80000000},
75 {"hex(80000001):", 0x80000001},
76 {"hex(80000002):", 0x80000002},
77 {"hex(80000003):", 0x80000003},
78 {"hex(80000004):", 0x80000004},
79 {"hex(80000005):", 0x80000005},
80 {"hex(80000006):", 0x80000006},
81 {"hex(80000007):", 0x80000007},
82 {"hex(80000008):", 0x80000008},
83 {"hex(80000009):", 0x80000000},
84 {"hex(8000000a):", 0x8000000A}
86 const static int LAST_TYPE_MAP
= sizeof(typeMap
)/sizeof(dataTypeMap
);
92 typedef void (*commandAPI
)(LPSTR lpsLine
);
94 static void doSetValue(LPSTR lpsLine
);
95 static void doDeleteValue(LPSTR lpsLine
);
96 static void doCreateKey(LPSTR lpsLine
);
97 static void doDeleteKey(LPSTR lpsLine
);
98 static void doQueryValue(LPSTR lpsLine
);
99 static void doRegisterDLL(LPSTR lpsLine
);
100 static void doUnregisterDLL(LPSTR lpsLine
);
103 * current supported api
105 static const char* commandNames
[COMMAND_COUNT
] = {
116 * Pointers to processing entry points
118 static const commandAPI commandAPIs
[COMMAND_COUNT
] = {
129 * This array controls the registry saving needs at the end of the process
131 static const BOOL commandSaveRegistry
[COMMAND_COUNT
] = {
144 static DWORD
getDataType(LPSTR
*lpValue
);
145 static LPSTR
getRegKeyName(LPSTR lpLine
);
146 static HKEY
getRegClass(LPSTR lpLine
);
147 static LPSTR
getArg(LPSTR arg
);
148 static INT
getCommand(LPSTR commandName
);
149 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
);
150 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
);
151 static LPSTR
convertHexToHexCSV( BYTE
*buf
, ULONG len
);
152 static LPSTR
convertHexToDWORDStr( BYTE
*buf
, ULONG len
);
153 static HRESULT
openKey(LPSTR stdInput
);
154 static void closeKey();
157 * api setValue prototypes
159 static void processSetValue(LPSTR cmdline
);
160 static HRESULT
setValue(LPSTR
*argv
);
163 * api queryValue prototypes
165 static void processQueryValue(LPSTR cmdline
);
168 * Help Text displayed when invalid parameters are provided
170 static char helpText
[] =
172 " regapi - provide a command line interface to the wine registry.\n"
175 " regapi commandName [-force] < file\n"
178 " regapi allows editing the wine registry. It processes the given\n"
179 " commandName for every line in the stdin data stream. Input data\n"
180 " format may vary depending on the commandName see INPUT FILE FORMAT.\n"
184 " Instruct regapi about what action to perform on the data stream.\n"
185 " Currently, only setValue and queryValue are supported and\n"
189 " When provided the action will be performed anyway. This may\n"
190 " have a different meaning depending on the context. For example,\n"
191 " when providing -force to setValue, the value is set even if it\n"
192 " was previously set to another value.\n"
195 " STDIN channel, provide a file name with line of the appropriate\n"
198 "INPUT FILE FORMAT\n"
201 " The input file format required by the setValue command is similar\n"
202 " to the one obtained from regedit.exe export option. The only\n"
203 " difference is that multi line values are not supported, the\n"
204 " value data must be on a single line.\n"
206 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
207 " \"Value1\"=\"Data1\"\n"
208 " \"Value2\"=\"Data2\"\n"
209 " \"Valuen\"=\"Datan\"\n"
213 " The input file format required by the queryValue command is\n"
214 " similar to the one required by setValue. The only\n"
215 " difference is that you only provide the value name.\n"
217 " [KEY_CLASS\\Some\\Path\\For\\A\\Key]\n"
223 " The input file format is a list of DLLs to register\n"
226 " The input file format is a list of DLLs to unregister\n"
231 /******************************************************************************
232 * This function returns the HKEY associated with the data type encoded in the
233 * value. It modifies the input parameter (key value) in order to skip this
234 * "now useless" data type information.
236 DWORD
getDataType(LPSTR
*lpValue
)
239 DWORD dwReturn
= REG_SZ
;
241 for (; counter
< LAST_TYPE_MAP
; counter
++)
243 LONG len
= strlen(typeMap
[counter
].mask
);
244 if ( strncasecmp( *lpValue
, typeMap
[counter
].mask
, len
) == IDENTICAL
)
247 * We found it, modify the value's pointer in order to skip the data
248 * type identifier, set the return value and exit the loop.
251 dwReturn
= typeMap
[counter
].dataType
;
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 * Returns an allocated buffer with a cleaned copy (removed the surrounding
321 * dbl quotes) of the passed value.
323 static LPSTR
getArg( LPSTR arg
)
332 * Get rid of surrounding quotes
336 if( arg
[len
-1] == '\"' ) arg
[len
-1] = '\0';
337 if( arg
[0] == '\"' ) arg
++;
339 tmp
= HeapAlloc(GetProcessHeap(), 0, strlen(arg
)+1);
345 /******************************************************************************
346 * Returns the index in the commands array of the command to process.
348 static INT
getCommand(LPSTR commandName
)
351 for (count
=0; count
< COMMAND_COUNT
; count
++)
352 if ( strcmp(commandName
, commandNames
[count
]) == IDENTICAL
)
355 return COMMAND_NOT_FOUND
;
358 /******************************************************************************
359 * Converts a hex representation of a DWORD into a DWORD.
361 static DWORD
convertHexToDWord(char *str
, BYTE
*buf
)
363 char *s
= str
; /* Pointer to current */
364 char *b
= buf
; /* Pointer to result */
369 while (strPos
< 4) /* 8 byte in a DWORD */
374 memcpy(xbuf
,s
,2); xbuf
[2]='\0';
375 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
376 *b
++ =(unsigned char)wc
;
382 return 4; /* always 4 byte for the word */
385 /******************************************************************************
386 * Converts a hex buffer into a hex comma separated values
388 static char* convertHexToHexCSV(BYTE
*buf
, ULONG bufLen
)
396 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
+1)*2);
397 memset(str
, 0, (bufLen
+1)*2);
398 ptrStr
= str
; /* Pointer to result */
399 ptrBuf
= buf
; /* Pointer to current */
401 while (current
< bufLen
)
403 BYTE bCur
= ptrBuf
[current
++];
406 sprintf(res
, "%02x", (unsigned int)*&bCur
);
411 /* Get rid of the last comma */
412 str
[strlen(str
)-1] = '\0';
416 /******************************************************************************
417 * Converts a hex buffer into a DWORD string
419 static char* convertHexToDWORDStr(BYTE
*buf
, ULONG bufLen
)
427 str
= HeapAlloc(GetProcessHeap(), 0, (bufLen
*2)+1);
428 memset(str
, 0, (bufLen
*2)+1);
429 ptrStr
= str
; /* Pointer to result */
430 ptrBuf
= buf
; /* Pointer to current */
432 while (current
< bufLen
)
434 BYTE bCur
= ptrBuf
[current
++];
437 sprintf(res
, "%02x", (unsigned int)*&bCur
);
441 /* Get rid of the last comma */
444 /******************************************************************************
445 * Converts a hex comma separated values list into a hex list.
447 static DWORD
convertHexCSVToHex(char *str
, BYTE
*buf
, ULONG bufLen
)
449 char *s
= str
; /* Pointer to current */
450 char *b
= buf
; /* Pointer to result */
452 ULONG strLen
= strlen(str
);
456 memset(buf
, 0, bufLen
);
459 * warn the user if we are here with a string longer than 2 bytes that does
460 * not contains ",". It is more likely because the data is invalid.
462 if ( ( strlen(str
) > 2) && ( strstr(str
, ",") == NULL
) )
463 printf("regapi: WARNING converting CSV hex stream with no comma, "
464 "input data seems invalid.\n");
466 while (strPos
< strLen
)
471 memcpy(xbuf
,s
,2); xbuf
[3]='\0';
472 sscanf(xbuf
,"%02x",(UINT
*)&wc
);
473 *b
++ =(unsigned char)wc
;
484 /******************************************************************************
485 * Sets the value in argv[0] to the data in argv[1] for the currently
488 static HRESULT
setValue(LPSTR
*argv
)
491 DWORD dwSize
= KEY_MAX_LEN
;
495 LPSTR lpsCurrentValue
;
497 LPSTR keyValue
= argv
[0];
498 LPSTR keyData
= argv
[1];
500 /* Make some checks */
501 if ( (keyValue
== NULL
) || (keyData
== NULL
) )
502 return ERROR_INVALID_PARAMETER
;
504 lpsCurrentValue
=HeapAlloc(GetProcessHeap(), 0,KEY_MAX_LEN
);
506 * Default registry values are encoded in the input stream as '@' but as
507 * blank in the wine registry.
509 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
512 /* Get the data type stored into the value field */
513 dwDataType
= getDataType(&keyData
);
515 memset(lpsCurrentValue
, 0, KEY_MAX_LEN
);
516 hRes
= RegQueryValueExA(
521 (LPBYTE
)lpsCurrentValue
,
524 while(hRes
==ERROR_MORE_DATA
){
526 lpsCurrentValue
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsCurrentValue
,dwSize
);
527 hRes
= RegQueryValueExA(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpsCurrentValue
,&dwSize
);
530 if( ( strlen(lpsCurrentValue
) == 0 ) || /* The value is not existing */
531 ( bForce
)) /* -force option */
534 BYTE convert
[KEY_MAX_LEN
];
537 if ( dwDataType
== REG_SZ
) /* no convertion for string */
539 dwLen
= strlen(keyData
);
542 else if (dwDataType
== REG_DWORD
) /* Convert the dword types */
544 dwLen
= convertHexToDWord(keyData
, convert
);
547 else /* Convert the hexadecimal types */
549 dwLen
= convertHexCSVToHex(keyData
, convert
, KEY_MAX_LEN
);
553 hRes
= RegSetValueEx(
563 /* return the current value data into argv[1] */
566 HeapFree(GetProcessHeap(), 0, argv
[1]);
567 argv
[1] = HeapAlloc(GetProcessHeap(), 0, dwSize
+1);
569 if ( argv
[1] != NULL
) {
570 strncpy(argv
[1], lpsCurrentValue
, dwSize
);
571 argv
[1][dwSize
]='\0';
575 return KEY_VALUE_ALREADY_SET
;
581 /******************************************************************************
584 static HRESULT
openKey( LPSTR stdInput
)
590 if (stdInput
== NULL
)
591 return ERROR_INVALID_PARAMETER
;
593 /* Get the registry class */
594 currentKeyClass
= getRegClass(stdInput
); /* Sets global variable */
595 if (currentKeyClass
== (HKEY
)ERROR_INVALID_PARAMETER
)
596 return (HRESULT
)ERROR_INVALID_PARAMETER
;
598 /* Get the key name */
599 currentKeyName
= getRegKeyName(stdInput
); /* Sets global variable */
600 if (currentKeyName
== NULL
)
601 return ERROR_INVALID_PARAMETER
;
603 hRes
= RegCreateKeyEx(
604 currentKeyClass
, /* Class */
605 currentKeyName
, /* Sub Key */
607 NULL
, /* object type */
608 REG_OPTION_NON_VOLATILE
, /* option, REG_OPTION_NON_VOLATILE ... */
609 KEY_ALL_ACCESS
, /* access mask, KEY_ALL_ACCESS */
610 NULL
, /* security attribute */
611 ¤tKeyHandle
, /* result */
612 &dwDisp
); /* disposition, REG_CREATED_NEW_KEY or
613 REG_OPENED_EXISTING_KEY */
615 if (hRes
== ERROR_SUCCESS
)
616 bTheKeyIsOpen
= TRUE
;
621 /******************************************************************************
622 * This function is a wrapper arround the setValue function. It prepares the
623 * land and clean the area once completed.
625 static void processSetValue(LPSTR cmdline
)
627 LPSTR argv
[SET_VALUE_MAX_ARGS
]; /* args storage */
629 LPSTR token
= NULL
; /* current token analized */
630 ULONG argCounter
= 0; /* counter of args */
635 * Init storage and parse the line
637 for (counter
=0; counter
<SET_VALUE_MAX_ARGS
; counter
++)
640 while( (token
= strsep(&cmdline
, setValueDelim
[argCounter
])) != NULL
)
642 argv
[argCounter
++] = getArg(token
);
644 if (argCounter
== SET_VALUE_MAX_ARGS
)
645 break; /* Stop processing args no matter what */
648 hRes
= setValue(argv
);
649 if ( hRes
== ERROR_SUCCESS
)
651 "regapi: Value \"%s\" has been set to \"%s\" in key [%s]\n",
656 else if ( hRes
== KEY_VALUE_ALREADY_SET
)
658 "regapi: Value \"%s\" already set to \"%s\" in key [%s]\n",
664 printf("regapi: ERROR Key %s not created. Value: %s, Data: %s\n",
672 for (counter
=0; counter
<argCounter
; counter
++)
673 if (argv
[counter
] != NULL
)
674 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
677 /******************************************************************************
678 * This function is a wrapper arround the queryValue function. It prepares the
679 * land and clean the area once completed.
681 static void processQueryValue(LPSTR cmdline
)
683 LPSTR argv
[QUERY_VALUE_MAX_ARGS
];/* args storage */
684 LPSTR token
= NULL
; /* current token analized */
685 ULONG argCounter
= 0; /* counter of args */
688 LPSTR keyValue
= NULL
;
692 * Init storage and parse the line
694 for (counter
=0; counter
<QUERY_VALUE_MAX_ARGS
; counter
++)
697 while( (token
= strsep(&cmdline
, queryValueDelim
[argCounter
])) != NULL
)
699 argv
[argCounter
++] = getArg(token
);
701 if (argCounter
== QUERY_VALUE_MAX_ARGS
)
702 break; /* Stop processing args no matter what */
705 /* The value we look for is the first token on the line */
706 if ( argv
[0] == NULL
)
707 return; /* SHOULD NOT OCCURS */
711 if( (keyValue
[0] == '@') && (strlen(keyValue
) == 1) )
713 LONG lLen
= KEY_MAX_LEN
;
714 CHAR
* lpsData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
716 * We need to query the key default value
718 hRes
= RegQueryValue(
724 if (hRes
==ERROR_MORE_DATA
) {
725 lpsData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpsData
,lLen
);
726 hRes
= RegQueryValue(currentKeyHandle
,currentKeyName
,(LPBYTE
)lpsData
,&lLen
);
729 if (hRes
== ERROR_SUCCESS
)
731 lpsRes
= HeapAlloc( GetProcessHeap(), 0, lLen
);
732 strncpy(lpsRes
, lpsData
, lLen
);
738 DWORD dwLen
= KEY_MAX_LEN
;
739 BYTE
* lpbData
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,KEY_MAX_LEN
);
742 * We need to query a specific value for the key
744 hRes
= RegQueryValueEx(
752 if (hRes
==ERROR_MORE_DATA
) {
753 lpbData
=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,lpbData
,dwLen
);
754 hRes
= RegQueryValueEx(currentKeyHandle
,keyValue
,NULL
,&dwType
,(LPBYTE
)lpbData
,&dwLen
);
757 if (hRes
== ERROR_SUCCESS
)
760 * Convert the returned data to a displayable format
767 lpsRes
= HeapAlloc( GetProcessHeap(), 0, dwLen
);
768 strncpy(lpsRes
, lpbData
, dwLen
);
769 lpsRes
[dwLen
-1]='\0';
774 lpsRes
= convertHexToDWORDStr(lpbData
, dwLen
);
779 lpsRes
= convertHexToHexCSV(lpbData
, dwLen
);
785 HeapFree(GetProcessHeap(), 0, lpbData
);
789 if ( hRes
== ERROR_SUCCESS
)
791 "regapi: Value \"%s\" = \"%s\" in key [%s]\n",
797 printf("regapi: ERROR Value \"%s\" not found. for key \"%s\"\n",
804 for (counter
=0; counter
<argCounter
; counter
++)
805 if (argv
[counter
] != NULL
)
806 HeapFree(GetProcessHeap(), 0, argv
[counter
]);
809 HeapFree(GetProcessHeap(), 0, lpsRes
);
813 /******************************************************************************
814 * Close the currently opened key.
816 static void closeKey()
818 RegCloseKey(currentKeyHandle
);
820 HeapFree(GetProcessHeap(), 0, currentKeyName
); /* Allocated by getKeyName */
822 bTheKeyIsOpen
= FALSE
;
824 currentKeyName
= NULL
;
826 currentKeyHandle
= 0;
829 /******************************************************************************
830 * This funtion is the main entry point to the setValue type of action. It
831 * receives the currently read line and dispatch the work depending on the
834 static void doSetValue(LPSTR stdInput
)
837 * We encoutered the end of the file, make sure we
838 * close the opened key and exit
840 if (stdInput
== NULL
)
842 if (bTheKeyIsOpen
!= FALSE
)
848 if ( stdInput
[0] == '[') /* We are reading a new key */
850 if ( bTheKeyIsOpen
!= FALSE
)
851 closeKey(); /* Close the previous key before */
853 if ( openKey(stdInput
) != ERROR_SUCCESS
)
854 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
856 else if( ( bTheKeyIsOpen
) &&
857 (( stdInput
[0] == '@') || /* reading a default @=data pair */
858 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
860 processSetValue(stdInput
);
862 else /* since we are assuming that the */
863 { /* file format is valid we must */
864 if ( bTheKeyIsOpen
) /* be reading a blank line which */
865 closeKey(); /* indicate end of this key processing */
869 /******************************************************************************
870 * This funtion is the main entry point to the queryValue type of action. It
871 * receives the currently read line and dispatch the work depending on the
874 static void doQueryValue(LPSTR stdInput
) {
876 * We encoutered the end of the file, make sure we
877 * close the opened key and exit
879 if (stdInput
== NULL
)
881 if (bTheKeyIsOpen
!= FALSE
)
887 if ( stdInput
[0] == '[') /* We are reading a new key */
889 if ( bTheKeyIsOpen
!= FALSE
)
890 closeKey(); /* Close the previous key before */
892 if ( openKey(stdInput
) != ERROR_SUCCESS
)
893 printf ("regapi: doSetValue failed to open key %s\n", stdInput
);
895 else if( ( bTheKeyIsOpen
) &&
896 (( stdInput
[0] == '@') || /* reading a default @=data pair */
897 ( stdInput
[0] == '\"'))) /* reading a new value=data pair */
899 processQueryValue(stdInput
);
901 else /* since we are assuming that the */
902 { /* file format is valid we must */
903 if ( bTheKeyIsOpen
) /* be reading a blank line which */
904 closeKey(); /* indicate end of this key processing */
908 /******************************************************************************
909 * This funtion is the main entry point to the deletetValue type of action. It
910 * receives the currently read line and dispatch the work depending on the
913 static void doDeleteValue(LPSTR line
) {
914 printf ("regapi: deleteValue not yet implemented\n");
916 /******************************************************************************
917 * This funtion is the main entry point to the deleteKey type of action. It
918 * receives the currently read line and dispatch the work depending on the
921 static void doDeleteKey(LPSTR line
) {
922 printf ("regapi: deleteKey not yet implemented\n");
924 /******************************************************************************
925 * This funtion is the main entry point to the createKey type of action. It
926 * receives the currently read line and dispatch the work depending on the
929 static void doCreateKey(LPSTR line
) {
930 printf ("regapi: createKey not yet implemented\n");
933 /******************************************************************************
934 * This funtion is the main entry point to the registerDLL action. It
935 * receives the currently read line, then loads and registers the requested DLLs
937 static void doRegisterDLL(LPSTR stdInput
) {
941 /* Check for valid input */
942 if (stdInput
== NULL
)
945 /* Load and register the library, then free it */
946 theLib
= LoadLibrary(stdInput
);
949 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllRegisterServer");
951 retVal
= (*lpfnDLLRegProc
)();
953 printf("regapi: Couldn't find DllRegisterServer proc in '%s'.\n", stdInput
);
956 printf("regapi: DLLRegisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
962 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
966 /******************************************************************************
967 * This funtion is the main entry point to the unregisterDLL action. It
968 * receives the currently read line, then loads and unregisters the requested DLLs
970 static void doUnregisterDLL(LPSTR stdInput
) {
974 /* Check for valid input */
975 if (stdInput
== NULL
)
978 /* Load and unregister the library, then free it */
979 theLib
= LoadLibrary(stdInput
);
982 FARPROC lpfnDLLRegProc
= GetProcAddress(theLib
, "DllUnregisterServer");
984 retVal
= (*lpfnDLLRegProc
)();
986 printf("regapi: Couldn't find DllUnregisterServer proc in '%s'.\n", stdInput
);
989 printf("regapi: DLLUnregisterServer error 0x%x in '%s'.\n", retVal
, stdInput
);
995 printf("regapi: Could not load DLL '%s'.\n", stdInput
);
999 /******************************************************************************
1000 * MAIN - The main simply validate the first parameter (command to perform)
1001 * It then read the STDIN lines by lines forwarding their processing
1002 * to the appropriate method.
1004 int PASCAL
WinMain (HINSTANCE inst
, HINSTANCE prev
, LPSTR cmdline
, int show
)
1006 LPSTR token
= NULL
; /* current token analized */
1007 LPSTR stdInput
= NULL
; /* line read from stdin */
1008 INT cmdIndex
= -1; /* index of the command in array */
1009 LPSTR nextLine
= NULL
;
1010 ULONG currentSize
= STDIN_MAX_LEN
;
1012 stdInput
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1013 nextLine
= HeapAlloc(GetProcessHeap(), 0, STDIN_MAX_LEN
);
1015 if (stdInput
== NULL
|| nextLine
== NULL
)
1016 return NOT_ENOUGH_MEMORY
;
1019 * get the command, should be the first arg (modify cmdLine)
1021 token
= strsep(&cmdline
, " ");
1024 cmdIndex
= getCommand(token
);
1025 if (cmdIndex
== COMMAND_NOT_FOUND
)
1027 printf("regapi: Command \"%s\" is not supported.\n", token
);
1029 return COMMAND_NOT_SUPPORTED
;
1035 "regapi: The first item on the command line must be the command name.\n");
1037 return COMMAND_NOT_SUPPORTED
;
1041 * check to see weather we force the action
1042 * (meaning differ depending on the command performed)
1044 if ( cmdline
!= NULL
) /* will be NULL if '-force' is not provided */
1045 if ( strstr(cmdline
, "-force") != NULL
)
1048 printf("Processing stdin...\n");
1055 ULONG curSize
=STDIN_MAX_LEN
;
1058 while((NULL
!=(stdInput
=fgets(stdInput
,curSize
,stdin
))) && (NULL
==(s
=strchr(stdInput
,'\n'))) ){
1059 fseek(stdin
,-curSize
,SEEK_CUR
+1);
1060 stdInput
=HeapReAlloc(GetProcessHeap(), 0,stdInput
,curSize
+=STDIN_MAX_LEN
);
1063 * Make some handy generic stuff here...
1065 if ( stdInput
!= NULL
)
1067 stdInput
[strlen(stdInput
) -1] = '\0'; /* get rid of new line */
1069 if( stdInput
[0] == '#' ) /* this is a comment, skip */
1072 while( stdInput
[strlen(stdInput
) -1] == '\\' ){ /* a '\' char in the end of the current line means */
1073 /* that this line is not complete and we have to get */
1074 stdInput
[strlen(stdInput
) -1]= '\0'; /* the rest in the next lines */
1076 nextLine
= fgets(nextLine
, STDIN_MAX_LEN
, stdin
);
1078 nextLine
[strlen(nextLine
)-1] = '\0';
1080 if ( (strlen(stdInput
)+strlen(nextLine
)) > currentSize
){
1082 stdInput
=HeapReAlloc(GetProcessHeap(),0,stdInput
,strlen(stdInput
)+STDIN_MAX_LEN
);
1084 currentSize
+=STDIN_MAX_LEN
;
1087 strcat(stdInput
,nextLine
+2);
1092 * We process every lines even the NULL (last) line, to indicate the
1093 * end of the processing to the specific process.
1095 commandAPIs
[cmdIndex
](stdInput
);
1097 if (stdInput
== NULL
) /* EOF encountered */
1103 * Save the registry only if it was modified
1105 if ( commandSaveRegistry
[cmdIndex
] != FALSE
)
1106 SHELL_SaveRegistry();
1108 HeapFree(GetProcessHeap(), 0, nextLine
);
1110 HeapFree(GetProcessHeap(), 0, stdInput
);