/****************************************************************************** * 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 - 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 - 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'); }