Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenregproc.c
Go to the documentation of this file.
00001 /* 00002 * Registry processing routines. Routines, common for registry 00003 * processing frontends. 00004 * 00005 * Copyright 1999 Sylvain St-Germain 00006 * Copyright 2002 Andriy Palamarchuk 00007 * Copyright 2008 Alexander N. S?rnes <alex@thehandofagony.com> 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 */ 00023 00024 #include "regedit.h" 00025 00026 #define REG_VAL_BUF_SIZE 4096 00027 00028 /* maximal number of characters in hexadecimal data line, 00029 * including the indentation, but not including the '\' character 00030 */ 00031 #define REG_FILE_HEX_LINE_LEN (2 + 25 * 3) 00032 00033 static const CHAR *reg_class_names[] = 00034 { 00035 "HKEY_LOCAL_MACHINE", "HKEY_USERS", "HKEY_CLASSES_ROOT", 00036 "HKEY_CURRENT_CONFIG", "HKEY_CURRENT_USER", "HKEY_DYN_DATA" 00037 }; 00038 00039 #define REG_CLASS_NUMBER (sizeof(reg_class_names) / sizeof(reg_class_names[0])) 00040 00041 const WCHAR* reg_class_namesW[REG_CLASS_NUMBER] = 00042 { 00043 L"HKEY_LOCAL_MACHINE", L"HKEY_USERS", L"HKEY_CLASSES_ROOT", 00044 L"HKEY_CURRENT_CONFIG", L"HKEY_CURRENT_USER", L"HKEY_DYN_DATA" 00045 }; 00046 00047 static HKEY reg_class_keys[REG_CLASS_NUMBER] = 00048 { 00049 HKEY_LOCAL_MACHINE, HKEY_USERS, HKEY_CLASSES_ROOT, 00050 HKEY_CURRENT_CONFIG, HKEY_CURRENT_USER, HKEY_DYN_DATA 00051 }; 00052 00053 /* return values */ 00054 #define NOT_ENOUGH_MEMORY 1 00055 #define IO_ERROR 2 00056 00057 /* processing macros */ 00058 00059 /* common check of memory allocation results */ 00060 #define CHECK_ENOUGH_MEMORY(p) \ 00061 if (!(p)) \ 00062 { \ 00063 fprintf(stderr,"%s: file %s, line %d: Not enough memory\n", \ 00064 getAppName(), __FILE__, __LINE__); \ 00065 exit(NOT_ENOUGH_MEMORY); \ 00066 } 00067 00068 /****************************************************************************** 00069 * Allocates memory and converts input from multibyte to wide chars 00070 * Returned string must be freed by the caller 00071 */ 00072 WCHAR* GetWideString(const char* strA) 00073 { 00074 if(strA) 00075 { 00076 WCHAR* strW; 00077 int len = MultiByteToWideChar(CP_ACP, 0, strA, -1, NULL, 0); 00078 00079 strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 00080 CHECK_ENOUGH_MEMORY(strW); 00081 MultiByteToWideChar(CP_ACP, 0, strA, -1, strW, len); 00082 return strW; 00083 } 00084 return NULL; 00085 } 00086 00087 /****************************************************************************** 00088 * Allocates memory and converts input from multibyte to wide chars 00089 * Returned string must be freed by the caller 00090 */ 00091 static WCHAR* GetWideStringN(const char* strA, int chars, DWORD *len) 00092 { 00093 if(strA) 00094 { 00095 WCHAR* strW; 00096 *len = MultiByteToWideChar(CP_ACP, 0, strA, chars, NULL, 0); 00097 00098 strW = HeapAlloc(GetProcessHeap(), 0, *len * sizeof(WCHAR)); 00099 CHECK_ENOUGH_MEMORY(strW); 00100 MultiByteToWideChar(CP_ACP, 0, strA, chars, strW, *len); 00101 return strW; 00102 } 00103 *len = 0; 00104 return NULL; 00105 } 00106 00107 /****************************************************************************** 00108 * Allocates memory and converts input from wide chars to multibyte 00109 * Returned string must be freed by the caller 00110 */ 00111 char* GetMultiByteString(const WCHAR* strW) 00112 { 00113 if(strW) 00114 { 00115 char* strA; 00116 int len = WideCharToMultiByte(CP_ACP, 0, strW, -1, NULL, 0, NULL, NULL); 00117 00118 strA = HeapAlloc(GetProcessHeap(), 0, len); 00119 CHECK_ENOUGH_MEMORY(strA); 00120 WideCharToMultiByte(CP_ACP, 0, strW, -1, strA, len, NULL, NULL); 00121 return strA; 00122 } 00123 return NULL; 00124 } 00125 00126 /****************************************************************************** 00127 * Allocates memory and converts input from wide chars to multibyte 00128 * Returned string must be freed by the caller 00129 */ 00130 static char* GetMultiByteStringN(const WCHAR* strW, int chars, DWORD* len) 00131 { 00132 if(strW) 00133 { 00134 char* strA; 00135 *len = WideCharToMultiByte(CP_ACP, 0, strW, chars, NULL, 0, NULL, NULL); 00136 00137 strA = HeapAlloc(GetProcessHeap(), 0, *len); 00138 CHECK_ENOUGH_MEMORY(strA); 00139 WideCharToMultiByte(CP_ACP, 0, strW, chars, strA, *len, NULL, NULL); 00140 return strA; 00141 } 00142 *len = 0; 00143 return NULL; 00144 } 00145 00146 /****************************************************************************** 00147 * Converts a hex representation of a DWORD into a DWORD. 00148 */ 00149 static BOOL convertHexToDWord(WCHAR* str, DWORD *dw) 00150 { 00151 char buf[9]; 00152 char dummy; 00153 00154 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, 9, NULL, NULL); 00155 if (lstrlenW(str) > 8 || sscanf(buf, "%lx%c", dw, &dummy) != 1) 00156 { 00157 fprintf(stderr,"%s: ERROR, invalid hex value\n", getAppName()); 00158 return FALSE; 00159 } 00160 return TRUE; 00161 } 00162 00163 /****************************************************************************** 00164 * Converts a hex comma separated values list into a binary string. 00165 */ 00166 static BYTE* convertHexCSVToHex(WCHAR *str, DWORD *size) 00167 { 00168 WCHAR *s; 00169 BYTE *d, *data; 00170 00171 /* The worst case is 1 digit + 1 comma per byte */ 00172 *size=(lstrlenW(str)+1)/2; 00173 data=HeapAlloc(GetProcessHeap(), 0, *size); 00174 CHECK_ENOUGH_MEMORY(data); 00175 00176 s = str; 00177 d = data; 00178 *size=0; 00179 while (*s != '\0') 00180 { 00181 UINT wc; 00182 WCHAR *end; 00183 00184 wc = wcstoul(s,&end, 16); 00185 if (end == s || wc > 0xff || (*end && *end != L',')) 00186 { 00187 char* strA = GetMultiByteString(s); 00188 fprintf(stderr,"%s: ERROR converting CSV hex stream. Invalid value at '%s'\n", 00189 getAppName(), strA); 00190 HeapFree(GetProcessHeap(), 0, data); 00191 HeapFree(GetProcessHeap(), 0, strA); 00192 return NULL; 00193 } 00194 *d++ =(BYTE)wc; 00195 (*size)++; 00196 if (*end) end++; 00197 s = end; 00198 } 00199 00200 return data; 00201 } 00202 00203 /****************************************************************************** 00204 * This function returns the HKEY associated with the data type encoded in the 00205 * value. It modifies the input parameter (key value) in order to skip this 00206 * "now useless" data type information. 00207 * 00208 * Note: Updated based on the algorithm used in 'server/registry.c' 00209 */ 00210 static DWORD getDataType(LPWSTR *lpValue, DWORD* parse_type) 00211 { 00212 struct data_type 00213 { 00214 const WCHAR *tag; 00215 int len; 00216 int type; 00217 int parse_type; 00218 }; 00219 00220 static const WCHAR quote[] = {'"'}; 00221 static const WCHAR str[] = {'s','t','r',':','"'}; 00222 static const WCHAR str2[] = {'s','t','r','(','2',')',':','"'}; 00223 static const WCHAR hex[] = {'h','e','x',':'}; 00224 static const WCHAR dword[] = {'d','w','o','r','d',':'}; 00225 static const WCHAR hexp[] = {'h','e','x','('}; 00226 00227 static const struct data_type data_types[] = { /* actual type */ /* type to assume for parsing */ 00228 { quote, 1, REG_SZ, REG_SZ }, 00229 { str, 5, REG_SZ, REG_SZ }, 00230 { str2, 8, REG_EXPAND_SZ, REG_SZ }, 00231 { hex, 4, REG_BINARY, REG_BINARY }, 00232 { dword, 6, REG_DWORD, REG_DWORD }, 00233 { hexp, 4, -1, REG_BINARY }, 00234 { NULL, 0, 0, 0 } 00235 }; 00236 00237 const struct data_type *ptr; 00238 int type; 00239 00240 for (ptr = data_types; ptr->tag; ptr++) 00241 { 00242 if (wcsncmp(ptr->tag, *lpValue, ptr->len)) 00243 continue; 00244 00245 /* Found! */ 00246 *parse_type = ptr->parse_type; 00247 type=ptr->type; 00248 *lpValue+=ptr->len; 00249 if (type == -1) 00250 { 00251 WCHAR* end; 00252 00253 /* "hex(xx):" is special */ 00254 type = (int)wcstoul( *lpValue , &end, 16 ); 00255 if (**lpValue=='\0' || *end!=')' || *(end+1)!=':') 00256 { 00257 type=REG_NONE; 00258 } 00259 else 00260 { 00261 *lpValue = end + 2; 00262 } 00263 } 00264 return type; 00265 } 00266 *parse_type=REG_NONE; 00267 return REG_NONE; 00268 } 00269 00270 /****************************************************************************** 00271 * Replaces escape sequences with the characters. 00272 */ 00273 static void REGPROC_unescape_string(WCHAR* str) 00274 { 00275 int str_idx = 0; /* current character under analysis */ 00276 int val_idx = 0; /* the last character of the unescaped string */ 00277 int len = lstrlenW(str); 00278 for (str_idx = 0; str_idx < len; str_idx++, val_idx++) 00279 { 00280 if (str[str_idx] == '\\') 00281 { 00282 str_idx++; 00283 switch (str[str_idx]) 00284 { 00285 case 'n': 00286 str[val_idx] = '\n'; 00287 break; 00288 case '\\': 00289 case '"': 00290 str[val_idx] = str[str_idx]; 00291 break; 00292 default: 00293 fprintf(stderr,"Warning! Unrecognized escape sequence: \\%C'\n", 00294 str[str_idx]); 00295 str[val_idx] = str[str_idx]; 00296 break; 00297 } 00298 } 00299 else 00300 { 00301 str[val_idx] = str[str_idx]; 00302 } 00303 } 00304 str[val_idx] = '\0'; 00305 } 00306 00307 static BOOL parseKeyName(LPWSTR lpKeyName, HKEY *hKey, LPWSTR *lpKeyPath) 00308 { 00309 WCHAR* lpSlash = NULL; 00310 unsigned int i, len; 00311 00312 if (lpKeyName == NULL) 00313 return FALSE; 00314 00315 for(i = 0; *(lpKeyName + i) != 0; i++) 00316 { 00317 if(*(lpKeyName+i) == '\\') 00318 { 00319 lpSlash = lpKeyName + i; 00320 break; 00321 } 00322 } 00323 00324 if (lpSlash) 00325 { 00326 len = lpSlash-lpKeyName; 00327 } 00328 else 00329 { 00330 len = lstrlenW(lpKeyName); 00331 lpSlash = lpKeyName+len; 00332 } 00333 *hKey = NULL; 00334 00335 for (i = 0; i < REG_CLASS_NUMBER; i++) 00336 { 00337 if (CompareStringW(LOCALE_USER_DEFAULT, 0, lpKeyName, len, reg_class_namesW[i], len) == CSTR_EQUAL && 00338 len == lstrlenW(reg_class_namesW[i])) 00339 { 00340 *hKey = reg_class_keys[i]; 00341 break; 00342 } 00343 } 00344 00345 if (*hKey == NULL) 00346 return FALSE; 00347 00348 if (*lpSlash != '\0') 00349 lpSlash++; 00350 *lpKeyPath = lpSlash; 00351 return TRUE; 00352 } 00353 00354 /* Globals used by the setValue() & co */ 00355 static LPSTR currentKeyName; 00356 static HKEY currentKeyHandle = NULL; 00357 00358 /****************************************************************************** 00359 * Sets the value with name val_name to the data in val_data for the currently 00360 * opened key. 00361 * 00362 * Parameters: 00363 * val_name - name of the registry value 00364 * val_data - registry value data 00365 */ 00366 static LONG setValue(WCHAR* val_name, WCHAR* val_data, BOOL is_unicode) 00367 { 00368 LONG res; 00369 DWORD dwDataType, dwParseType; 00370 LPBYTE lpbData; 00371 DWORD dwData, dwLen; 00372 WCHAR del[] = {'-',0}; 00373 00374 if ( (val_name == NULL) || (val_data == NULL) ) 00375 return ERROR_INVALID_PARAMETER; 00376 00377 if (lstrcmpW(val_data, del) == 0) 00378 { 00379 res=RegDeleteValueW(currentKeyHandle,val_name); 00380 return (res == ERROR_FILE_NOT_FOUND ? ERROR_SUCCESS : res); 00381 } 00382 00383 /* Get the data type stored into the value field */ 00384 dwDataType = getDataType(&val_data, &dwParseType); 00385 00386 if (dwParseType == REG_SZ) /* no conversion for string */ 00387 { 00388 REGPROC_unescape_string(val_data); 00389 /* Compute dwLen after REGPROC_unescape_string because it may 00390 * have changed the string length and we don't want to store 00391 * the extra garbage in the registry. 00392 */ 00393 dwLen = lstrlenW(val_data); 00394 if (dwLen>0 && val_data[dwLen-1]=='"') 00395 { 00396 dwLen--; 00397 val_data[dwLen]='\0'; 00398 } 00399 lpbData = (BYTE*) val_data; 00400 dwLen++; /* include terminating null */ 00401 dwLen = dwLen * sizeof(WCHAR); /* size is in bytes */ 00402 } 00403 else if (dwParseType == REG_DWORD) /* Convert the dword types */ 00404 { 00405 if (!convertHexToDWord(val_data, &dwData)) 00406 return ERROR_INVALID_DATA; 00407 lpbData = (BYTE*)&dwData; 00408 dwLen = sizeof(dwData); 00409 } 00410 else if (dwParseType == REG_BINARY) /* Convert the binary data */ 00411 { 00412 lpbData = convertHexCSVToHex(val_data, &dwLen); 00413 if (!lpbData) 00414 return ERROR_INVALID_DATA; 00415 00416 if((dwDataType == REG_MULTI_SZ || dwDataType == REG_EXPAND_SZ) && !is_unicode) 00417 { 00418 LPBYTE tmp = lpbData; 00419 lpbData = (LPBYTE)GetWideStringN((char*)lpbData, dwLen, &dwLen); 00420 dwLen *= sizeof(WCHAR); 00421 HeapFree(GetProcessHeap(), 0, tmp); 00422 } 00423 } 00424 else /* unknown format */ 00425 { 00426 fprintf(stderr,"%s: ERROR, unknown data format\n", getAppName()); 00427 return ERROR_INVALID_DATA; 00428 } 00429 00430 res = RegSetValueExW( 00431 currentKeyHandle, 00432 val_name, 00433 0, /* Reserved */ 00434 dwDataType, 00435 lpbData, 00436 dwLen); 00437 if (dwParseType == REG_BINARY) 00438 HeapFree(GetProcessHeap(), 0, lpbData); 00439 return res; 00440 } 00441 00442 /****************************************************************************** 00443 * A helper function for processRegEntry() that opens the current key. 00444 * That key must be closed by calling closeKey(). 00445 */ 00446 static LONG openKeyW(WCHAR* stdInput) 00447 { 00448 HKEY keyClass; 00449 WCHAR* keyPath; 00450 DWORD dwDisp; 00451 LONG res; 00452 00453 /* Sanity checks */ 00454 if (stdInput == NULL) 00455 return ERROR_INVALID_PARAMETER; 00456 00457 /* Get the registry class */ 00458 if (!parseKeyName(stdInput, &keyClass, &keyPath)) 00459 return ERROR_INVALID_PARAMETER; 00460 00461 res = RegCreateKeyExW( 00462 keyClass, /* Class */ 00463 keyPath, /* Sub Key */ 00464 0, /* MUST BE 0 */ 00465 NULL, /* object type */ 00466 REG_OPTION_NON_VOLATILE, /* option, REG_OPTION_NON_VOLATILE ... */ 00467 KEY_ALL_ACCESS, /* access mask, KEY_ALL_ACCESS */ 00468 NULL, /* security attribute */ 00469 ¤tKeyHandle, /* result */ 00470 &dwDisp); /* disposition, REG_CREATED_NEW_KEY or 00471 REG_OPENED_EXISTING_KEY */ 00472 00473 if (res == ERROR_SUCCESS) 00474 currentKeyName = GetMultiByteString(stdInput); 00475 else 00476 currentKeyHandle = NULL; 00477 00478 return res; 00479 00480 } 00481 00482 /****************************************************************************** 00483 * Close the currently opened key. 00484 */ 00485 static void closeKey(void) 00486 { 00487 if (currentKeyHandle) 00488 { 00489 HeapFree(GetProcessHeap(), 0, currentKeyName); 00490 RegCloseKey(currentKeyHandle); 00491 currentKeyHandle = NULL; 00492 } 00493 } 00494 00495 /****************************************************************************** 00496 * This function is a wrapper for the setValue function. It prepares the 00497 * land and cleans the area once completed. 00498 * Note: this function modifies the line parameter. 00499 * 00500 * line - registry file unwrapped line. Should have the registry value name and 00501 * complete registry value data. 00502 */ 00503 static void processSetValue(WCHAR* line, BOOL is_unicode) 00504 { 00505 WCHAR* val_name; /* registry value name */ 00506 WCHAR* val_data; /* registry value data */ 00507 int line_idx = 0; /* current character under analysis */ 00508 LONG res; 00509 00510 /* get value name */ 00511 while ( iswspace(line[line_idx]) ) line_idx++; 00512 if (line[line_idx] == '@' && line[line_idx + 1] == '=') 00513 { 00514 line[line_idx] = '\0'; 00515 val_name = line; 00516 line_idx++; 00517 } 00518 else if (line[line_idx] == '\"') 00519 { 00520 line_idx++; 00521 val_name = line + line_idx; 00522 while (TRUE) 00523 { 00524 if (line[line_idx] == '\\') /* skip escaped character */ 00525 { 00526 line_idx += 2; 00527 } 00528 else 00529 { 00530 if (line[line_idx] == '\"') 00531 { 00532 line[line_idx] = '\0'; 00533 line_idx++; 00534 break; 00535 } 00536 else 00537 { 00538 line_idx++; 00539 } 00540 } 00541 } 00542 while ( iswspace(line[line_idx]) ) line_idx++; 00543 if (line[line_idx] != '=') 00544 { 00545 char* lineA; 00546 line[line_idx] = '\"'; 00547 lineA = GetMultiByteString(line); 00548 fprintf(stderr,"Warning! unrecognized line:\n%s\n", lineA); 00549 HeapFree(GetProcessHeap(), 0, lineA); 00550 return; 00551 } 00552 00553 } 00554 else 00555 { 00556 char* lineA = GetMultiByteString(line); 00557 fprintf(stderr,"Warning! unrecognized line:\n%s\n", lineA); 00558 HeapFree(GetProcessHeap(), 0, lineA); 00559 return; 00560 } 00561 line_idx++; /* skip the '=' character */ 00562 00563 while ( iswspace(line[line_idx]) ) line_idx++; 00564 val_data = line + line_idx; 00565 /* trim trailing blanks */ 00566 line_idx = lstrlenW(val_data); 00567 while (line_idx > 0 && iswspace(val_data[line_idx-1])) line_idx--; 00568 val_data[line_idx] = '\0'; 00569 00570 REGPROC_unescape_string(val_name); 00571 res = setValue(val_name, val_data, is_unicode); 00572 if ( res != ERROR_SUCCESS ) 00573 { 00574 char* val_nameA = GetMultiByteString(val_name); 00575 char* val_dataA = GetMultiByteString(val_data); 00576 fprintf(stderr,"%s: ERROR Key %s not created. Value: %s, Data: %s\n", 00577 getAppName(), 00578 currentKeyName, 00579 val_nameA, 00580 val_dataA); 00581 HeapFree(GetProcessHeap(), 0, val_nameA); 00582 HeapFree(GetProcessHeap(), 0, val_dataA); 00583 } 00584 } 00585 00586 /****************************************************************************** 00587 * This function receives the currently read entry and performs the 00588 * corresponding action. 00589 * isUnicode affects parsing of REG_MULTI_SZ values 00590 */ 00591 static void processRegEntry(WCHAR* stdInput, BOOL isUnicode) 00592 { 00593 /* 00594 * We encountered the end of the file, make sure we 00595 * close the opened key and exit 00596 */ 00597 if (stdInput == NULL) 00598 { 00599 closeKey(); 00600 return; 00601 } 00602 00603 if ( stdInput[0] == L'[') /* We are reading a new key */ 00604 { 00605 WCHAR* keyEnd; 00606 closeKey(); /* Close the previous key */ 00607 00608 /* Get rid of the square brackets */ 00609 stdInput++; 00610 keyEnd = wcsrchr(stdInput, L']'); 00611 if (keyEnd) 00612 *keyEnd='\0'; 00613 00614 /* delete the key if we encounter '-' at the start of reg key */ 00615 if ( stdInput[0] == '-') 00616 { 00617 delete_registry_key(stdInput + 1); 00618 } 00619 else if ( openKeyW(stdInput) != ERROR_SUCCESS ) 00620 { 00621 char* stdInputA = GetMultiByteString(stdInput); 00622 fprintf(stderr,"%s: setValue failed to open key %s\n", 00623 getAppName(), stdInputA); 00624 HeapFree(GetProcessHeap(), 0, stdInputA); 00625 } 00626 } 00627 else if( currentKeyHandle && 00628 (( stdInput[0] == '@') || /* reading a default @=data pair */ 00629 ( stdInput[0] == '\"'))) /* reading a new value=data pair */ 00630 { 00631 processSetValue(stdInput, isUnicode); 00632 } 00633 else 00634 { 00635 /* Since we are assuming that the file format is valid we must be 00636 * reading a blank line which indicates the end of this key processing 00637 */ 00638 closeKey(); 00639 } 00640 } 00641 00642 /****************************************************************************** 00643 * Processes a registry file. 00644 * Correctly processes comments (in # form), line continuation. 00645 * 00646 * Parameters: 00647 * in - input stream to read from 00648 */ 00649 static void processRegLinesA(FILE *in) 00650 { 00651 LPSTR line = NULL; /* line read from input stream */ 00652 ULONG lineSize = REG_VAL_BUF_SIZE; 00653 00654 line = HeapAlloc(GetProcessHeap(), 0, lineSize); 00655 CHECK_ENOUGH_MEMORY(line); 00656 00657 while (!feof(in)) 00658 { 00659 LPSTR s; /* The pointer into line for where the current fgets should read */ 00660 LPSTR check; 00661 WCHAR* lineW; 00662 s = line; 00663 00664 for (;;) 00665 { 00666 size_t size_remaining; 00667 int size_to_get; 00668 char *s_eol; /* various local uses */ 00669 00670 /* Do we need to expand the buffer ? */ 00671 assert (s >= line && s <= line + lineSize); 00672 size_remaining = lineSize - (s-line); 00673 if (size_remaining < 2) /* room for 1 character and the \0 */ 00674 { 00675 char *new_buffer; 00676 size_t new_size = lineSize + REG_VAL_BUF_SIZE; 00677 if (new_size > lineSize) /* no arithmetic overflow */ 00678 new_buffer = HeapReAlloc (GetProcessHeap(), 0, line, new_size); 00679 else 00680 new_buffer = NULL; 00681 CHECK_ENOUGH_MEMORY(new_buffer); 00682 line = new_buffer; 00683 s = line + lineSize - size_remaining; 00684 lineSize = new_size; 00685 size_remaining = lineSize - (s-line); 00686 } 00687 00688 /* Get as much as possible into the buffer, terminated either by 00689 * eof, error, eol or getting the maximum amount. Abort on error. 00690 */ 00691 size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining); 00692 00693 check = fgets (s, size_to_get, in); 00694 00695 if (check == NULL) 00696 { 00697 if (ferror(in)) 00698 { 00699 perror ("While reading input"); 00700 exit (IO_ERROR); 00701 } 00702 else 00703 { 00704 assert (feof(in)); 00705 *s = '\0'; 00706 /* It is not clear to me from the definition that the 00707 * contents of the buffer are well defined on detecting 00708 * an eof without managing to read anything. 00709 */ 00710 } 00711 } 00712 00713 /* If we didn't read the eol nor the eof go around for the rest */ 00714 s_eol = strchr (s, '\n'); 00715 if (!feof (in) && !s_eol) 00716 { 00717 s = strchr (s, '\0'); 00718 /* It should be s + size_to_get - 1 but this is safer */ 00719 continue; 00720 } 00721 00722 /* If it is a comment line then discard it and go around again */ 00723 if (line [0] == '#') 00724 { 00725 s = line; 00726 continue; 00727 } 00728 00729 /* Remove any line feed. Leave s_eol on the \0 */ 00730 if (s_eol) 00731 { 00732 *s_eol = '\0'; 00733 if (s_eol > line && *(s_eol-1) == '\r') 00734 *--s_eol = '\0'; 00735 } 00736 else 00737 s_eol = strchr (s, '\0'); 00738 00739 /* If there is a concatenating \\ then go around again */ 00740 if (s_eol > line && *(s_eol-1) == '\\') 00741 { 00742 int c; 00743 s = s_eol-1; 00744 00745 do 00746 { 00747 c = fgetc(in); 00748 } 00749 while(c == ' ' || c == '\t'); 00750 00751 if(c == EOF) 00752 { 00753 fprintf(stderr,"%s: ERROR - invalid continuation.\n", 00754 getAppName()); 00755 } 00756 else 00757 { 00758 *s = c; 00759 s++; 00760 } 00761 continue; 00762 } 00763 00764 lineW = GetWideString(line); 00765 00766 break; /* That is the full virtual line */ 00767 } 00768 00769 processRegEntry(lineW, FALSE); 00770 HeapFree(GetProcessHeap(), 0, lineW); 00771 } 00772 processRegEntry(NULL, FALSE); 00773 00774 HeapFree(GetProcessHeap(), 0, line); 00775 } 00776 00777 static void processRegLinesW(FILE *in) 00778 { 00779 WCHAR* buf = NULL; /* line read from input stream */ 00780 ULONG lineSize = REG_VAL_BUF_SIZE; 00781 size_t CharsInBuf = -1; 00782 00783 WCHAR* s; /* The pointer into buf for where the current fgets should read */ 00784 WCHAR* line; /* The start of the current line */ 00785 00786 buf = HeapAlloc(GetProcessHeap(), 0, lineSize * sizeof(WCHAR)); 00787 CHECK_ENOUGH_MEMORY(buf); 00788 00789 s = buf; 00790 line = buf; 00791 00792 while(!feof(in)) 00793 { 00794 size_t size_remaining; 00795 int size_to_get; 00796 WCHAR *s_eol = NULL; /* various local uses */ 00797 00798 /* Do we need to expand the buffer ? */ 00799 assert (s >= buf && s <= buf + lineSize); 00800 size_remaining = lineSize - (s-buf); 00801 if (size_remaining < 2) /* room for 1 character and the \0 */ 00802 { 00803 WCHAR *new_buffer; 00804 size_t new_size = lineSize + (REG_VAL_BUF_SIZE / sizeof(WCHAR)); 00805 if (new_size > lineSize) /* no arithmetic overflow */ 00806 new_buffer = HeapReAlloc (GetProcessHeap(), 0, buf, new_size * sizeof(WCHAR)); 00807 else 00808 new_buffer = NULL; 00809 CHECK_ENOUGH_MEMORY(new_buffer); 00810 buf = new_buffer; 00811 line = buf; 00812 s = buf + lineSize - size_remaining; 00813 lineSize = new_size; 00814 size_remaining = lineSize - (s-buf); 00815 } 00816 00817 /* Get as much as possible into the buffer, terminated either by 00818 * eof, error or getting the maximum amount. Abort on error. 00819 */ 00820 size_to_get = (size_remaining > INT_MAX ? INT_MAX : size_remaining); 00821 00822 CharsInBuf = fread(s, sizeof(WCHAR), size_to_get - 1, in); 00823 s[CharsInBuf] = 0; 00824 00825 if (CharsInBuf == 0) 00826 { 00827 if (ferror(in)) 00828 { 00829 perror ("While reading input"); 00830 exit (IO_ERROR); 00831 } 00832 else 00833 { 00834 assert (feof(in)); 00835 *s = '\0'; 00836 /* It is not clear to me from the definition that the 00837 * contents of the buffer are well defined on detecting 00838 * an eof without managing to read anything. 00839 */ 00840 } 00841 } 00842 00843 /* If we didn't read the eol nor the eof go around for the rest */ 00844 while(1) 00845 { 00846 s_eol = wcschr(line, '\n'); 00847 00848 if(!s_eol) 00849 { 00850 /* Move the stub of the line to the start of the buffer so 00851 * we get the maximum space to read into, and so we don't 00852 * have to recalculate 'line' if the buffer expands */ 00853 MoveMemory(buf, line, (lstrlenW(line) + 1) * sizeof(WCHAR)); 00854 line = buf; 00855 s = wcschr(line, '\0'); 00856 break; 00857 } 00858 00859 /* If it is a comment line then discard it and go around again */ 00860 if (*line == '#') 00861 { 00862 line = s_eol + 1; 00863 continue; 00864 } 00865 00866 /* If there is a concatenating \\ then go around again */ 00867 if ((*(s_eol-1) == '\\') || 00868 (*(s_eol-1) == '\r' && *(s_eol-2) == '\\')) 00869 { 00870 WCHAR* NextLine = s_eol; 00871 00872 while(*(NextLine+1) == ' ' || *(NextLine+1) == '\t') 00873 NextLine++; 00874 00875 NextLine++; 00876 00877 if(*(s_eol-1) == '\r') 00878 s_eol--; 00879 00880 MoveMemory(s_eol - 1, NextLine, (CharsInBuf - (NextLine - s) + 1)*sizeof(WCHAR)); 00881 CharsInBuf -= NextLine - s_eol + 1; 00882 s_eol = 0; 00883 continue; 00884 } 00885 00886 /* Remove any line feed. Leave s_eol on the \0 */ 00887 if (s_eol) 00888 { 00889 *s_eol = '\0'; 00890 if (s_eol > buf && *(s_eol-1) == '\r') 00891 *(s_eol-1) = '\0'; 00892 } 00893 00894 if(!s_eol) 00895 break; 00896 00897 processRegEntry(line, TRUE); 00898 line = s_eol + 1; 00899 s_eol = 0; 00900 continue; /* That is the full virtual line */ 00901 } 00902 } 00903 00904 processRegEntry(NULL, TRUE); 00905 00906 HeapFree(GetProcessHeap(), 0, buf); 00907 } 00908 00909 /**************************************************************************** 00910 * REGPROC_print_error 00911 * 00912 * Print the message for GetLastError 00913 */ 00914 00915 static void REGPROC_print_error(void) 00916 { 00917 LPVOID lpMsgBuf; 00918 DWORD error_code; 00919 int status; 00920 00921 error_code = GetLastError (); 00922 status = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 00923 NULL, error_code, 0, (LPTSTR) &lpMsgBuf, 0, NULL); 00924 if (!status) 00925 { 00926 fprintf(stderr,"%s: Cannot display message for error %ld, status %ld\n", 00927 getAppName(), error_code, GetLastError()); 00928 exit(1); 00929 } 00930 puts(lpMsgBuf); 00931 LocalFree(lpMsgBuf); 00932 exit(1); 00933 } 00934 00935 /****************************************************************************** 00936 * Checks whether the buffer has enough room for the string or required size. 00937 * Resizes the buffer if necessary. 00938 * 00939 * Parameters: 00940 * buffer - pointer to a buffer for string 00941 * len - current length of the buffer in characters. 00942 * required_len - length of the string to place to the buffer in characters. 00943 * The length does not include the terminating null character. 00944 */ 00945 static void REGPROC_resize_char_buffer(WCHAR **buffer, DWORD *len, DWORD required_len) 00946 { 00947 required_len++; 00948 if (required_len > *len) 00949 { 00950 *len = required_len; 00951 if (!*buffer) 00952 *buffer = HeapAlloc(GetProcessHeap(), 0, *len * sizeof(**buffer)); 00953 else 00954 *buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *len * sizeof(**buffer)); 00955 CHECK_ENOUGH_MEMORY(*buffer); 00956 } 00957 } 00958 00959 /****************************************************************************** 00960 * Same as REGPROC_resize_char_buffer() but on a regular buffer. 00961 * 00962 * Parameters: 00963 * buffer - pointer to a buffer 00964 * len - current size of the buffer in bytes 00965 * required_size - size of the data to place in the buffer in bytes 00966 */ 00967 static void REGPROC_resize_binary_buffer(BYTE **buffer, DWORD *size, DWORD required_size) 00968 { 00969 if (required_size > *size) 00970 { 00971 *size = required_size; 00972 if (!*buffer) 00973 *buffer = HeapAlloc(GetProcessHeap(), 0, *size); 00974 else 00975 *buffer = HeapReAlloc(GetProcessHeap(), 0, *buffer, *size); 00976 CHECK_ENOUGH_MEMORY(*buffer); 00977 } 00978 } 00979 00980 /****************************************************************************** 00981 * Prints string str to file 00982 */ 00983 static void REGPROC_export_string(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, WCHAR *str, DWORD str_len) 00984 { 00985 DWORD i, pos; 00986 DWORD extra = 0; 00987 00988 REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + 10); 00989 00990 /* escaping characters */ 00991 pos = *line_len; 00992 for (i = 0; i < str_len; i++) 00993 { 00994 WCHAR c = str[i]; 00995 switch (c) 00996 { 00997 case '\n': 00998 extra++; 00999 REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra); 01000 (*line_buf)[pos++] = '\\'; 01001 (*line_buf)[pos++] = 'n'; 01002 break; 01003 01004 case '\\': 01005 case '"': 01006 extra++; 01007 REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra); 01008 (*line_buf)[pos++] = '\\'; 01009 /* Fall through */ 01010 01011 default: 01012 (*line_buf)[pos++] = c; 01013 break; 01014 } 01015 } 01016 (*line_buf)[pos] = '\0'; 01017 *line_len = pos; 01018 } 01019 01020 static void REGPROC_export_binary(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, DWORD type, BYTE *value, DWORD value_size, BOOL unicode) 01021 { 01022 DWORD hex_pos, data_pos; 01023 const WCHAR *hex_prefix; 01024 const WCHAR hex[] = {'h','e','x',':',0}; 01025 WCHAR hex_buf[17]; 01026 const WCHAR concat[] = {'\\','\n',' ',' ',0}; 01027 DWORD concat_prefix, concat_len; 01028 const WCHAR newline[] = {'\n',0}; 01029 CHAR* value_multibyte = NULL; 01030 01031 if (type == REG_BINARY) 01032 { 01033 hex_prefix = hex; 01034 } 01035 else 01036 { 01037 const WCHAR hex_format[] = {'h','e','x','(','%','u',')',':',0}; 01038 hex_prefix = hex_buf; 01039 wsprintfW(hex_buf, hex_format, type); 01040 if ((type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ) && !unicode) 01041 { 01042 value_multibyte = GetMultiByteStringN((WCHAR*)value, value_size / sizeof(WCHAR), &value_size); 01043 value = (BYTE*)value_multibyte; 01044 } 01045 } 01046 01047 concat_len = lstrlenW(concat); 01048 concat_prefix = 2; 01049 01050 hex_pos = *line_len; 01051 *line_len += lstrlenW(hex_prefix); 01052 data_pos = *line_len; 01053 *line_len += value_size * 3; 01054 /* - The 2 spaces that concat places at the start of the 01055 * line effectively reduce the space available for data. 01056 * - If the value name and hex prefix are very long 01057 * ( > REG_FILE_HEX_LINE_LEN) then we may overestimate 01058 * the needed number of lines by one. But that's ok. 01059 * - The trailing linefeed takes the place of a comma so 01060 * it's accounted for already. 01061 */ 01062 *line_len += *line_len / (REG_FILE_HEX_LINE_LEN - concat_prefix) * concat_len; 01063 REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len); 01064 lstrcpyW(*line_buf + hex_pos, hex_prefix); 01065 if (value_size) 01066 { 01067 const WCHAR format[] = {'%','0','2','x',0}; 01068 DWORD i, column; 01069 01070 column = data_pos; /* no line wrap yet */ 01071 i = 0; 01072 while (1) 01073 { 01074 wsprintfW(*line_buf + data_pos, format, (unsigned int)value[i]); 01075 data_pos += 2; 01076 if (++i == value_size) 01077 break; 01078 01079 (*line_buf)[data_pos++] = ','; 01080 column += 3; 01081 01082 /* wrap the line */ 01083 if (column >= REG_FILE_HEX_LINE_LEN) 01084 { 01085 lstrcpyW(*line_buf + data_pos, concat); 01086 data_pos += concat_len; 01087 column = concat_prefix; 01088 } 01089 } 01090 } 01091 lstrcpyW(*line_buf + data_pos, newline); 01092 HeapFree(GetProcessHeap(), 0, value_multibyte); 01093 } 01094 01095 /****************************************************************************** 01096 * Writes the given line to a file, in multi-byte or wide characters 01097 */ 01098 static void REGPROC_write_line(FILE *file, const WCHAR* str, BOOL unicode) 01099 { 01100 int i; 01101 if (unicode) 01102 { 01103 for(i = 0; str[i]; i++) 01104 { 01105 if (str[i] == L'\n') 01106 fputwc(L'\r', file); 01107 fputwc(str[i], file); 01108 } 01109 } 01110 else 01111 { 01112 char* strA = GetMultiByteString(str); 01113 fputs(strA, file); 01114 HeapFree(GetProcessHeap(), 0, strA); 01115 } 01116 } 01117 01118 /****************************************************************************** 01119 * Writes contents of the registry key to the specified file stream. 01120 * 01121 * Parameters: 01122 * file - writable file stream to export registry branch to. 01123 * key - registry branch to export. 01124 * reg_key_name_buf - name of the key with registry class. 01125 * Is resized if necessary. 01126 * reg_key_name_size - length of the buffer for the registry class in characters. 01127 * val_name_buf - buffer for storing value name. 01128 * Is resized if necessary. 01129 * val_name_size - length of the buffer for storing value names in characters. 01130 * val_buf - buffer for storing values while extracting. 01131 * Is resized if necessary. 01132 * val_size - size of the buffer for storing values in bytes. 01133 */ 01134 static void export_hkey(FILE *file, HKEY key, 01135 WCHAR **reg_key_name_buf, DWORD *reg_key_name_size, 01136 WCHAR **val_name_buf, DWORD *val_name_size, 01137 BYTE **val_buf, DWORD *val_size, 01138 WCHAR **line_buf, DWORD *line_buf_size, 01139 BOOL unicode) 01140 { 01141 DWORD max_sub_key_len; 01142 DWORD max_val_name_len; 01143 DWORD max_val_size; 01144 DWORD curr_len; 01145 DWORD i; 01146 BOOL more_data; 01147 LONG ret; 01148 WCHAR key_format[] = {'\n','[','%','s',']','\n',0}; 01149 01150 /* get size information and resize the buffers if necessary */ 01151 if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, 01152 &max_sub_key_len, NULL, 01153 NULL, &max_val_name_len, &max_val_size, NULL, NULL 01154 ) != ERROR_SUCCESS) 01155 { 01156 REGPROC_print_error(); 01157 } 01158 curr_len = lstrlenW(*reg_key_name_buf); 01159 REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, 01160 max_sub_key_len + curr_len + 1); 01161 REGPROC_resize_char_buffer(val_name_buf, val_name_size, 01162 max_val_name_len); 01163 REGPROC_resize_binary_buffer(val_buf, val_size, max_val_size); 01164 REGPROC_resize_char_buffer(line_buf, line_buf_size, lstrlenW(*reg_key_name_buf) + 4); 01165 /* output data for the current key */ 01166 wsprintfW(*line_buf, key_format, *reg_key_name_buf); 01167 REGPROC_write_line(file, *line_buf, unicode); 01168 01169 /* print all the values */ 01170 i = 0; 01171 more_data = TRUE; 01172 while(more_data) 01173 { 01174 DWORD value_type; 01175 DWORD val_name_size1 = *val_name_size; 01176 DWORD val_size1 = *val_size; 01177 ret = RegEnumValueW(key, i, *val_name_buf, &val_name_size1, NULL, 01178 &value_type, *val_buf, &val_size1); 01179 if (ret == ERROR_MORE_DATA) 01180 { 01181 /* Increase the size of the buffers and retry */ 01182 REGPROC_resize_char_buffer(val_name_buf, val_name_size, val_name_size1); 01183 REGPROC_resize_binary_buffer(val_buf, val_size, val_size1); 01184 } 01185 else if (ret != ERROR_SUCCESS) 01186 { 01187 more_data = FALSE; 01188 if (ret != ERROR_NO_MORE_ITEMS) 01189 { 01190 REGPROC_print_error(); 01191 } 01192 } 01193 else 01194 { 01195 DWORD line_len; 01196 i++; 01197 01198 if ((*val_name_buf)[0]) 01199 { 01200 const WCHAR val_start[] = {'"','%','s','"','=',0}; 01201 01202 line_len = 0; 01203 REGPROC_export_string(line_buf, line_buf_size, &line_len, *val_name_buf, lstrlenW(*val_name_buf)); 01204 REGPROC_resize_char_buffer(val_name_buf, val_name_size, lstrlenW(*line_buf) + 1); 01205 lstrcpyW(*val_name_buf, *line_buf); 01206 01207 line_len = 3 + lstrlenW(*val_name_buf); 01208 REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); 01209 wsprintfW(*line_buf, val_start, *val_name_buf); 01210 } 01211 else 01212 { 01213 const WCHAR std_val[] = {'@','=',0}; 01214 line_len = 2; 01215 REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); 01216 lstrcpyW(*line_buf, std_val); 01217 } 01218 01219 switch (value_type) 01220 { 01221 case REG_SZ: 01222 { 01223 WCHAR* wstr = (WCHAR*)*val_buf; 01224 01225 if (val_size1 < sizeof(WCHAR) || val_size1 % sizeof(WCHAR) || 01226 wstr[val_size1 / sizeof(WCHAR) - 1]) 01227 { 01228 REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); 01229 } 01230 else 01231 { 01232 const WCHAR start[] = {'"',0}; 01233 const WCHAR end[] = {'"','\n',0}; 01234 DWORD len; 01235 01236 len = lstrlenW(start); 01237 REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len); 01238 lstrcpyW(*line_buf + line_len, start); 01239 line_len += len; 01240 01241 /* At this point we know wstr is '\0'-terminated 01242 * so we can substract 1 from the size 01243 */ 01244 REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, val_size1 / sizeof(WCHAR) - 1); 01245 01246 REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end)); 01247 lstrcpyW(*line_buf + line_len, end); 01248 } 01249 break; 01250 } 01251 01252 case REG_DWORD: 01253 { 01254 WCHAR format[] = {'d','w','o','r','d',':','%','0','8','x','\n',0}; 01255 01256 REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + 15); 01257 wsprintfW(*line_buf + line_len, format, *((DWORD *)*val_buf)); 01258 break; 01259 } 01260 01261 default: 01262 { 01263 char* key_nameA = GetMultiByteString(*reg_key_name_buf); 01264 char* value_nameA = GetMultiByteString(*val_name_buf); 01265 fprintf(stderr,"%s: warning - unsupported registry format '%ld', " 01266 "treat as binary\n", 01267 getAppName(), value_type); 01268 fprintf(stderr,"key name: \"%s\"\n", key_nameA); 01269 fprintf(stderr,"value name:\"%s\"\n\n", value_nameA); 01270 HeapFree(GetProcessHeap(), 0, key_nameA); 01271 HeapFree(GetProcessHeap(), 0, value_nameA); 01272 } 01273 /* falls through */ 01274 case REG_EXPAND_SZ: 01275 case REG_MULTI_SZ: 01276 /* falls through */ 01277 case REG_BINARY: 01278 REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); 01279 } 01280 REGPROC_write_line(file, *line_buf, unicode); 01281 } 01282 } 01283 01284 i = 0; 01285 more_data = TRUE; 01286 (*reg_key_name_buf)[curr_len] = '\\'; 01287 while(more_data) 01288 { 01289 DWORD buf_size = *reg_key_name_size - curr_len - 1; 01290 01291 ret = RegEnumKeyExW(key, i, *reg_key_name_buf + curr_len + 1, &buf_size, 01292 NULL, NULL, NULL, NULL); 01293 if (ret == ERROR_MORE_DATA) 01294 { 01295 /* Increase the size of the buffer and retry */ 01296 REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, curr_len + 1 + buf_size); 01297 } 01298 else if (ret != ERROR_SUCCESS) 01299 { 01300 more_data = FALSE; 01301 if (ret != ERROR_NO_MORE_ITEMS) 01302 { 01303 REGPROC_print_error(); 01304 } 01305 } 01306 else 01307 { 01308 HKEY subkey; 01309 01310 i++; 01311 if (RegOpenKeyW(key, *reg_key_name_buf + curr_len + 1, 01312 &subkey) == ERROR_SUCCESS) 01313 { 01314 export_hkey(file, subkey, reg_key_name_buf, reg_key_name_size, 01315 val_name_buf, val_name_size, val_buf, val_size, 01316 line_buf, line_buf_size, unicode); 01317 RegCloseKey(subkey); 01318 } 01319 else 01320 { 01321 REGPROC_print_error(); 01322 } 01323 } 01324 } 01325 (*reg_key_name_buf)[curr_len] = '\0'; 01326 } 01327 01328 /****************************************************************************** 01329 * Open file for export. 01330 */ 01331 static FILE *REGPROC_open_export_file(WCHAR *file_name, BOOL unicode) 01332 { 01333 FILE *file; 01334 WCHAR dash = '-'; 01335 01336 if (wcsncmp(file_name, &dash, 1) == 0) 01337 file = stdout; 01338 else 01339 { 01340 if (unicode) 01341 file = _wfopen(file_name, L"wb"); 01342 else 01343 file = _wfopen(file_name, L"w"); 01344 if (!file) 01345 { 01346 CHAR* file_nameA = GetMultiByteString(file_name); 01347 perror(""); 01348 fprintf(stderr,"%s: Can't open file \"%s\"\n", getAppName(), file_nameA); 01349 HeapFree(GetProcessHeap(), 0, file_nameA); 01350 exit(1); 01351 } 01352 } 01353 if (unicode) 01354 { 01355 const BYTE unicode_seq[] = {0xff,0xfe}; 01356 const WCHAR header[] = L"Windows Registry Editor Version 5.00\r\n"; 01357 fwrite(unicode_seq, sizeof(BYTE), COUNT_OF(unicode_seq), file); 01358 fwrite(header, sizeof(WCHAR), lstrlenW(header), file); 01359 } 01360 else 01361 { 01362 fputs("REGEDIT4\n", file); 01363 } 01364 01365 return file; 01366 } 01367 01368 /****************************************************************************** 01369 * Writes contents of the registry key to the specified file stream. 01370 * 01371 * Parameters: 01372 * file_name - name of a file to export registry branch to. 01373 * reg_key_name - registry branch to export. The whole registry is exported if 01374 * reg_key_name is NULL or contains an empty string. 01375 */ 01376 BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format) 01377 { 01378 WCHAR *reg_key_name_buf; 01379 WCHAR *val_name_buf; 01380 BYTE *val_buf; 01381 WCHAR *line_buf; 01382 DWORD reg_key_name_size = KEY_MAX_LEN; 01383 DWORD val_name_size = KEY_MAX_LEN; 01384 DWORD val_size = REG_VAL_BUF_SIZE; 01385 DWORD line_buf_size = KEY_MAX_LEN + REG_VAL_BUF_SIZE; 01386 FILE *file = NULL; 01387 BOOL unicode = (format == REG_FORMAT_5); 01388 01389 reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, 01390 reg_key_name_size * sizeof(*reg_key_name_buf)); 01391 val_name_buf = HeapAlloc(GetProcessHeap(), 0, 01392 val_name_size * sizeof(*val_name_buf)); 01393 val_buf = HeapAlloc(GetProcessHeap(), 0, val_size); 01394 line_buf = HeapAlloc(GetProcessHeap(), 0, line_buf_size * sizeof(*line_buf)); 01395 CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf && line_buf); 01396 01397 if (reg_key_name && reg_key_name[0]) 01398 { 01399 HKEY reg_key_class; 01400 WCHAR *branch_name = NULL; 01401 HKEY key; 01402 01403 REGPROC_resize_char_buffer(®_key_name_buf, ®_key_name_size, 01404 lstrlenW(reg_key_name)); 01405 lstrcpyW(reg_key_name_buf, reg_key_name); 01406 01407 /* open the specified key */ 01408 if (!parseKeyName(reg_key_name, ®_key_class, &branch_name)) 01409 { 01410 CHAR* key_nameA = GetMultiByteString(reg_key_name); 01411 fprintf(stderr,"%s: Incorrect registry class specification in '%s'\n", 01412 getAppName(), key_nameA); 01413 HeapFree(GetProcessHeap(), 0, key_nameA); 01414 exit(1); 01415 } 01416 if (!branch_name[0]) 01417 { 01418 /* no branch - registry class is specified */ 01419 file = REGPROC_open_export_file(file_name, unicode); 01420 export_hkey(file, reg_key_class, 01421 ®_key_name_buf, ®_key_name_size, 01422 &val_name_buf, &val_name_size, 01423 &val_buf, &val_size, &line_buf, 01424 &line_buf_size, unicode); 01425 } 01426 else if (RegOpenKeyW(reg_key_class, branch_name, &key) == ERROR_SUCCESS) 01427 { 01428 file = REGPROC_open_export_file(file_name, unicode); 01429 export_hkey(file, key, 01430 ®_key_name_buf, ®_key_name_size, 01431 &val_name_buf, &val_name_size, 01432 &val_buf, &val_size, &line_buf, 01433 &line_buf_size, unicode); 01434 RegCloseKey(key); 01435 } 01436 else 01437 { 01438 CHAR* key_nameA = GetMultiByteString(reg_key_name); 01439 fprintf(stderr,"%s: Can't export. Registry key '%s' does not exist!\n", 01440 getAppName(), key_nameA); 01441 HeapFree(GetProcessHeap(), 0, key_nameA); 01442 REGPROC_print_error(); 01443 } 01444 } 01445 else 01446 { 01447 unsigned int i; 01448 01449 /* export all registry classes */ 01450 file = REGPROC_open_export_file(file_name, unicode); 01451 for (i = 0; i < REG_CLASS_NUMBER; i++) 01452 { 01453 /* do not export HKEY_CLASSES_ROOT */ 01454 if (reg_class_keys[i] != HKEY_CLASSES_ROOT && 01455 reg_class_keys[i] != HKEY_CURRENT_USER && 01456 reg_class_keys[i] != HKEY_CURRENT_CONFIG && 01457 reg_class_keys[i] != HKEY_DYN_DATA) 01458 { 01459 lstrcpyW(reg_key_name_buf, reg_class_namesW[i]); 01460 export_hkey(file, reg_class_keys[i], 01461 ®_key_name_buf, ®_key_name_size, 01462 &val_name_buf, &val_name_size, 01463 &val_buf, &val_size, &line_buf, 01464 &line_buf_size, unicode); 01465 } 01466 } 01467 } 01468 01469 if (file) 01470 { 01471 fclose(file); 01472 } 01473 HeapFree(GetProcessHeap(), 0, reg_key_name); 01474 HeapFree(GetProcessHeap(), 0, val_name_buf); 01475 HeapFree(GetProcessHeap(), 0, val_buf); 01476 HeapFree(GetProcessHeap(), 0, line_buf); 01477 return TRUE; 01478 } 01479 01480 /****************************************************************************** 01481 * Reads contents of the specified file into the registry. 01482 */ 01483 BOOL import_registry_file(FILE* reg_file) 01484 { 01485 if (reg_file) 01486 { 01487 BYTE s[2]; 01488 if (fread( s, 2, 1, reg_file) == 1) 01489 { 01490 if (s[0] == 0xff && s[1] == 0xfe) 01491 { 01492 processRegLinesW(reg_file); 01493 } 01494 else 01495 { 01496 fseek(reg_file, 0, SEEK_SET); 01497 processRegLinesA(reg_file); 01498 } 01499 } 01500 return TRUE; 01501 } 01502 return FALSE; 01503 } 01504 01505 /****************************************************************************** 01506 * Removes the registry key with all subkeys. Parses full key name. 01507 * 01508 * Parameters: 01509 * reg_key_name - full name of registry branch to delete. Ignored if is NULL, 01510 * empty, points to register key class, does not exist. 01511 */ 01512 void delete_registry_key(WCHAR *reg_key_name) 01513 { 01514 WCHAR *key_name = NULL; 01515 HKEY key_class; 01516 01517 if (!reg_key_name || !reg_key_name[0]) 01518 return; 01519 01520 if (!parseKeyName(reg_key_name, &key_class, &key_name)) 01521 { 01522 char* reg_key_nameA = GetMultiByteString(reg_key_name); 01523 fprintf(stderr,"%s: Incorrect registry class specification in '%s'\n", 01524 getAppName(), reg_key_nameA); 01525 HeapFree(GetProcessHeap(), 0, reg_key_nameA); 01526 exit(1); 01527 } 01528 if (!*key_name) 01529 { 01530 char* reg_key_nameA = GetMultiByteString(reg_key_name); 01531 fprintf(stderr,"%s: Can't delete registry class '%s'\n", 01532 getAppName(), reg_key_nameA); 01533 HeapFree(GetProcessHeap(), 0, reg_key_nameA); 01534 exit(1); 01535 } 01536 01537 SHDeleteKey(key_class, key_name); 01538 } Generated on Sun May 27 2012 04:17:41 for ReactOS by
1.7.6.1
|