static void register_manifest( const WCHAR *dll_name, const char *manifest, DWORD len, const void *dll_data, size_t dll_size ) { #ifdef __i386__ static const char current_arch[] = "x86"; #elif defined __x86_64__ static const char current_arch[] = "amd64"; #else static const char current_arch[] = "none"; #endif xmlbuf_t buffer; xmlstr_t elem, attr_name, attr_value; xmlstr_t name, version, arch, key, lang; BOOL end = FALSE, error; buffer.ptr = manifest; buffer.end = manifest + len; name.ptr = version.ptr = arch.ptr = key.ptr = lang.ptr = NULL; name.len = version.len = arch.len = key.len = lang.len = 0; while (next_xml_elem( &buffer, &elem )) { if (!xmlstr_cmp( &elem, "assemblyIdentity" )) continue; while (next_xml_attr( &buffer, &attr_name, &attr_value, &error, &end )) { if (xmlstr_cmp(&attr_name, "name")) name = attr_value; else if (xmlstr_cmp(&attr_name, "version")) version = attr_value; else if (xmlstr_cmp(&attr_name, "processorArchitecture")) arch = attr_value; else if (xmlstr_cmp(&attr_name, "publicKeyToken")) key = attr_value; else if (xmlstr_cmp(&attr_name, "language")) lang = attr_value; } if (!error && name.ptr && version.ptr && arch.ptr && key.ptr) { if (!lang.ptr) { lang.ptr = "none"; lang.len = strlen( lang.ptr ); } if (!arch.len) /* fixup the architecture */ { char *new_buffer = HeapAlloc( GetProcessHeap(), 0, len + sizeof(current_arch) ); memcpy( new_buffer, manifest, arch.ptr - manifest ); strcpy( new_buffer + (arch.ptr - manifest), current_arch ); memcpy( new_buffer + strlen(new_buffer), arch.ptr, len - (arch.ptr - manifest) ); arch.ptr = current_arch; arch.len = strlen( current_arch ); if (create_winsxs_dll( dll_name, &arch, &name, &key, &version, &lang, dll_data, dll_size )) create_manifest( &arch, &name, &key, &version, &lang, new_buffer, len + arch.len ); HeapFree( GetProcessHeap(), 0, new_buffer ); } else { if (create_winsxs_dll( dll_name, &arch, &name, &key, &version, &lang, dll_data, dll_size )) create_manifest( &arch, &name, &key, &version, &lang, manifest, len ); } } } }
static BOOL CALLBACK register_manifest( HMODULE module, const WCHAR *type, WCHAR *res_name, LONG_PTR arg ) { #ifdef __i386__ static const char current_arch[] = "x86"; #elif defined __x86_64__ static const char current_arch[] = "amd64"; #else static const char current_arch[] = "none"; #endif static const WCHAR manifestW[] = {'W','I','N','E','_','M','A','N','I','F','E','S','T'}; const struct dll_data *dll_data = (const struct dll_data*)arg; xmlbuf_t buffer; xmlstr_t elem, attr_name, attr_value; xmlstr_t name, version, arch, key, lang; BOOL end = FALSE, error; const char *manifest; SIZE_T len; HRSRC rsrc; if (IS_INTRESOURCE(res_name) || strncmpW( res_name, manifestW, sizeof(manifestW)/sizeof(WCHAR) )) return TRUE; rsrc = FindResourceW( module, res_name, type ); manifest = LoadResource( module, rsrc ); len = SizeofResource( module, rsrc ); buffer.ptr = manifest; buffer.end = manifest + len; name.ptr = version.ptr = arch.ptr = key.ptr = lang.ptr = NULL; name.len = version.len = arch.len = key.len = lang.len = 0; while (next_xml_elem( &buffer, &elem )) { if (!xmlstr_cmp( &elem, "assemblyIdentity" )) continue; while (next_xml_attr( &buffer, &attr_name, &attr_value, &error, &end )) { if (xmlstr_cmp(&attr_name, "name")) name = attr_value; else if (xmlstr_cmp(&attr_name, "version")) version = attr_value; else if (xmlstr_cmp(&attr_name, "processorArchitecture")) arch = attr_value; else if (xmlstr_cmp(&attr_name, "publicKeyToken")) key = attr_value; else if (xmlstr_cmp(&attr_name, "language")) lang = attr_value; } if (!error && name.ptr && version.ptr && arch.ptr && key.ptr) { if (!lang.ptr) { lang.ptr = "none"; lang.len = strlen( lang.ptr ); } if (!arch.len) /* fixup the architecture */ { char *new_buffer = HeapAlloc( GetProcessHeap(), 0, len + sizeof(current_arch) ); memcpy( new_buffer, manifest, arch.ptr - manifest ); strcpy( new_buffer + (arch.ptr - manifest), current_arch ); memcpy( new_buffer + strlen(new_buffer), arch.ptr, len - (arch.ptr - manifest) ); arch.ptr = current_arch; arch.len = strlen( current_arch ); if (create_winsxs_dll( dll_data->name, &arch, &name, &key, &version, &lang, dll_data->data, dll_data->size )) create_manifest( &arch, &name, &key, &version, &lang, new_buffer, len + arch.len ); HeapFree( GetProcessHeap(), 0, new_buffer ); } else { if (create_winsxs_dll( dll_data->name, &arch, &name, &key, &version, &lang, dll_data->data, dll_data->size )) create_manifest( &arch, &name, &key, &version, &lang, manifest, len ); } } } return TRUE; }