X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fio-layer%2Fversioninfo.c;h=2ba7fc96d5554ee1eaa5d1c7221aabaa020896ae;hb=09456b827bab4a89758be84c464abfcbf59f7ce7;hp=d61ca7fa2a0a5c31aa060248ebaf76abc03e31f5;hpb=e7b8a0eb35714c02bd70ca7bfcf9118b1aee3fb2;p=mono.git diff --git a/mono/io-layer/versioninfo.c b/mono/io-layer/versioninfo.c index d61ca7fa2a0..2ba7fc96d55 100644 --- a/mono/io-layer/versioninfo.c +++ b/mono/io-layer/versioninfo.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -24,12 +23,20 @@ #include #include #include +#include -#undef DEBUG +#if 0 +// #define DEBUG(...) g_message(__VA_ARGS__) +#else +#define DEBUG(...) +#endif + +#define ALIGN32(ptr) ptr = (gpointer)((char *)ptr + 3); ptr = (gpointer)((char *)ptr - ((gsize)ptr & 3)); -static WapiImageSectionHeader *get_enclosing_section_header (guint32 rva, WapiImageNTHeaders *nt_headers) +static WapiImageSectionHeader * +get_enclosing_section_header (guint32 rva, WapiImageNTHeaders32 *nt_headers) { - WapiImageSectionHeader *section = IMAGE_FIRST_SECTION (nt_headers); + WapiImageSectionHeader *section = _WAPI_IMAGE_FIRST_SECTION32 (nt_headers); guint32 i; for (i = 0; i < GUINT16_FROM_LE (nt_headers->FileHeader.NumberOfSections); i++, section++) { @@ -47,8 +54,11 @@ static WapiImageSectionHeader *get_enclosing_section_header (guint32 rva, WapiIm return(NULL); } -static gpointer get_ptr_from_rva (guint32 rva, WapiImageNTHeaders *ntheaders, - gpointer file_map) +/* This works for both 32bit and 64bit files, as the differences are + * all after the section header block + */ +static gpointer +get_ptr_from_rva (guint32 rva, WapiImageNTHeaders32 *ntheaders, gpointer file_map) { WapiImageSectionHeader *section_header; guint32 delta; @@ -64,12 +74,13 @@ static gpointer get_ptr_from_rva (guint32 rva, WapiImageNTHeaders *ntheaders, return((guint8 *)file_map + rva - delta); } -static gpointer scan_resource_dir (WapiImageResourceDirectory *root, - WapiImageNTHeaders *nt_headers, - gpointer file_map, - WapiImageResourceDirectoryEntry *entry, - int level, guint32 res_id, guint32 lang_id, - guint32 *size) +static gpointer +scan_resource_dir (WapiImageResourceDirectory *root, + WapiImageNTHeaders32 *nt_headers, + gpointer file_map, + WapiImageResourceDirectoryEntry *entry, + int level, guint32 res_id, guint32 lang_id, + guint32 *size) { WapiImageResourceDirectoryEntry swapped_entry; gboolean is_string, is_dir; @@ -138,12 +149,13 @@ static gpointer scan_resource_dir (WapiImageResourceDirectory *root, } } -static gpointer find_pe_file_resources (gpointer file_map, guint32 map_size, - guint32 res_id, guint32 lang_id, - guint32 *size) +static gpointer +find_pe_file_resources32 (gpointer file_map, guint32 map_size, + guint32 res_id, guint32 lang_id, + guint32 *size) { WapiImageDosHeader *dos_header; - WapiImageNTHeaders *nt_headers; + WapiImageNTHeaders32 *nt_headers; WapiImageResourceDirectory *resource_dir; WapiImageResourceDirectoryEntry *resource_dir_entry; guint32 resource_rva, entries, i; @@ -151,30 +163,22 @@ static gpointer find_pe_file_resources (gpointer file_map, guint32 map_size, dos_header = (WapiImageDosHeader *)file_map; if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { -#ifdef DEBUG - g_message ("%s: Bad dos signature 0x%x", __func__, - dos_header->e_magic); -#endif + DEBUG ("%s: Bad dos signature 0x%x", __func__, dos_header->e_magic); SetLastError (ERROR_INVALID_DATA); return(NULL); } - if (map_size < sizeof(WapiImageNTHeaders) + GUINT32_FROM_LE (dos_header->e_lfanew)) { -#ifdef DEBUG - g_message ("%s: File is too small: %d", __func__, map_size); -#endif + if (map_size < sizeof(WapiImageNTHeaders32) + GUINT32_FROM_LE (dos_header->e_lfanew)) { + DEBUG ("%s: File is too small: %d", __func__, map_size); SetLastError (ERROR_BAD_LENGTH); return(NULL); } - nt_headers = (WapiImageNTHeaders *)((guint8 *)file_map + GUINT32_FROM_LE (dos_header->e_lfanew)); + nt_headers = (WapiImageNTHeaders32 *)((guint8 *)file_map + GUINT32_FROM_LE (dos_header->e_lfanew)); if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { -#ifdef DEBUG - g_message ("%s: Bad NT signature 0x%x", __func__, - nt_headers->Signature); -#endif + DEBUG ("%s: Bad NT signature 0x%x", __func__, nt_headers->Signature); SetLastError (ERROR_INVALID_DATA); return(NULL); @@ -188,18 +192,16 @@ static gpointer find_pe_file_resources (gpointer file_map, guint32 map_size, } if (resource_rva == 0) { -#ifdef DEBUG - g_message ("%s: No resources in file!", __func__); -#endif + DEBUG ("%s: No resources in file!", __func__); + SetLastError (ERROR_INVALID_DATA); return(NULL); } - resource_dir = (WapiImageResourceDirectory *)get_ptr_from_rva (resource_rva, nt_headers, file_map); + resource_dir = (WapiImageResourceDirectory *)get_ptr_from_rva (resource_rva, (WapiImageNTHeaders32 *)nt_headers, file_map); if (resource_dir == NULL) { -#ifdef DEBUG - g_message ("%s: Can't find resource directory", __func__); -#endif + DEBUG ("%s: Can't find resource directory", __func__); + SetLastError (ERROR_INVALID_DATA); return(NULL); } @@ -209,17 +211,110 @@ static gpointer find_pe_file_resources (gpointer file_map, guint32 map_size, for (i = 0; i < entries; i++) { WapiImageResourceDirectoryEntry *direntry = &resource_dir_entry[i]; - ret = scan_resource_dir (resource_dir, nt_headers, file_map, - direntry, 0, res_id, lang_id, size); + ret = scan_resource_dir (resource_dir, + (WapiImageNTHeaders32 *)nt_headers, + file_map, direntry, 0, res_id, + lang_id, size); if (ret != NULL) { return(ret); } } + + return(NULL); +} + +static gpointer +find_pe_file_resources64 (gpointer file_map, guint32 map_size, + guint32 res_id, guint32 lang_id, + guint32 *size) +{ + WapiImageDosHeader *dos_header; + WapiImageNTHeaders64 *nt_headers; + WapiImageResourceDirectory *resource_dir; + WapiImageResourceDirectoryEntry *resource_dir_entry; + guint32 resource_rva, entries, i; + gpointer ret = NULL; + + dos_header = (WapiImageDosHeader *)file_map; + if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) { + DEBUG ("%s: Bad dos signature 0x%x", __func__, dos_header->e_magic); + + SetLastError (ERROR_INVALID_DATA); + return(NULL); + } + if (map_size < sizeof(WapiImageNTHeaders64) + GUINT32_FROM_LE (dos_header->e_lfanew)) { + DEBUG ("%s: File is too small: %d", __func__, map_size); + + SetLastError (ERROR_BAD_LENGTH); + return(NULL); + } + + nt_headers = (WapiImageNTHeaders64 *)((guint8 *)file_map + GUINT32_FROM_LE (dos_header->e_lfanew)); + if (nt_headers->Signature != IMAGE_NT_SIGNATURE) { + DEBUG ("%s: Bad NT signature 0x%x", __func__, + nt_headers->Signature); + + SetLastError (ERROR_INVALID_DATA); + return(NULL); + } + + if (nt_headers->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + /* Do 64-bit stuff */ + resource_rva = GUINT32_FROM_LE (((WapiImageNTHeaders64 *)nt_headers)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + } else { + resource_rva = GUINT32_FROM_LE (nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress); + } + + if (resource_rva == 0) { + DEBUG ("%s: No resources in file!", __func__); + + SetLastError (ERROR_INVALID_DATA); + return(NULL); + } + + resource_dir = (WapiImageResourceDirectory *)get_ptr_from_rva (resource_rva, (WapiImageNTHeaders32 *)nt_headers, file_map); + if (resource_dir == NULL) { + DEBUG ("%s: Can't find resource directory", __func__); + + SetLastError (ERROR_INVALID_DATA); + return(NULL); + } + + entries = GUINT16_FROM_LE (resource_dir->NumberOfNamedEntries) + GUINT16_FROM_LE (resource_dir->NumberOfIdEntries); + resource_dir_entry = (WapiImageResourceDirectoryEntry *)(resource_dir + 1); + + for (i = 0; i < entries; i++) { + WapiImageResourceDirectoryEntry *direntry = &resource_dir_entry[i]; + ret = scan_resource_dir (resource_dir, + (WapiImageNTHeaders32 *)nt_headers, + file_map, direntry, 0, res_id, + lang_id, size); + if (ret != NULL) { + return(ret); + } + } + return(NULL); } -static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) +static gpointer +find_pe_file_resources (gpointer file_map, guint32 map_size, + guint32 res_id, guint32 lang_id, + guint32 *size) +{ + /* Figure this out when we support 64bit PE files */ + if (1) { + return find_pe_file_resources32 (file_map, map_size, res_id, + lang_id, size); + } else { + return find_pe_file_resources64 (file_map, map_size, res_id, + lang_id, size); + } +} + +static gpointer +map_pe_file (gunichar2 *filename, gint32 *map_size, void **handle) { gchar *filename_ext; int fd; @@ -233,9 +328,7 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) filename_ext = mono_unicode_to_external (filename); if (filename_ext == NULL) { -#ifdef DEBUG - g_message ("%s: unicode conversion returned NULL", __func__); -#endif + DEBUG ("%s: unicode conversion returned NULL", __func__); SetLastError (ERROR_INVALID_NAME); return(NULL); @@ -243,10 +336,7 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) fd = _wapi_open (filename_ext, O_RDONLY, 0); if (fd == -1) { -#ifdef DEBUG - g_message ("%s: Error opening file %s: %s", __func__, - filename_ext, strerror (errno)); -#endif + DEBUG ("%s: Error opening file %s: %s", __func__, filename_ext, strerror (errno)); SetLastError (_wapi_get_win32_file_error (errno)); g_free (filename_ext); @@ -255,10 +345,7 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) } if (fstat (fd, &statbuf) == -1) { -#ifdef DEBUG - g_message ("%s: Error stat()ing file %s: %s", __func__, - filename_ext, strerror (errno)); -#endif + DEBUG ("%s: Error stat()ing file %s: %s", __func__, filename_ext, strerror (errno)); SetLastError (_wapi_get_win32_file_error (errno)); g_free (filename_ext); @@ -266,13 +353,10 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) return(NULL); } *map_size = statbuf.st_size; - + /* Check basic file size */ if (statbuf.st_size < sizeof(WapiImageDosHeader)) { -#ifdef DEBUG - g_message ("%s: File %s is too small: %ld", __func__, - filename_ext, statbuf.st_size); -#endif + DEBUG ("%s: File %s is too small: %lld", __func__, filename_ext, statbuf.st_size); SetLastError (ERROR_BAD_LENGTH); g_free (filename_ext); @@ -280,12 +364,9 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) return(NULL); } - file_map = mmap (NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (file_map == MAP_FAILED) { -#ifdef DEBUG - g_message ("%s: Error mmap()int file %s: %s", __func__, - filename_ext, strerror (errno)); -#endif + file_map = mono_file_map (statbuf.st_size, MONO_MMAP_READ | MONO_MMAP_PRIVATE, fd, 0, handle); + if (file_map == NULL) { + DEBUG ("%s: Error mmap()int file %s: %s", __func__, filename_ext, strerror (errno)); SetLastError (_wapi_get_win32_file_error (errno)); g_free (filename_ext); @@ -295,16 +376,19 @@ static gpointer map_pe_file (gunichar2 *filename, guint32 *map_size) /* Don't need the fd any more */ close (fd); + g_free (filename_ext); return(file_map); } -static void unmap_pe_file (gpointer file_map, guint32 map_size) +static void +unmap_pe_file (gpointer file_map, void *handle) { - munmap (file_map, map_size); + mono_file_unmap (file_map, handle); } -static guint32 unicode_chars (const gunichar2 *str) +static guint32 +unicode_chars (const gunichar2 *str) { guint32 len = 0; @@ -316,7 +400,8 @@ static guint32 unicode_chars (const gunichar2 *str) } while(1); } -static gboolean unicode_compare (const gunichar2 *str1, const gunichar2 *str2) +static gboolean +unicode_compare (const gunichar2 *str1, const gunichar2 *str2) { while (*str1 && *str2) { if (*str1 != *str2) { @@ -332,7 +417,8 @@ static gboolean unicode_compare (const gunichar2 *str1, const gunichar2 *str2) /* compare a little-endian null-terminated utf16 string and a normal string. * Can be used only for ascii or latin1 chars. */ -static gboolean unicode_string_equals (const gunichar2 *str1, const gchar *str2) +static gboolean +unicode_string_equals (const gunichar2 *str1, const gchar *str2) { while (*str1 && *str2) { if (GUINT16_TO_LE (*str1) != *str2) { @@ -356,8 +442,8 @@ typedef struct /* Returns a pointer to the value data, because there's no way to know * how big that data is (value_len is set to zero for most blocks :-( ) */ -static gconstpointer get_versioninfo_block (gconstpointer data, - version_data *block) +static gconstpointer +get_versioninfo_block (gconstpointer data, version_data *block) { block->data_len = GUINT16_FROM_LE (*((guint16 *)data)); data = (char *)data + sizeof(guint16); @@ -373,14 +459,13 @@ static gconstpointer get_versioninfo_block (gconstpointer data, data = ((gunichar2 *)data) + (unicode_chars (block->key) + 1); /* align on a 32-bit boundary */ - data = (gpointer)((char *)data + 3); - data = (gpointer)((char *)data - (GPOINTER_TO_INT (data) & 3)); + ALIGN32 (data); return(data); } -static gconstpointer get_fixedfileinfo_block (gconstpointer data, - version_data *block) +static gconstpointer +get_fixedfileinfo_block (gconstpointer data, version_data *block) { gconstpointer data_ptr; gint32 data_len; /* signed to guard against underflow */ @@ -390,33 +475,29 @@ static gconstpointer get_fixedfileinfo_block (gconstpointer data, data_len = block->data_len; if (block->value_len != sizeof(WapiFixedFileInfo)) { -#ifdef DEBUG - g_message ("%s: FIXEDFILEINFO size mismatch", __func__); -#endif + DEBUG ("%s: FIXEDFILEINFO size mismatch", __func__); return(NULL); } if (!unicode_string_equals (block->key, "VS_VERSION_INFO")) { -#ifdef DEBUG - g_message ("%s: VS_VERSION_INFO mismatch", __func__); -#endif + DEBUG ("%s: VS_VERSION_INFO mismatch", __func__); + return(NULL); } ffi = ((WapiFixedFileInfo *)data_ptr); if ((ffi->dwSignature != VS_FFI_SIGNATURE) || (ffi->dwStrucVersion != VS_FFI_STRUCVERSION)) { -#ifdef DEBUG - g_message ("%s: FIXEDFILEINFO bad signature", __func__); -#endif + DEBUG ("%s: FIXEDFILEINFO bad signature", __func__); + return(NULL); } return(data_ptr); } -static gconstpointer get_varfileinfo_block (gconstpointer data_ptr, - version_data *block) +static gconstpointer +get_varfileinfo_block (gconstpointer data_ptr, version_data *block) { /* data is pointing at a Var block */ @@ -425,11 +506,12 @@ static gconstpointer get_varfileinfo_block (gconstpointer data_ptr, return(data_ptr); } -static gconstpointer get_string_block (gconstpointer data_ptr, - const gunichar2 *string_key, - gpointer *string_value, - guint32 *string_value_len, - version_data *block) +static gconstpointer +get_string_block (gconstpointer data_ptr, + const gunichar2 *string_key, + gpointer *string_value, + guint32 *string_value_len, + version_data *block) { guint16 data_len = block->data_len; guint16 string_len = 28; /* Length of the StringTable block */ @@ -441,18 +523,15 @@ static gconstpointer get_string_block (gconstpointer data_ptr, */ while (((char *)data_ptr - (char *)orig_data_ptr) < data_len) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, block); if (block->data_len == 0) { /* We must have hit padding, so give up * processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", - __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); + return(NULL); } @@ -480,16 +559,18 @@ static gconstpointer get_string_block (gconstpointer data_ptr, * * If lang == NULL it means we're just stepping through this block */ -static gconstpointer get_stringtable_block (gconstpointer data_ptr, - gchar *lang, - const gunichar2 *string_key, - gpointer *string_value, - guint32 *string_value_len, - version_data *block) +static gconstpointer +get_stringtable_block (gconstpointer data_ptr, + gchar *lang, + const gunichar2 *string_key, + gpointer *string_value, + guint32 *string_value_len, + version_data *block) { guint16 data_len = block->data_len; guint16 string_len = 36; /* length of the StringFileInfo block */ gchar *found_lang; + gchar *lowercase_lang; /* data_ptr is pointing at an array of StringTable blocks, * with total length (not including alignment padding) of @@ -498,18 +579,14 @@ static gconstpointer get_stringtable_block (gconstpointer data_ptr, while(string_len < data_len) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, block); if (block->data_len == 0) { /* We must have hit padding, so give up * processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", - __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); return(NULL); } @@ -517,13 +594,14 @@ static gconstpointer get_stringtable_block (gconstpointer data_ptr, found_lang = g_utf16_to_utf8 (block->key, 8, NULL, NULL, NULL); if (found_lang == NULL) { -#ifdef DEBUG - g_message ("%s: Didn't find a valid language key, giving up", __func__); -#endif + DEBUG ("%s: Didn't find a valid language key, giving up", __func__); return(NULL); } - g_strdown (found_lang); + lowercase_lang = g_utf8_strdown (found_lang, -1); + g_free (found_lang); + found_lang = lowercase_lang; + lowercase_lang = NULL; if (lang != NULL && !strcmp (found_lang, lang)) { /* Got the one we're interested in */ @@ -539,9 +617,7 @@ static gconstpointer get_stringtable_block (gconstpointer data_ptr, if (data_ptr == NULL) { /* Child block hit padding */ -#ifdef DEBUG - g_message ("%s: Child block hit 0-length block, giving up", __func__); -#endif + DEBUG ("%s: Child block hit 0-length block, giving up", __func__); return(NULL); } } @@ -550,8 +626,8 @@ static gconstpointer get_stringtable_block (gconstpointer data_ptr, } #if G_BYTE_ORDER == G_BIG_ENDIAN -static gconstpointer big_up_string_block (gconstpointer data_ptr, - version_data *block) +static gconstpointer +big_up_string_block (gconstpointer data_ptr, version_data *block) { guint16 data_len = block->data_len; guint16 string_len = 28; /* Length of the StringTable block */ @@ -564,18 +640,14 @@ static gconstpointer big_up_string_block (gconstpointer data_ptr, */ while (((char *)data_ptr - (char *)orig_data_ptr) < data_len) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, block); if (block->data_len == 0) { /* We must have hit padding, so give up * processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", - __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); return(NULL); } @@ -586,10 +658,7 @@ static gconstpointer big_up_string_block (gconstpointer data_ptr, "UTF-16BE", "UTF-16LE", NULL, NULL, NULL); if (big_value == NULL) { -#ifdef DEBUG - g_message ("%s: Didn't find a valid string, giving up", - __func__); -#endif + DEBUG ("%s: Didn't find a valid string, giving up", __func__); return(NULL); } @@ -606,9 +675,7 @@ static gconstpointer big_up_string_block (gconstpointer data_ptr, "UTF-16BE", "UTF-16LE", NULL, NULL, NULL); if (big_value == NULL) { -#ifdef DEBUG - g_message ("%s: Didn't find a valid data string, giving up", __func__); -#endif + DEBUG ("%s: Didn't find a valid data string, giving up", __func__); return(NULL); } memcpy ((gpointer)data_ptr, big_value, @@ -626,8 +693,8 @@ static gconstpointer big_up_string_block (gconstpointer data_ptr, * because the data length does not include padding bytes, so it's not * possible to just return the start position + length */ -static gconstpointer big_up_stringtable_block (gconstpointer data_ptr, - version_data *block) +static gconstpointer +big_up_stringtable_block (gconstpointer data_ptr, version_data *block) { guint16 data_len = block->data_len; guint16 string_len = 36; /* length of the StringFileInfo block */ @@ -640,18 +707,14 @@ static gconstpointer big_up_stringtable_block (gconstpointer data_ptr, while(string_len < data_len) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, block); if (block->data_len == 0) { /* We must have hit padding, so give up * processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", - __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); return(NULL); } @@ -660,10 +723,7 @@ static gconstpointer big_up_stringtable_block (gconstpointer data_ptr, big_value = g_convert ((gchar *)block->key, 16, "UTF-16BE", "UTF-16LE", NULL, NULL, NULL); if (big_value == NULL) { -#ifdef DEBUG - g_message ("%s: Didn't find a valid string, giving up", - __func__); -#endif + DEBUG ("%s: Didn't find a valid string, giving up", __func__); return(NULL); } @@ -674,9 +734,7 @@ static gconstpointer big_up_stringtable_block (gconstpointer data_ptr, if (data_ptr == NULL) { /* Child block hit padding */ -#ifdef DEBUG - g_message ("%s: Child block hit 0-length block, giving up", __func__); -#endif + DEBUG ("%s: Child block hit 0-length block, giving up", __func__); return(NULL); } } @@ -687,7 +745,8 @@ static gconstpointer big_up_stringtable_block (gconstpointer data_ptr, /* Follows the data structures and turns all UTF-16 strings from the * LE found in the resource section into UTF-16BE */ -static void big_up (gconstpointer datablock, guint32 size) +static void +big_up (gconstpointer datablock, guint32 size) { gconstpointer data_ptr; gint32 data_len; /* signed to guard against underflow */ @@ -720,18 +779,14 @@ static void big_up (gconstpointer datablock, guint32 size) */ while (data_len > 0) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, &block); if (block.data_len == 0) { /* We must have hit padding, so give * up processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", - __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); return; } @@ -747,17 +802,13 @@ static void big_up (gconstpointer datablock, guint32 size) &block); } else { /* Bogus data */ -#ifdef DEBUG - g_message ("%s: Not a valid VERSIONINFO child block", __func__); -#endif + DEBUG ("%s: Not a valid VERSIONINFO child block", __func__); return; } if (data_ptr == NULL) { /* Child block hit padding */ -#ifdef DEBUG - g_message ("%s: Child block hit 0-length block, giving up", __func__); -#endif + DEBUG ("%s: Child block hit 0-length block, giving up", __func__); return; } } @@ -765,8 +816,8 @@ static void big_up (gconstpointer datablock, guint32 size) } #endif -gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, - gpointer *buffer, guint32 *len) +gboolean +VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, gpointer *buffer, guint32 *len) { gchar *subblock_utf8, *lang_utf8 = NULL; gboolean ret = FALSE; @@ -779,6 +830,7 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, const gunichar2 *string_key = NULL; gpointer string_value = NULL; guint32 string_value_len = 0; + gchar *lowercase_lang; subblock_utf8 = g_utf16_to_utf8 (subblock, -1, NULL, NULL, NULL); if (subblock_utf8 == NULL) { @@ -791,7 +843,10 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, want_string = TRUE; memcpy (lang, subblock + 16, 8 * sizeof(gunichar2)); lang_utf8 = g_utf16_to_utf8 (lang, 8, NULL, NULL, NULL); - g_strdown (lang_utf8); + lowercase_lang = g_utf8_strdown (lang_utf8, -1); + g_free (lang_utf8); + lang_utf8 = lowercase_lang; + lowercase_lang = NULL; string_key = subblock + 25; } @@ -817,8 +872,7 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, */ while (data_len > 0) { /* align on a 32-bit boundary */ - data_ptr = (gpointer)((char *)data_ptr + 3); - data_ptr = (gpointer)((char *)data_ptr - (GPOINTER_TO_INT (data_ptr) & 3)); + ALIGN32 (data_ptr); data_ptr = get_versioninfo_block (data_ptr, &block); @@ -826,9 +880,7 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, /* We must have hit padding, * so give up processing now */ -#ifdef DEBUG - g_message ("%s: Hit 0-length block, giving up", __func__); -#endif + DEBUG ("%s: Hit 0-length block, giving up", __func__); goto done; } @@ -857,17 +909,13 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, } } else { /* Bogus data */ -#ifdef DEBUG - g_message ("%s: Not a valid VERSIONINFO child block", __func__); -#endif + DEBUG ("%s: Not a valid VERSIONINFO child block", __func__); goto done; } if (data_ptr == NULL) { /* Child block hit padding */ -#ifdef DEBUG - g_message ("%s: Child block hit 0-length block, giving up", __func__); -#endif + DEBUG ("%s: Child block hit 0-length block, giving up", __func__); goto done; } } @@ -883,23 +931,24 @@ gboolean VerQueryValue (gconstpointer datablock, const gunichar2 *subblock, return(ret); } -guint32 GetFileVersionInfoSize (gunichar2 *filename, guint32 *handle) +guint32 +GetFileVersionInfoSize (gunichar2 *filename, guint32 *handle) { gpointer file_map; gpointer versioninfo; - guint32 map_size; + void *map_handle; + gint32 map_size; guint32 size; - + /* This value is unused, but set to zero */ *handle = 0; - file_map = map_pe_file (filename, &map_size); + file_map = map_pe_file (filename, &map_size, &map_handle); if (file_map == NULL) { return(0); } - versioninfo = find_pe_file_resources (file_map, map_size, RT_VERSION, - 0, &size); + versioninfo = find_pe_file_resources (file_map, map_size, RT_VERSION, 0, &size); if (versioninfo == NULL) { /* Didn't find the resource, so set the return value * to 0 @@ -907,21 +956,22 @@ guint32 GetFileVersionInfoSize (gunichar2 *filename, guint32 *handle) size = 0; } - unmap_pe_file (file_map, map_size); + unmap_pe_file (file_map, map_handle); return(size); } -gboolean GetFileVersionInfo (gunichar2 *filename, guint32 handle G_GNUC_UNUSED, - guint32 len, gpointer data) +gboolean +GetFileVersionInfo (gunichar2 *filename, guint32 handle G_GNUC_UNUSED, guint32 len, gpointer data) { gpointer file_map; gpointer versioninfo; - guint32 map_size; + void *map_handle; + gint32 map_size; guint32 size; gboolean ret = FALSE; - file_map = map_pe_file (filename, &map_size); + file_map = map_pe_file (filename, &map_size, &map_handle); if (file_map == NULL) { return(FALSE); } @@ -942,13 +992,13 @@ gboolean GetFileVersionInfo (gunichar2 *filename, guint32 handle G_GNUC_UNUSED, #endif } - unmap_pe_file (file_map, map_size); + unmap_pe_file (file_map, map_handle); return(ret); } -static guint32 copy_lang (gunichar2 *lang_out, guint32 lang_len, - const gchar *text) +static guint32 +copy_lang (gunichar2 *lang_out, guint32 lang_len, const gchar *text) { gunichar2 *unitext; int chars = strlen (text); @@ -972,18 +1022,20 @@ static guint32 copy_lang (gunichar2 *lang_out, guint32 lang_len, return(ret); } -guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) +guint32 +VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) { int primary, secondary; - + const char *name = NULL; + primary = lang & 0x3FF; secondary = (lang >> 10) & 0x3F; - + switch(primary) { case 0x00: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Process Default Language")); + name = "Process Default Language"; break; } break; @@ -991,72 +1043,72 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Arabic (Saudi Arabia)")); + name = "Arabic (Saudi Arabia)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Arabic (Iraq)")); + name = "Arabic (Iraq)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Arabic (Egypt)")); + name = "Arabic (Egypt)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "Arabic (Libya)")); + name = "Arabic (Libya)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "Arabic (Algeria)")); + name = "Arabic (Algeria)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "Arabic (Morocco)")); + name = "Arabic (Morocco)"; break; case 0x07: - return(copy_lang (lang_out, lang_len, "Arabic (Tunisia)")); + name = "Arabic (Tunisia)"; break; case 0x08: - return(copy_lang (lang_out, lang_len, "Arabic (Oman)")); + name = "Arabic (Oman)"; break; case 0x09: - return(copy_lang (lang_out, lang_len, "Arabic (Yemen)")); + name = "Arabic (Yemen)"; break; case 0x0a: - return(copy_lang (lang_out, lang_len, "Arabic (Syria)")); + name = "Arabic (Syria)"; break; case 0x0b: - return(copy_lang (lang_out, lang_len, "Arabic (Jordan)")); + name = "Arabic (Jordan)"; break; case 0x0c: - return(copy_lang (lang_out, lang_len, "Arabic (Lebanon)")); + name = "Arabic (Lebanon)"; break; case 0x0d: - return(copy_lang (lang_out, lang_len, "Arabic (Kuwait)")); + name = "Arabic (Kuwait)"; break; case 0x0e: - return(copy_lang (lang_out, lang_len, "Arabic (U.A.E.)")); + name = "Arabic (U.A.E.)"; break; case 0x0f: - return(copy_lang (lang_out, lang_len, "Arabic (Bahrain)")); + name = "Arabic (Bahrain)"; break; case 0x10: - return(copy_lang (lang_out, lang_len, "Arabic (Qatar)")); + name = "Arabic (Qatar)"; break; } break; case 0x02: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Bulgarian (Bulgaria)")); + name = "Bulgarian (Bulgaria)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Bulgarian")); + name = "Bulgarian"; break; } break; case 0x03: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Catalan (Spain)")); + name = "Catalan (Spain)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Catalan")); + name = "Catalan"; break; } break; @@ -1064,39 +1116,39 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Chinese (Taiwan)")); + name = "Chinese (Taiwan)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Chinese (PRC)")); + name = "Chinese (PRC)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Chinese (Hong Kong S.A.R.)")); + name = "Chinese (Hong Kong S.A.R.)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "Chinese (Singapore)")); + name = "Chinese (Singapore)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "Chinese (Macau S.A.R.)")); + name = "Chinese (Macau S.A.R.)"; break; } break; case 0x05: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Czech (Czech Republic)")); + name = "Czech (Czech Republic)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Czech")); + name = "Czech"; break; } break; case 0x06: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Danish (Denmark)")); + name = "Danish (Denmark)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Danish")); + name = "Danish"; break; } break; @@ -1104,29 +1156,29 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "German (Germany)")); + name = "German (Germany)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "German (Switzerland)")); + name = "German (Switzerland)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "German (Austria)")); + name = "German (Austria)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "German (Luxembourg)")); + name = "German (Luxembourg)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "German (Liechtenstein)")); + name = "German (Liechtenstein)"; break; } break; case 0x08: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Greek (Greece)")); + name = "Greek (Greece)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Greek")); + name = "Greek"; break; } break; @@ -1134,132 +1186,132 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "English (United States)")); + name = "English (United States)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "English (United Kingdom)")); + name = "English (United Kingdom)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "English (Australia)")); + name = "English (Australia)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "English (Canada)")); + name = "English (Canada)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "English (New Zealand)")); + name = "English (New Zealand)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "English (Ireland)")); + name = "English (Ireland)"; break; case 0x07: - return(copy_lang (lang_out, lang_len, "English (South Africa)")); + name = "English (South Africa)"; break; case 0x08: - return(copy_lang (lang_out, lang_len, "English (Jamaica)")); + name = "English (Jamaica)"; break; case 0x09: - return(copy_lang (lang_out, lang_len, "English (Caribbean)")); + name = "English (Caribbean)"; break; case 0x0a: - return(copy_lang (lang_out, lang_len, "English (Belize)")); + name = "English (Belize)"; break; case 0x0b: - return(copy_lang (lang_out, lang_len, "English (Trinidad and Tobago)")); + name = "English (Trinidad and Tobago)"; break; case 0x0c: - return(copy_lang (lang_out, lang_len, "English (Zimbabwe)")); + name = "English (Zimbabwe)"; break; case 0x0d: - return(copy_lang (lang_out, lang_len, "English (Philippines)")); + name = "English (Philippines)"; break; case 0x10: - return(copy_lang (lang_out, lang_len, "English (India)")); + name = "English (India)"; break; case 0x11: - return(copy_lang (lang_out, lang_len, "English (Malaysia)")); + name = "English (Malaysia)"; break; case 0x12: - return(copy_lang (lang_out, lang_len, "English (Singapore)")); + name = "English (Singapore)"; break; } break; case 0x0a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Spanish (Spain)")); + name = "Spanish (Spain)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Spanish (Traditional Sort)")); + name = "Spanish (Traditional Sort)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Spanish (Mexico)")); + name = "Spanish (Mexico)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Spanish (International Sort)")); + name = "Spanish (International Sort)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "Spanish (Guatemala)")); + name = "Spanish (Guatemala)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "Spanish (Costa Rica)")); + name = "Spanish (Costa Rica)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "Spanish (Panama)")); + name = "Spanish (Panama)"; break; case 0x07: - return(copy_lang (lang_out, lang_len, "Spanish (Dominican Republic)")); + name = "Spanish (Dominican Republic)"; break; case 0x08: - return(copy_lang (lang_out, lang_len, "Spanish (Venezuela)")); + name = "Spanish (Venezuela)"; break; case 0x09: - return(copy_lang (lang_out, lang_len, "Spanish (Colombia)")); + name = "Spanish (Colombia)"; break; case 0x0a: - return(copy_lang (lang_out, lang_len, "Spanish (Peru)")); + name = "Spanish (Peru)"; break; case 0x0b: - return(copy_lang (lang_out, lang_len, "Spanish (Argentina)")); + name = "Spanish (Argentina)"; break; case 0x0c: - return(copy_lang (lang_out, lang_len, "Spanish (Ecuador)")); + name = "Spanish (Ecuador)"; break; case 0x0d: - return(copy_lang (lang_out, lang_len, "Spanish (Chile)")); + name = "Spanish (Chile)"; break; case 0x0e: - return(copy_lang (lang_out, lang_len, "Spanish (Uruguay)")); + name = "Spanish (Uruguay)"; break; case 0x0f: - return(copy_lang (lang_out, lang_len, "Spanish (Paraguay)")); + name = "Spanish (Paraguay)"; break; case 0x10: - return(copy_lang (lang_out, lang_len, "Spanish (Bolivia)")); + name = "Spanish (Bolivia)"; break; case 0x11: - return(copy_lang (lang_out, lang_len, "Spanish (El Salvador)")); + name = "Spanish (El Salvador)"; break; case 0x12: - return(copy_lang (lang_out, lang_len, "Spanish (Honduras)")); + name = "Spanish (Honduras)"; break; case 0x13: - return(copy_lang (lang_out, lang_len, "Spanish (Nicaragua)")); + name = "Spanish (Nicaragua)"; break; case 0x14: - return(copy_lang (lang_out, lang_len, "Spanish (Puerto Rico)")); + name = "Spanish (Puerto Rico)"; break; case 0x15: - return(copy_lang (lang_out, lang_len, "Spanish (United States)")); + name = "Spanish (United States)"; break; } break; case 0x0b: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Finnish (Finland)")); + name = "Finnish (Finland)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Finnish")); + name = "Finnish"; break; } break; @@ -1267,52 +1319,52 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "French (France)")); + name = "French (France)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "French (Belgium)")); + name = "French (Belgium)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "French (Canada)")); + name = "French (Canada)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "French (Switzerland)")); + name = "French (Switzerland)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "French (Luxembourg)")); + name = "French (Luxembourg)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "French (Monaco)")); + name = "French (Monaco)"; break; } break; case 0x0d: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Hebrew (Israel)")); + name = "Hebrew (Israel)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Hebrew")); + name = "Hebrew"; break; } break; case 0x0e: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Hungarian (Hungary)")); + name = "Hungarian (Hungary)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Hungarian")); + name = "Hungarian"; break; } break; case 0x0f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Icelandic (Iceland)")); + name = "Icelandic (Iceland)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Icelandic")); + name = "Icelandic"; break; } break; @@ -1320,30 +1372,30 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Italian (Italy)")); + name = "Italian (Italy)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Italian (Switzerland)")); + name = "Italian (Switzerland)"; break; } break; case 0x11: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Japanese (Japan)")); + name = "Japanese (Japan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Japanese")); + name = "Japanese"; break; } break; case 0x12: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Korean (Korea)")); + name = "Korean (Korea)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Korean")); + name = "Korean"; break; } break; @@ -1351,10 +1403,10 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Dutch (Netherlands)")); + name = "Dutch (Netherlands)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Dutch (Belgium)")); + name = "Dutch (Belgium)"; break; } break; @@ -1362,20 +1414,20 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Norwegian (Bokmal)")); + name = "Norwegian (Bokmal)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Norwegian (Nynorsk)")); + name = "Norwegian (Nynorsk)"; break; } break; case 0x15: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Polish (Poland)")); + name = "Polish (Poland)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Polish")); + name = "Polish"; break; } break; @@ -1383,402 +1435,402 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Portuguese (Brazil)")); + name = "Portuguese (Brazil)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Portuguese (Portugal)")); + name = "Portuguese (Portugal)"; break; } break; case 0x17: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Romansh (Switzerland)")); + name = "Romansh (Switzerland)"; break; } break; case 0x18: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Romanian (Romania)")); + name = "Romanian (Romania)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Romanian")); + name = "Romanian"; break; } break; case 0x19: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Russian (Russia)")); + name = "Russian (Russia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Russian")); + name = "Russian"; break; } break; case 0x1a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Croatian (Croatia)")); + name = "Croatian (Croatia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Croatian")); + name = "Croatian"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Serbian (Latin)")); + name = "Serbian (Latin)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Serbian (Cyrillic)")); + name = "Serbian (Cyrillic)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "Croatian (Bosnia and Herzegovina)")); + name = "Croatian (Bosnia and Herzegovina)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "Bosnian (Latin, Bosnia and Herzegovina)")); + name = "Bosnian (Latin, Bosnia and Herzegovina)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "Serbian (Latin, Bosnia and Herzegovina)")); + name = "Serbian (Latin, Bosnia and Herzegovina)"; break; case 0x07: - return(copy_lang (lang_out, lang_len, "Serbian (Cyrillic, Bosnia and Herzegovina)")); + name = "Serbian (Cyrillic, Bosnia and Herzegovina)"; break; case 0x08: - return(copy_lang (lang_out, lang_len, "Bosnian (Cyrillic, Bosnia and Herzegovina)")); + name = "Bosnian (Cyrillic, Bosnia and Herzegovina)"; break; } break; case 0x1b: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Slovak (Slovakia)")); + name = "Slovak (Slovakia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Slovak")); + name = "Slovak"; break; } break; case 0x1c: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Albanian (Albania)")); + name = "Albanian (Albania)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Albanian")); + name = "Albanian"; break; } break; case 0x1d: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Swedish (Sweden)")); + name = "Swedish (Sweden)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Swedish")); + name = "Swedish"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Swedish (Finland)")); + name = "Swedish (Finland)"; break; } break; case 0x1e: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Thai (Thailand)")); + name = "Thai (Thailand)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Thai")); + name = "Thai"; break; } break; case 0x1f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Turkish (Turkey)")); + name = "Turkish (Turkey)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Turkish")); + name = "Turkish"; break; } break; case 0x20: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Urdu (Islamic Republic of Pakistan)")); + name = "Urdu (Islamic Republic of Pakistan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Urdu")); + name = "Urdu"; break; } break; case 0x21: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Indonesian (Indonesia)")); + name = "Indonesian (Indonesia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Indonesian")); + name = "Indonesian"; break; } break; case 0x22: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Ukrainian (Ukraine)")); + name = "Ukrainian (Ukraine)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Ukrainian")); + name = "Ukrainian"; break; } break; case 0x23: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Belarusian (Belarus)")); + name = "Belarusian (Belarus)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Belarusian")); + name = "Belarusian"; break; } break; case 0x24: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Slovenian (Slovenia)")); + name = "Slovenian (Slovenia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Slovenian")); + name = "Slovenian"; break; } break; case 0x25: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Estonian (Estonia)")); + name = "Estonian (Estonia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Estonian")); + name = "Estonian"; break; } break; case 0x26: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Latvian (Latvia)")); + name = "Latvian (Latvia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Latvian")); + name = "Latvian"; break; } break; case 0x27: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Lithuanian (Lithuania)")); + name = "Lithuanian (Lithuania)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Lithuanian")); + name = "Lithuanian"; break; } break; case 0x28: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Tajik (Tajikistan)")); + name = "Tajik (Tajikistan)"; break; } break; case 0x29: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Farsi (Iran)")); + name = "Farsi (Iran)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Farsi")); + name = "Farsi"; break; } break; case 0x2a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Vietnamese (Viet Nam)")); + name = "Vietnamese (Viet Nam)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Vietnamese")); + name = "Vietnamese"; break; } break; case 0x2b: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Armenian (Armenia)")); + name = "Armenian (Armenia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Armenian")); + name = "Armenian"; break; } break; case 0x2c: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Azeri (Latin) (Azerbaijan)")); + name = "Azeri (Latin) (Azerbaijan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Azeri (Latin)")); + name = "Azeri (Latin)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Azeri (Cyrillic)")); + name = "Azeri (Cyrillic)"; break; } break; case 0x2d: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Basque (Spain)")); + name = "Basque (Spain)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Basque")); + name = "Basque"; break; } break; case 0x2e: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Upper Sorbian (Germany)")); + name = "Upper Sorbian (Germany)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Lower Sorbian (Germany)")); + name = "Lower Sorbian (Germany)"; break; } break; case 0x2f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "FYRO Macedonian (Former Yugoslav Republic of Macedonia)")); + name = "FYRO Macedonian (Former Yugoslav Republic of Macedonia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "FYRO Macedonian")); + name = "FYRO Macedonian"; break; } break; case 0x32: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Tswana (South Africa)")); + name = "Tswana (South Africa)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Tswana")); + name = "Tswana"; break; } break; case 0x34: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Xhosa (South Africa)")); + name = "Xhosa (South Africa)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Xhosa")); + name = "Xhosa"; break; } break; case 0x35: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Zulu (South Africa)")); + name = "Zulu (South Africa)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Zulu")); + name = "Zulu"; break; } break; case 0x36: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Afrikaans (South Africa)")); + name = "Afrikaans (South Africa)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Afrikaans")); + name = "Afrikaans"; break; } break; case 0x37: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Georgian (Georgia)")); + name = "Georgian (Georgia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Georgian")); + name = "Georgian"; break; } break; case 0x38: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Faroese (Faroe Islands)")); + name = "Faroese (Faroe Islands)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Faroese")); + name = "Faroese"; break; } break; case 0x39: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Hindi (India)")); + name = "Hindi (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Hindi")); + name = "Hindi"; break; } break; case 0x3a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Maltese (Malta)")); + name = "Maltese (Malta)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Maltese")); + name = "Maltese"; break; } break; case 0x3b: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Sami (Northern) (Norway)")); + name = "Sami (Northern) (Norway)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Sami, Northern (Norway)")); + name = "Sami, Northern (Norway)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Sami, Northern (Sweden)")); + name = "Sami, Northern (Sweden)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Sami, Northern (Finland)")); + name = "Sami, Northern (Finland)"; break; case 0x04: - return(copy_lang (lang_out, lang_len, "Sami, Lule (Norway)")); + name = "Sami, Lule (Norway)"; break; case 0x05: - return(copy_lang (lang_out, lang_len, "Sami, Lule (Sweden)")); + name = "Sami, Lule (Sweden)"; break; case 0x06: - return(copy_lang (lang_out, lang_len, "Sami, Southern (Norway)")); + name = "Sami, Southern (Norway)"; break; case 0x07: - return(copy_lang (lang_out, lang_len, "Sami, Southern (Sweden)")); + name = "Sami, Southern (Sweden)"; break; case 0x08: - return(copy_lang (lang_out, lang_len, "Sami, Skolt (Finland)")); + name = "Sami, Skolt (Finland)"; break; case 0x09: - return(copy_lang (lang_out, lang_len, "Sami, Inari (Finland)")); + name = "Sami, Inari (Finland)"; break; } break; case 0x3c: switch(secondary) { case 0x02: - return(copy_lang (lang_out, lang_len, "Irish (Ireland)")); + name = "Irish (Ireland)"; break; } break; @@ -1786,70 +1838,70 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Malay (Malaysia)")); + name = "Malay (Malaysia)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Malay (Brunei Darussalam)")); + name = "Malay (Brunei Darussalam)"; break; } break; case 0x3f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Kazakh (Kazakhstan)")); + name = "Kazakh (Kazakhstan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Kazakh")); + name = "Kazakh"; break; } break; case 0x40: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Kyrgyz (Kyrgyzstan)")); + name = "Kyrgyz (Kyrgyzstan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Kyrgyz (Cyrillic)")); + name = "Kyrgyz (Cyrillic)"; break; } break; case 0x41: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Swahili (Kenya)")); + name = "Swahili (Kenya)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Swahili")); + name = "Swahili"; break; } break; case 0x42: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Turkmen (Turkmenistan)")); + name = "Turkmen (Turkmenistan)"; break; } break; case 0x43: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Uzbek (Latin) (Uzbekistan)")); + name = "Uzbek (Latin) (Uzbekistan)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Uzbek (Latin)")); + name = "Uzbek (Latin)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Uzbek (Cyrillic)")); + name = "Uzbek (Cyrillic)"; break; } break; case 0x44: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Tatar (Russia)")); + name = "Tatar (Russia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Tatar")); + name = "Tatar"; break; } break; @@ -1857,57 +1909,57 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Bengali (India)")); + name = "Bengali (India)"; break; } break; case 0x46: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Punjabi (India)")); + name = "Punjabi (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Punjabi")); + name = "Punjabi"; break; } break; case 0x47: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Gujarati (India)")); + name = "Gujarati (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Gujarati")); + name = "Gujarati"; break; } break; case 0x49: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Tamil (India)")); + name = "Tamil (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Tamil")); + name = "Tamil"; break; } break; case 0x4a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Telugu (India)")); + name = "Telugu (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Telugu")); + name = "Telugu"; break; } break; case 0x4b: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Kannada (India)")); + name = "Kannada (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Kannada")); + name = "Kannada"; break; } break; @@ -1915,194 +1967,194 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Malayalam (India)")); + name = "Malayalam (India)"; break; } break; case 0x4d: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Assamese (India)")); + name = "Assamese (India)"; break; } break; case 0x4e: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Marathi (India)")); + name = "Marathi (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Marathi")); + name = "Marathi"; break; } break; case 0x4f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Sanskrit (India)")); + name = "Sanskrit (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Sanskrit")); + name = "Sanskrit"; break; } break; case 0x50: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Mongolian (Mongolia)")); + name = "Mongolian (Mongolia)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Mongolian (Cyrillic)")); + name = "Mongolian (Cyrillic)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Mongolian (PRC)")); + name = "Mongolian (PRC)"; break; } break; case 0x51: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Tibetan (PRC)")); + name = "Tibetan (PRC)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Tibetan (Bhutan)")); + name = "Tibetan (Bhutan)"; break; } break; case 0x52: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Welsh (United Kingdom)")); + name = "Welsh (United Kingdom)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Welsh")); + name = "Welsh"; break; } break; case 0x53: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Khmer (Cambodia)")); + name = "Khmer (Cambodia)"; break; } break; case 0x54: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Lao (Lao PDR)")); + name = "Lao (Lao PDR)"; break; } break; case 0x56: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Galician (Spain)")); + name = "Galician (Spain)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Galician")); + name = "Galician"; break; } break; case 0x57: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Konkani (India)")); + name = "Konkani (India)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Konkani")); + name = "Konkani"; break; } break; case 0x5a: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Syriac (Syria)")); + name = "Syriac (Syria)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Syriac")); + name = "Syriac"; break; } break; case 0x5b: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Sinhala (Sri Lanka)")); + name = "Sinhala (Sri Lanka)"; break; } break; case 0x5d: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Inuktitut (Syllabics, Canada)")); + name = "Inuktitut (Syllabics, Canada)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Inuktitut (Latin, Canada)")); + name = "Inuktitut (Latin, Canada)"; break; } break; case 0x5e: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Amharic (Ethiopia)")); + name = "Amharic (Ethiopia)"; break; } break; case 0x5f: switch(secondary) { case 0x02: - return(copy_lang (lang_out, lang_len, "Tamazight (Algeria, Latin)")); + name = "Tamazight (Algeria, Latin)"; break; } break; case 0x61: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Nepali (Nepal)")); + name = "Nepali (Nepal)"; break; } break; case 0x62: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Frisian (Netherlands)")); + name = "Frisian (Netherlands)"; break; } break; case 0x63: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Pashto (Afghanistan)")); + name = "Pashto (Afghanistan)"; break; } break; case 0x64: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Filipino (Philippines)")); + name = "Filipino (Philippines)"; break; } break; case 0x65: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Divehi (Maldives)")); + name = "Divehi (Maldives)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Divehi")); + name = "Divehi"; break; } break; case 0x68: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Hausa (Nigeria, Latin)")); + name = "Hausa (Nigeria, Latin)"; break; } break; case 0x6a: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Yoruba (Nigeria)")); + name = "Yoruba (Nigeria)"; break; } break; @@ -2110,153 +2162,156 @@ guint32 VerLanguageName (guint32 lang, gunichar2 *lang_out, guint32 lang_len) switch(secondary) { case 0x00: case 0x01: - return(copy_lang (lang_out, lang_len, "Quechua (Bolivia)")); + name = "Quechua (Bolivia)"; break; case 0x02: - return(copy_lang (lang_out, lang_len, "Quechua (Ecuador)")); + name = "Quechua (Ecuador)"; break; case 0x03: - return(copy_lang (lang_out, lang_len, "Quechua (Peru)")); + name = "Quechua (Peru)"; break; } break; case 0x6c: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Northern Sotho (South Africa)")); + name = "Northern Sotho (South Africa)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Northern Sotho")); + name = "Northern Sotho"; break; } break; case 0x6d: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Bashkir (Russia)")); + name = "Bashkir (Russia)"; break; } break; case 0x6e: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Luxembourgish (Luxembourg)")); + name = "Luxembourgish (Luxembourg)"; break; } break; case 0x6f: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Greenlandic (Greenland)")); + name = "Greenlandic (Greenland)"; break; } break; case 0x78: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Yi (PRC)")); + name = "Yi (PRC)"; break; } break; case 0x7a: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Mapudungun (Chile)")); + name = "Mapudungun (Chile)"; break; } break; case 0x7c: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Mohawk (Mohawk)")); + name = "Mohawk (Mohawk)"; break; } break; case 0x7e: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Breton (France)")); + name = "Breton (France)"; break; } break; case 0x7f: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Invariant Language (Invariant Country)")); + name = "Invariant Language (Invariant Country)"; break; } break; case 0x80: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Uighur (PRC)")); + name = "Uighur (PRC)"; break; } break; case 0x81: switch(secondary) { case 0x00: - return(copy_lang (lang_out, lang_len, "Maori (New Zealand)")); + name = "Maori (New Zealand)"; break; case 0x01: - return(copy_lang (lang_out, lang_len, "Maori")); + name = "Maori"; break; } break; case 0x83: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Corsican (France)")); + name = "Corsican (France)"; break; } break; case 0x84: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Alsatian (France)")); + name = "Alsatian (France)"; break; } break; case 0x85: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Yakut (Russia)")); + name = "Yakut (Russia)"; break; } break; case 0x86: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "K'iche (Guatemala)")); + name = "K'iche (Guatemala)"; break; } break; case 0x87: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Kinyarwanda (Rwanda)")); + name = "Kinyarwanda (Rwanda)"; break; } break; case 0x88: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Wolof (Senegal)")); + name = "Wolof (Senegal)"; break; } break; case 0x8c: switch(secondary) { case 0x01: - return(copy_lang (lang_out, lang_len, "Dari (Afghanistan)")); + name = "Dari (Afghanistan)"; break; } break; default: - return(copy_lang (lang_out, lang_len, "Language Neutral")); + name = "Language Neutral"; } - return(copy_lang (lang_out, lang_len, "Language Neutral")); + if (!name) + name = "Language Neutral"; + + return copy_lang (lang_out, lang_len, name); }