/****************************************************************************** * Prints string str to file */ static void REGPROC_export_string(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, WCHAR *str, DWORD str_len) { DWORD i, pos; DWORD extra = 0; REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + 10); /* escaping characters */ pos = *line_len; for (i = 0; i < str_len; i++) { WCHAR c = str[i]; switch (c) { case '\n': extra++; REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra); (*line_buf)[pos++] = '\\'; (*line_buf)[pos++] = 'n'; break; case '\\': case '"': extra++; REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len + str_len + extra); (*line_buf)[pos++] = '\\'; /* Fall through */ default: (*line_buf)[pos++] = c; break; } } (*line_buf)[pos] = '\0'; *line_len = pos; }
/****************************************************************************** * Recursive function which removes the registry key with all subkeys. */ BOOL delete_branch(HKEY key, TCHAR** reg_key_name_buf, DWORD* reg_key_name_len) { HKEY branch_key; DWORD max_sub_key_len; DWORD subkeys; DWORD curr_len; LONG ret; long int i; if (RegOpenKey(key, *reg_key_name_buf, &branch_key) != ERROR_SUCCESS) { REGPROC_print_error(); return FALSE; } /* get size information and resize the buffers if necessary */ if (RegQueryInfoKey(branch_key, NULL, NULL, NULL, &subkeys, &max_sub_key_len, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) { REGPROC_print_error(); RegCloseKey(branch_key); return FALSE; } curr_len = _tcslen(*reg_key_name_buf); REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1); (*reg_key_name_buf)[curr_len] = '\\'; for (i = subkeys - 1; i >= 0; i--) { DWORD buf_len = *reg_key_name_len - curr_len; ret = RegEnumKeyEx(branch_key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA && ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); RegCloseKey(branch_key); return FALSE; } else { delete_branch(key, reg_key_name_buf, reg_key_name_len); } } (*reg_key_name_buf)[curr_len] = '\0'; RegCloseKey(branch_key); RegDeleteKey(key, *reg_key_name_buf); return TRUE; }
static void REGPROC_export_binary(WCHAR **line_buf, DWORD *line_buf_size, DWORD *line_len, DWORD type, BYTE *value, DWORD value_size, BOOL unicode) { DWORD hex_pos, data_pos; const WCHAR *hex_prefix; const WCHAR hex[] = {'h','e','x',':',0}; WCHAR hex_buf[17]; const WCHAR concat[] = {'\\','\r','\n',' ',' ',0}; DWORD concat_prefix, concat_len; const WCHAR newline[] = {'\r','\n',0}; CHAR* value_multibyte = NULL; if (type == REG_BINARY) { hex_prefix = hex; } else { const WCHAR hex_format[] = {'h','e','x','(','%','x',')',':',0}; hex_prefix = hex_buf; sprintfW(hex_buf, hex_format, type); if ((type == REG_SZ || type == REG_EXPAND_SZ || type == REG_MULTI_SZ) && !unicode) { value_multibyte = GetMultiByteStringN((WCHAR*)value, value_size / sizeof(WCHAR), &value_size); value = (BYTE*)value_multibyte; } } concat_len = lstrlenW(concat); concat_prefix = 2; hex_pos = *line_len; *line_len += lstrlenW(hex_prefix); data_pos = *line_len; *line_len += value_size * 3; /* - The 2 spaces that concat places at the start of the * line effectively reduce the space available for data. * - If the value name and hex prefix are very long * ( > REG_FILE_HEX_LINE_LEN) or *line_len divides * without a remainder then we may overestimate * the needed number of lines by one. But that's ok. * - The trailing '\r' takes the place of a comma so * we only need to add 1 for the trailing '\n' */ *line_len += *line_len / (REG_FILE_HEX_LINE_LEN - concat_prefix) * concat_len + 1; REGPROC_resize_char_buffer(line_buf, line_buf_size, *line_len); lstrcpyW(*line_buf + hex_pos, hex_prefix); if (value_size) { const WCHAR format[] = {'%','0','2','x',0}; DWORD i, column; column = data_pos; /* no line wrap yet */ i = 0; while (1) { sprintfW(*line_buf + data_pos, format, (unsigned int)value[i]); data_pos += 2; if (++i == value_size) break; (*line_buf)[data_pos++] = ','; column += 3; /* wrap the line */ if (column >= REG_FILE_HEX_LINE_LEN) { lstrcpyW(*line_buf + data_pos, concat); data_pos += concat_len; column = concat_prefix; } } } lstrcpyW(*line_buf + data_pos, newline); HeapFree(GetProcessHeap(), 0, value_multibyte); }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file_name - name of a file to export registry branch to. * reg_key_name - registry branch to export. The whole registry is exported if * reg_key_name is NULL or contains an empty string. */ BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format) { WCHAR *reg_key_name_buf; WCHAR *val_name_buf; BYTE *val_buf; WCHAR *line_buf; DWORD reg_key_name_size = KEY_MAX_LEN; DWORD val_name_size = KEY_MAX_LEN; DWORD val_size = REG_VAL_BUF_SIZE; DWORD line_buf_size = KEY_MAX_LEN + REG_VAL_BUF_SIZE; FILE *file = NULL; BOOL unicode = (format == REG_FORMAT_5); reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_size * sizeof(*reg_key_name_buf)); val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_size * sizeof(*val_name_buf)); val_buf = HeapAlloc(GetProcessHeap(), 0, val_size); line_buf = HeapAlloc(GetProcessHeap(), 0, line_buf_size * sizeof(*line_buf)); CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf && line_buf); if (reg_key_name && reg_key_name[0]) { HKEY reg_key_class; WCHAR *branch_name = NULL; HKEY key; REGPROC_resize_char_buffer(®_key_name_buf, ®_key_name_size, lstrlenW(reg_key_name)); lstrcpyW(reg_key_name_buf, reg_key_name); /* open the specified key */ if (!parseKeyName(reg_key_name, ®_key_class, &branch_name)) { CHAR* key_nameA = GetMultiByteString(reg_key_name); fprintf(stderr,"%s: Incorrect registry class specification in '%s'\n", getAppName(), key_nameA); HeapFree(GetProcessHeap(), 0, key_nameA); exit(1); } if (!branch_name[0]) { /* no branch - registry class is specified */ file = REGPROC_open_export_file(file_name, unicode); export_hkey(file, reg_key_class, ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); } else if (RegOpenKeyW(reg_key_class, branch_name, &key) == ERROR_SUCCESS) { file = REGPROC_open_export_file(file_name, unicode); export_hkey(file, key, ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); RegCloseKey(key); } else { CHAR* key_nameA = GetMultiByteString(reg_key_name); fprintf(stderr,"%s: Can't export. Registry key '%s' does not exist!\n", getAppName(), key_nameA); HeapFree(GetProcessHeap(), 0, key_nameA); REGPROC_print_error(); } } else { unsigned int i; /* export all registry classes */ file = REGPROC_open_export_file(file_name, unicode); for (i = 0; i < REG_CLASS_NUMBER; i++) { /* do not export HKEY_CLASSES_ROOT */ if (reg_class_keys[i] != HKEY_CLASSES_ROOT && reg_class_keys[i] != HKEY_CURRENT_USER && reg_class_keys[i] != HKEY_CURRENT_CONFIG && reg_class_keys[i] != HKEY_DYN_DATA) { lstrcpyW(reg_key_name_buf, reg_class_namesW[i]); export_hkey(file, reg_class_keys[i], ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); } } } if (file) { fclose(file); } HeapFree(GetProcessHeap(), 0, reg_key_name); HeapFree(GetProcessHeap(), 0, val_name_buf); HeapFree(GetProcessHeap(), 0, val_buf); HeapFree(GetProcessHeap(), 0, line_buf); return TRUE; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file - writable file stream to export registry branch to. * key - registry branch to export. * reg_key_name_buf - name of the key with registry class. * Is resized if necessary. * reg_key_name_size - length of the buffer for the registry class in characters. * val_name_buf - buffer for storing value name. * Is resized if necessary. * val_name_size - length of the buffer for storing value names in characters. * val_buf - buffer for storing values while extracting. * Is resized if necessary. * val_size - size of the buffer for storing values in bytes. */ static void export_hkey(FILE *file, HKEY key, WCHAR **reg_key_name_buf, DWORD *reg_key_name_size, WCHAR **val_name_buf, DWORD *val_name_size, BYTE **val_buf, DWORD *val_size, WCHAR **line_buf, DWORD *line_buf_size, BOOL unicode) { DWORD max_sub_key_len; DWORD max_val_name_len; DWORD max_val_size; DWORD curr_len; DWORD i; BOOL more_data; LONG ret; WCHAR key_format[] = {'\r','\n','[','%','s',']','\r','\n',0}; /* get size information and resize the buffers if necessary */ if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL, NULL, &max_val_name_len, &max_val_size, NULL, NULL ) != ERROR_SUCCESS) { REGPROC_print_error(); } curr_len = strlenW(*reg_key_name_buf); REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, max_sub_key_len + curr_len + 1); REGPROC_resize_char_buffer(val_name_buf, val_name_size, max_val_name_len); REGPROC_resize_binary_buffer(val_buf, val_size, max_val_size); REGPROC_resize_char_buffer(line_buf, line_buf_size, lstrlenW(*reg_key_name_buf) + 4); /* output data for the current key */ sprintfW(*line_buf, key_format, *reg_key_name_buf); REGPROC_write_line(file, *line_buf, unicode); /* print all the values */ i = 0; more_data = TRUE; while(more_data) { DWORD value_type; DWORD val_name_size1 = *val_name_size; DWORD val_size1 = *val_size; ret = RegEnumValueW(key, i, *val_name_buf, &val_name_size1, NULL, &value_type, *val_buf, &val_size1); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffers and retry */ REGPROC_resize_char_buffer(val_name_buf, val_name_size, val_name_size1); REGPROC_resize_binary_buffer(val_buf, val_size, val_size1); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { DWORD line_len; i++; if ((*val_name_buf)[0]) { const WCHAR val_start[] = {'"','%','s','"','=',0}; line_len = 0; REGPROC_export_string(line_buf, line_buf_size, &line_len, *val_name_buf, lstrlenW(*val_name_buf)); REGPROC_resize_char_buffer(val_name_buf, val_name_size, lstrlenW(*line_buf) + 1); lstrcpyW(*val_name_buf, *line_buf); line_len = 3 + lstrlenW(*val_name_buf); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); sprintfW(*line_buf, val_start, *val_name_buf); } else { const WCHAR std_val[] = {'@','=',0}; line_len = 2; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); lstrcpyW(*line_buf, std_val); } switch (value_type) { case REG_SZ: { WCHAR* wstr = (WCHAR*)*val_buf; if (val_size1 < sizeof(WCHAR) || val_size1 % sizeof(WCHAR) || wstr[val_size1 / sizeof(WCHAR) - 1]) { REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } else { const WCHAR start[] = {'"',0}; const WCHAR end[] = {'"','\r','\n',0}; DWORD len; len = lstrlenW(start); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len); lstrcpyW(*line_buf + line_len, start); line_len += len; /* At this point we know wstr is '\0'-terminated * so we can subtract 1 from the size */ REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, val_size1 / sizeof(WCHAR) - 1); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end)); lstrcpyW(*line_buf + line_len, end); } break; } case REG_DWORD: { WCHAR format[] = {'d','w','o','r','d',':','%','0','8','x','\r','\n',0}; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + 15); sprintfW(*line_buf + line_len, format, *((DWORD *)*val_buf)); break; } default: { char* key_nameA = GetMultiByteString(*reg_key_name_buf); char* value_nameA = GetMultiByteString(*val_name_buf); fprintf(stderr,"%s: warning - unsupported registry format '%d', " "treat as binary\n", getAppName(), value_type); fprintf(stderr,"key name: \"%s\"\n", key_nameA); fprintf(stderr,"value name:\"%s\"\n\n", value_nameA); HeapFree(GetProcessHeap(), 0, key_nameA); HeapFree(GetProcessHeap(), 0, value_nameA); } /* falls through */ case REG_EXPAND_SZ: case REG_MULTI_SZ: /* falls through */ case REG_BINARY: REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } REGPROC_write_line(file, *line_buf, unicode); } } i = 0; more_data = TRUE; (*reg_key_name_buf)[curr_len] = '\\'; while(more_data) { DWORD buf_size = *reg_key_name_size - curr_len - 1; ret = RegEnumKeyExW(key, i, *reg_key_name_buf + curr_len + 1, &buf_size, NULL, NULL, NULL, NULL); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffer and retry */ REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, curr_len + 1 + buf_size); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { HKEY subkey; i++; if (RegOpenKeyW(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) { export_hkey(file, subkey, reg_key_name_buf, reg_key_name_size, val_name_buf, val_name_size, val_buf, val_size, line_buf, line_buf_size, unicode); RegCloseKey(subkey); } else { REGPROC_print_error(); } } } (*reg_key_name_buf)[curr_len] = '\0'; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file_name - name of a file to export registry branch to. * reg_key_name - registry branch to export. The whole registry is exported if * reg_key_name is NULL or contains an empty string. */ BOOL export_registry_key(WCHAR *file_name, WCHAR *reg_key_name, DWORD format) { WCHAR *reg_key_name_buf; WCHAR *val_name_buf; BYTE *val_buf; WCHAR *line_buf; DWORD reg_key_name_size = KEY_MAX_LEN; DWORD val_name_size = KEY_MAX_LEN; DWORD val_size = REG_VAL_BUF_SIZE; DWORD line_buf_size = KEY_MAX_LEN + REG_VAL_BUF_SIZE; FILE *file = NULL; BOOL unicode = (format == REG_FORMAT_5); reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_size * sizeof(*reg_key_name_buf)); val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_size * sizeof(*val_name_buf)); val_buf = HeapAlloc(GetProcessHeap(), 0, val_size); line_buf = HeapAlloc(GetProcessHeap(), 0, line_buf_size * sizeof(*line_buf)); CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf && line_buf); if (reg_key_name && reg_key_name[0]) { HKEY reg_key_class; WCHAR *branch_name = NULL; HKEY key; REGPROC_resize_char_buffer(®_key_name_buf, ®_key_name_size, lstrlenW(reg_key_name)); lstrcpyW(reg_key_name_buf, reg_key_name); /* open the specified key */ if (!parseKeyName(reg_key_name, ®_key_class, &branch_name)) { output_message(STRING_INCORRECT_REG_CLASS, reg_key_name); exit(1); } if (!branch_name[0]) { /* no branch - registry class is specified */ file = REGPROC_open_export_file(file_name, unicode); export_hkey(file, reg_key_class, ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); } else if (RegOpenKeyW(reg_key_class, branch_name, &key) == ERROR_SUCCESS) { file = REGPROC_open_export_file(file_name, unicode); export_hkey(file, key, ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); RegCloseKey(key); } else { output_message(STRING_REG_KEY_NOT_FOUND, reg_key_name); } } else { unsigned int i; /* export all registry classes */ file = REGPROC_open_export_file(file_name, unicode); for (i = 0; i < ARRAY_SIZE(reg_class_keys); i++) { /* do not export HKEY_CLASSES_ROOT */ if (reg_class_keys[i] != HKEY_CLASSES_ROOT && reg_class_keys[i] != HKEY_CURRENT_USER && reg_class_keys[i] != HKEY_CURRENT_CONFIG && reg_class_keys[i] != HKEY_DYN_DATA) { lstrcpyW(reg_key_name_buf, reg_class_namesW[i]); export_hkey(file, reg_class_keys[i], ®_key_name_buf, ®_key_name_size, &val_name_buf, &val_name_size, &val_buf, &val_size, &line_buf, &line_buf_size, unicode); } } } if (file) { fclose(file); } HeapFree(GetProcessHeap(), 0, reg_key_name); HeapFree(GetProcessHeap(), 0, val_name_buf); HeapFree(GetProcessHeap(), 0, val_buf); HeapFree(GetProcessHeap(), 0, line_buf); return TRUE; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file - writable file stream to export registry branch to. * key - registry branch to export. * reg_key_name_buf - name of the key with registry class. * Is resized if necessary. * reg_key_name_size - length of the buffer for the registry class in characters. * val_name_buf - buffer for storing value name. * Is resized if necessary. * val_name_size - length of the buffer for storing value names in characters. * val_buf - buffer for storing values while extracting. * Is resized if necessary. * val_size - size of the buffer for storing values in bytes. */ static void export_hkey(FILE *file, HKEY key, WCHAR **reg_key_name_buf, DWORD *reg_key_name_size, WCHAR **val_name_buf, DWORD *val_name_size, BYTE **val_buf, DWORD *val_size, WCHAR **line_buf, DWORD *line_buf_size, BOOL unicode) { DWORD max_sub_key_len; DWORD max_val_name_len; DWORD max_val_size; DWORD curr_len; DWORD i; BOOL more_data; LONG ret; WCHAR key_format[] = {'\r','\n','[','%','s',']','\r','\n',0}; /* get size information and resize the buffers if necessary */ if (RegQueryInfoKeyW(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL, NULL, &max_val_name_len, &max_val_size, NULL, NULL ) != ERROR_SUCCESS) { REGPROC_print_error(); } curr_len = strlenW(*reg_key_name_buf); REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, max_sub_key_len + curr_len + 1); REGPROC_resize_char_buffer(val_name_buf, val_name_size, max_val_name_len); REGPROC_resize_binary_buffer(val_buf, val_size, max_val_size); REGPROC_resize_char_buffer(line_buf, line_buf_size, lstrlenW(*reg_key_name_buf) + 4); /* output data for the current key */ sprintfW(*line_buf, key_format, *reg_key_name_buf); REGPROC_write_line(file, *line_buf, unicode); /* print all the values */ i = 0; more_data = TRUE; while(more_data) { DWORD value_type; DWORD val_name_size1 = *val_name_size; DWORD val_size1 = *val_size; ret = RegEnumValueW(key, i, *val_name_buf, &val_name_size1, NULL, &value_type, *val_buf, &val_size1); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffers and retry */ REGPROC_resize_char_buffer(val_name_buf, val_name_size, val_name_size1); REGPROC_resize_binary_buffer(val_buf, val_size, val_size1); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { DWORD line_len; i++; if ((*val_name_buf)[0]) { const WCHAR val_start[] = {'"','%','s','"','=',0}; line_len = 0; REGPROC_export_string(line_buf, line_buf_size, &line_len, *val_name_buf, lstrlenW(*val_name_buf)); REGPROC_resize_char_buffer(val_name_buf, val_name_size, lstrlenW(*line_buf) + 1); lstrcpyW(*val_name_buf, *line_buf); line_len = 3 + lstrlenW(*val_name_buf); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); sprintfW(*line_buf, val_start, *val_name_buf); } else { const WCHAR std_val[] = {'@','=',0}; line_len = 2; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len); lstrcpyW(*line_buf, std_val); } switch (value_type) { case REG_SZ: { WCHAR* wstr = (WCHAR*)*val_buf; if (val_size1 < sizeof(WCHAR) || val_size1 % sizeof(WCHAR) || wstr[val_size1 / sizeof(WCHAR) - 1]) { REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } else { const WCHAR start[] = {'"',0}; const WCHAR end[] = {'"','\r','\n',0}; DWORD len; len = lstrlenW(start); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + len); lstrcpyW(*line_buf + line_len, start); line_len += len; REGPROC_export_string(line_buf, line_buf_size, &line_len, wstr, lstrlenW(wstr)); REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + lstrlenW(end)); lstrcpyW(*line_buf + line_len, end); } break; } case REG_DWORD: { WCHAR format[] = {'d','w','o','r','d',':','%','0','8','x','\r','\n',0}; REGPROC_resize_char_buffer(line_buf, line_buf_size, line_len + 15); sprintfW(*line_buf + line_len, format, *((DWORD *)*val_buf)); break; } default: { output_message(STRING_UNSUPPORTED_TYPE, reg_type_to_wchar(value_type), *reg_key_name_buf); output_message(STRING_EXPORT_AS_BINARY, *val_name_buf); } /* falls through */ case REG_EXPAND_SZ: case REG_MULTI_SZ: /* falls through */ case REG_BINARY: REGPROC_export_binary(line_buf, line_buf_size, &line_len, value_type, *val_buf, val_size1, unicode); } REGPROC_write_line(file, *line_buf, unicode); } } i = 0; more_data = TRUE; (*reg_key_name_buf)[curr_len] = '\\'; while(more_data) { DWORD buf_size = *reg_key_name_size - curr_len - 1; ret = RegEnumKeyExW(key, i, *reg_key_name_buf + curr_len + 1, &buf_size, NULL, NULL, NULL, NULL); if (ret == ERROR_MORE_DATA) { /* Increase the size of the buffer and retry */ REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_size, curr_len + 1 + buf_size); } else if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { HKEY subkey; i++; if (RegOpenKeyW(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) { export_hkey(file, subkey, reg_key_name_buf, reg_key_name_size, val_name_buf, val_name_size, val_buf, val_size, line_buf, line_buf_size, unicode); RegCloseKey(subkey); } else { REGPROC_print_error(); } } } (*reg_key_name_buf)[curr_len] = '\0'; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file_name - name of a file to export registry branch to. * reg_key_name - registry branch to export. The whole registry is exported if * reg_key_name is NULL or contains an empty string. */ BOOL export_registry_key(TCHAR* file_name, TCHAR* reg_key_name) { HKEY reg_key_class; TCHAR *reg_key_name_buf; TCHAR *val_name_buf; BYTE *val_buf; DWORD reg_key_name_len = KEY_MAX_LEN; DWORD val_name_len = KEY_MAX_LEN; DWORD val_size = REG_VAL_BUF_SIZE; FILE *file = NULL; //_tprintf(_T("export_registry_key(%s, %s)\n"), reg_key_name, file_name); reg_key_name_buf = HeapAlloc(GetProcessHeap(), 0, reg_key_name_len * sizeof(*reg_key_name_buf)); val_name_buf = HeapAlloc(GetProcessHeap(), 0, val_name_len * sizeof(*val_name_buf)); val_buf = HeapAlloc(GetProcessHeap(), 0, val_size); CHECK_ENOUGH_MEMORY(reg_key_name_buf && val_name_buf && val_buf); if (reg_key_name && reg_key_name[0]) { TCHAR *branch_name; HKEY key; REGPROC_resize_char_buffer(®_key_name_buf, ®_key_name_len, _tcslen(reg_key_name)); _tcscpy(reg_key_name_buf, reg_key_name); /* open the specified key */ reg_key_class = getRegClass(reg_key_name); if (reg_key_class == (HKEY)ERROR_INVALID_PARAMETER) { _tprintf(_T("Incorrect registry class specification in '%s\n"), reg_key_name); //exit(1); return FALSE; } branch_name = getRegKeyName(reg_key_name); CHECK_ENOUGH_MEMORY(branch_name); if (!branch_name[0]) { /* no branch - registry class is specified */ file = REGPROC_open_export_file(file_name); export_hkey(file, reg_key_class, ®_key_name_buf, ®_key_name_len, &val_name_buf, &val_name_len, &val_buf, &val_size); } else if (RegOpenKey(reg_key_class, branch_name, &key) == ERROR_SUCCESS) { file = REGPROC_open_export_file(file_name); export_hkey(file, key, ®_key_name_buf, ®_key_name_len, &val_name_buf, &val_name_len, &val_buf, &val_size); RegCloseKey(key); } else { _tprintf(_T("Can't export. Registry key '%s does not exist!\n"), reg_key_name); REGPROC_print_error(); } HeapFree(GetProcessHeap(), 0, branch_name); } else { int i; /* export all registry classes */ file = REGPROC_open_export_file(file_name); for (i = 0; i < REG_CLASS_NUMBER; i++) { /* do not export HKEY_CLASSES_ROOT */ if (reg_class_keys[i] != HKEY_CLASSES_ROOT && reg_class_keys[i] != HKEY_CURRENT_USER && reg_class_keys[i] != HKEY_CURRENT_CONFIG) { _tcscpy(reg_key_name_buf, reg_class_names[i]); export_hkey(file, reg_class_keys[i], ®_key_name_buf, ®_key_name_len, &val_name_buf, &val_name_len, &val_buf, &val_size); } } } if (file) { fclose(file); } // HeapFree(GetProcessHeap(), 0, reg_key_name); HeapFree(GetProcessHeap(), 0, val_buf); HeapFree(GetProcessHeap(), 0, val_name_buf); HeapFree(GetProcessHeap(), 0, reg_key_name_buf); return TRUE; }
/****************************************************************************** * Writes contents of the registry key to the specified file stream. * * Parameters: * file - writable file stream to export registry branch to. * key - registry branch to export. * reg_key_name_buf - name of the key with registry class. * Is resized if necessary. * reg_key_name_len - length of the buffer for the registry class in characters. * val_name_buf - buffer for storing value name. * Is resized if necessary. * val_name_len - length of the buffer for storing value names in characters. * val_buf - buffer for storing values while extracting. * Is resized if necessary. * val_size - size of the buffer for storing values in bytes. */ void export_hkey(FILE *file, HKEY key, TCHAR **reg_key_name_buf, DWORD *reg_key_name_len, TCHAR **val_name_buf, DWORD *val_name_len, BYTE **val_buf, DWORD *val_size) { DWORD max_sub_key_len; DWORD max_val_name_len; DWORD max_val_size; DWORD curr_len; DWORD i; BOOL more_data; LONG ret; /* get size information and resize the buffers if necessary */ if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &max_sub_key_len, NULL, NULL, &max_val_name_len, &max_val_size, NULL, NULL) != ERROR_SUCCESS) { REGPROC_print_error(); } curr_len = _tcslen(*reg_key_name_buf); REGPROC_resize_char_buffer(reg_key_name_buf, reg_key_name_len, max_sub_key_len + curr_len + 1); REGPROC_resize_char_buffer(val_name_buf, val_name_len, max_val_name_len); if (max_val_size > *val_size) { *val_size = max_val_size; *val_buf = HeapReAlloc(GetProcessHeap(), 0, *val_buf, *val_size * sizeof(TCHAR)); CHECK_ENOUGH_MEMORY(val_buf); } /* output data for the current key */ _fputts(_T("\n["), file); _fputts(*reg_key_name_buf, file); _fputts(_T("]\n"), file); /* print all the values */ i = 0; more_data = TRUE; while (more_data) { DWORD value_type; DWORD val_name_len1 = *val_name_len; DWORD val_size1 = *val_size; ret = RegEnumValue(key, i, *val_name_buf, &val_name_len1, NULL, &value_type, *val_buf, &val_size1); if (ret != ERROR_SUCCESS) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { i++; if ((*val_name_buf)[0]) { _fputts(_T("\""), file); REGPROC_export_string(file, *val_name_buf); _fputts(_T("\"="), file); } else { _fputts(_T("@="), file); } switch (value_type) { case REG_EXPAND_SZ: _fputts(_T("expand:"), file); case REG_SZ: _fputts(_T("\""), file); REGPROC_export_string(file, *val_buf); _fputts(_T("\"\n"), file); break; case REG_DWORD: _ftprintf(file, _T("dword:%08lx\n"), *((DWORD *)*val_buf)); break; default: /* _tprintf(_T("warning - unsupported registry format '%ld', ") \ _T("treating as binary\n"), value_type); _tprintf(_T("key name: \"%s\"\n"), *reg_key_name_buf); _tprintf(_T("value name:\"%s\"\n\n"), *val_name_buf); */ /* falls through */ case REG_MULTI_SZ: /* falls through */ case REG_BINARY: { DWORD i1; TCHAR *hex_prefix; TCHAR buf[20]; int cur_pos; if (value_type == REG_BINARY) { hex_prefix = _T("hex:"); } else { hex_prefix = buf; _stprintf(buf, _T("hex(%ld):"), value_type); } /* position of where the next character will be printed */ /* NOTE: yes, _tcslen("hex:") is used even for hex(x): */ cur_pos = _tcslen(_T("\"\"=")) + _tcslen(_T("hex:")) + _tcslen(*val_name_buf); _fputts(hex_prefix, file); for (i1 = 0; i1 < val_size1; i1++) { _ftprintf(file, _T("%02x"), (unsigned int)(*val_buf)[i1]); if (i1 + 1 < val_size1) { _fputts(_T(","), file); } cur_pos += 3; /* wrap the line */ if (cur_pos > REG_FILE_HEX_LINE_LEN) { _fputts(_T("\\\n "), file); cur_pos = 2; } } _fputts(_T("\n"), file); break; } } } } i = 0; more_data = TRUE; (*reg_key_name_buf)[curr_len] = _T('\\'); while (more_data) { DWORD buf_len = *reg_key_name_len - curr_len; ret = RegEnumKeyEx(key, i, *reg_key_name_buf + curr_len + 1, &buf_len, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) { more_data = FALSE; if (ret != ERROR_NO_MORE_ITEMS) { REGPROC_print_error(); } } else { HKEY subkey; i++; if (RegOpenKey(key, *reg_key_name_buf + curr_len + 1, &subkey) == ERROR_SUCCESS) { export_hkey(file, subkey, reg_key_name_buf, reg_key_name_len, val_name_buf, val_name_len, val_buf, val_size); RegCloseKey(subkey); } else { REGPROC_print_error(); } } } (*reg_key_name_buf)[curr_len] = _T('\0'); }