X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Fxml_windows.c;h=305d2efa5a77ae39947df91d99768dee6bb09822;hb=refs%2Fheads%2Fmaster;hp=a45eeaef40281d38ba2661e0cb08c7296a28fa32;hpb=542225070ab6583b6f5915172425cac6e0326d77;p=wimlib diff --git a/src/xml_windows.c b/src/xml_windows.c index a45eeaef..305d2efa 100644 --- a/src/xml_windows.c +++ b/src/xml_windows.c @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2016 Eric Biggers + * Copyright 2016-2023 Eric Biggers * * This file is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free @@ -19,7 +19,7 @@ * details. * * You should have received a copy of the GNU Lesser General Public License - * along with this file; if not, see http://www.gnu.org/licenses/. + * along with this file; if not, see https://www.gnu.org/licenses/. */ #ifdef HAVE_CONFIG_H @@ -31,8 +31,10 @@ #include "wimlib.h" #include "wimlib/blob_table.h" #include "wimlib/dentry.h" +#include "wimlib/encoding.h" #include "wimlib/endianness.h" #include "wimlib/error.h" +#include "wimlib/metadata.h" #include "wimlib/registry.h" #include "wimlib/wim.h" #include "wimlib/xml_windows.h" @@ -53,26 +55,6 @@ struct windows_info_ctx { if (ctx->debug_enabled) \ WARNING(format, ##__VA_ARGS__) -/* Path to the SOFTWARE registry hive */ -static const tchar * const software_hive_path = - WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("config") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("SOFTWARE"); - -/* Path to the SYSTEM registry hive */ -static const tchar * const system_hive_path = - WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("config") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("SYSTEM"); - -/* Path to kernel32.dll */ -static const tchar * const kernel32_dll_path = - WIMLIB_WIM_PATH_SEPARATOR_STRING T("Windows") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("System32") - WIMLIB_WIM_PATH_SEPARATOR_STRING T("kernel32.dll"); - /* Set a property in the XML document, with error checking. */ static void set_string_property(struct windows_info_ctx *ctx, @@ -172,7 +154,7 @@ copy_registry_string(struct windows_info_ctx *ctx, const struct regf *regf, static const struct { u16 id; u16 name_start_offset; -} language_id_map[452] = { +} language_id_map[453] = { {0x0000, 0}, {0x0001, 6}, {0x0002, 12}, {0x0003, 18}, {0x0004, 24}, {0x0005, 30}, {0x0006, 36}, {0x0007, 42}, {0x0008, 48}, {0x0009, 54}, {0x000a, 60}, {0x000b, 66}, @@ -201,96 +183,97 @@ static const struct { {0x0064, 647}, {0x0065, 654}, {0x0066, 660}, {0x0067, 667}, {0x0068, 678}, {0x0069, 689}, {0x006a, 696}, {0x006b, 702}, {0x006c, 709}, {0x006d, 716}, {0x006e, 722}, {0x006f, 728}, - {0x0070, 734}, {0x0071, 740}, {0x0072, 746}, {0x0073, 752}, - {0x0074, 758}, {0x0075, 764}, {0x0076, 771}, {0x0077, 778}, - {0x0078, 784}, {0x0079, 790}, {0x007a, 798}, {0x007c, 805}, - {0x007e, 812}, {0x007f, 818}, {0x0080, 819}, {0x0081, 825}, - {0x0082, 831}, {0x0083, 837}, {0x0084, 843}, {0x0085, 850}, - {0x0086, 857}, {0x0087, 869}, {0x0088, 875}, {0x008c, 881}, - {0x0091, 888}, {0x0092, 894}, {0x0400, 905}, {0x0401, 911}, - {0x0402, 917}, {0x0403, 923}, {0x0404, 929}, {0x0405, 935}, - {0x0406, 941}, {0x0407, 947}, {0x0408, 953}, {0x0409, 959}, - {0x040a, 965}, {0x040b, 978}, {0x040c, 984}, {0x040d, 990}, - {0x040e, 996}, {0x040f, 1002}, {0x0410, 1008}, {0x0411, 1014}, - {0x0412, 1020}, {0x0413, 1026}, {0x0414, 1032}, {0x0415, 1038}, - {0x0416, 1044}, {0x0417, 1050}, {0x0418, 1056}, {0x0419, 1062}, - {0x041a, 1068}, {0x041b, 1074}, {0x041c, 1080}, {0x041d, 1086}, - {0x041e, 1092}, {0x041f, 1098}, {0x0420, 1104}, {0x0421, 1110}, - {0x0422, 1116}, {0x0423, 1122}, {0x0424, 1128}, {0x0425, 1134}, - {0x0426, 1140}, {0x0427, 1146}, {0x0428, 1152}, {0x0429, 1163}, - {0x042a, 1169}, {0x042b, 1175}, {0x042c, 1181}, {0x042d, 1192}, - {0x042e, 1198}, {0x042f, 1205}, {0x0430, 1211}, {0x0431, 1217}, - {0x0432, 1223}, {0x0433, 1229}, {0x0434, 1235}, {0x0435, 1241}, - {0x0436, 1247}, {0x0437, 1253}, {0x0438, 1259}, {0x0439, 1265}, - {0x043a, 1271}, {0x043b, 1277}, {0x043d, 1283}, {0x043e, 1290}, - {0x043f, 1296}, {0x0440, 1302}, {0x0441, 1308}, {0x0442, 1314}, - {0x0443, 1320}, {0x0444, 1331}, {0x0445, 1337}, {0x0446, 1343}, - {0x0447, 1349}, {0x0448, 1355}, {0x0449, 1361}, {0x044a, 1367}, - {0x044b, 1373}, {0x044c, 1379}, {0x044d, 1385}, {0x044e, 1391}, - {0x044f, 1397}, {0x0450, 1403}, {0x0451, 1409}, {0x0452, 1415}, - {0x0453, 1421}, {0x0454, 1427}, {0x0455, 1433}, {0x0456, 1439}, - {0x0457, 1445}, {0x0458, 1452}, {0x0459, 1459}, {0x045a, 1470}, - {0x045b, 1477}, {0x045c, 1483}, {0x045d, 1495}, {0x045e, 1506}, - {0x045f, 1512}, {0x0460, 1524}, {0x0461, 1535}, {0x0462, 1541}, - {0x0463, 1547}, {0x0464, 1553}, {0x0465, 1560}, {0x0466, 1566}, - {0x0467, 1573}, {0x0468, 1579}, {0x0469, 1590}, {0x046a, 1597}, - {0x046b, 1603}, {0x046c, 1610}, {0x046d, 1617}, {0x046e, 1623}, - {0x046f, 1629}, {0x0470, 1635}, {0x0471, 1641}, {0x0472, 1647}, - {0x0473, 1653}, {0x0474, 1659}, {0x0475, 1665}, {0x0476, 1672}, - {0x0477, 1679}, {0x0478, 1685}, {0x0479, 1691}, {0x047a, 1699}, - {0x047c, 1706}, {0x047e, 1713}, {0x0480, 1719}, {0x0481, 1725}, - {0x0482, 1731}, {0x0483, 1737}, {0x0484, 1743}, {0x0485, 1750}, - {0x0486, 1757}, {0x0487, 1769}, {0x0488, 1775}, {0x048c, 1781}, - {0x0491, 1788}, {0x0492, 1794}, {0x0501, 1805}, {0x05fe, 1814}, - {0x0800, 1824}, {0x0801, 1830}, {0x0803, 1836}, {0x0804, 1851}, - {0x0807, 1857}, {0x0809, 1863}, {0x080a, 1869}, {0x080c, 1875}, - {0x0810, 1881}, {0x0813, 1887}, {0x0814, 1893}, {0x0816, 1899}, - {0x0818, 1905}, {0x0819, 1911}, {0x081a, 1917}, {0x081d, 1928}, - {0x0820, 1934}, {0x082c, 1940}, {0x082e, 1951}, {0x0832, 1958}, - {0x083b, 1964}, {0x083c, 1970}, {0x083e, 1976}, {0x0843, 1982}, - {0x0845, 1993}, {0x0846, 1999}, {0x0849, 2010}, {0x0850, 2016}, - {0x0859, 2027}, {0x085d, 2038}, {0x085f, 2049}, {0x0860, 2061}, - {0x0861, 2072}, {0x0867, 2078}, {0x086b, 2089}, {0x0873, 2096}, - {0x0901, 2102}, {0x09ff, 2116}, {0x0c00, 2126}, {0x0c01, 2132}, - {0x0c04, 2138}, {0x0c07, 2144}, {0x0c09, 2150}, {0x0c0a, 2156}, - {0x0c0c, 2162}, {0x0c1a, 2168}, {0x0c3b, 2179}, {0x0c50, 2185}, - {0x0c51, 2196}, {0x0c6b, 2202}, {0x1000, 2209}, {0x1001, 2220}, - {0x1004, 2226}, {0x1007, 2232}, {0x1009, 2238}, {0x100a, 2244}, - {0x100c, 2250}, {0x101a, 2256}, {0x103b, 2262}, {0x105f, 2269}, - {0x1401, 2281}, {0x1404, 2287}, {0x1407, 2293}, {0x1409, 2299}, - {0x140a, 2305}, {0x140c, 2311}, {0x141a, 2317}, {0x143b, 2328}, - {0x1801, 2335}, {0x1809, 2341}, {0x180a, 2347}, {0x180c, 2353}, - {0x181a, 2359}, {0x183b, 2370}, {0x1c01, 2377}, {0x1c09, 2383}, - {0x1c0a, 2389}, {0x1c0c, 2395}, {0x1c1a, 2402}, {0x1c3b, 2413}, - {0x2000, 2420}, {0x2001, 2426}, {0x2009, 2432}, {0x200a, 2438}, - {0x200c, 2444}, {0x201a, 2450}, {0x203b, 2461}, {0x2400, 2468}, - {0x2401, 2474}, {0x2409, 2480}, {0x240a, 2487}, {0x240c, 2493}, - {0x241a, 2499}, {0x243b, 2510}, {0x2800, 2517}, {0x2801, 2523}, - {0x2809, 2529}, {0x280a, 2535}, {0x280c, 2541}, {0x281a, 2547}, - {0x2c00, 2558}, {0x2c01, 2564}, {0x2c09, 2570}, {0x2c0a, 2576}, - {0x2c0c, 2582}, {0x2c1a, 2588}, {0x3000, 2599}, {0x3001, 2605}, - {0x3009, 2611}, {0x300a, 2617}, {0x300c, 2623}, {0x301a, 2629}, - {0x3400, 2640}, {0x3401, 2646}, {0x3409, 2652}, {0x340a, 2658}, - {0x340c, 2664}, {0x3800, 2670}, {0x3801, 2676}, {0x3809, 2682}, - {0x380a, 2688}, {0x380c, 2694}, {0x3c00, 2700}, {0x3c01, 2706}, - {0x3c09, 2712}, {0x3c0a, 2718}, {0x3c0c, 2724}, {0x4000, 2730}, - {0x4001, 2736}, {0x4009, 2742}, {0x400a, 2748}, {0x4400, 2754}, - {0x4409, 2760}, {0x440a, 2766}, {0x4800, 2772}, {0x4809, 2778}, - {0x480a, 2784}, {0x4c00, 2790}, {0x4c0a, 2796}, {0x500a, 2802}, - {0x540a, 2808}, {0x580a, 2814}, {0x5c0a, 2821}, {0x641a, 2827}, - {0x681a, 2838}, {0x6c1a, 2849}, {0x701a, 2860}, {0x703b, 2871}, - {0x742c, 2878}, {0x743b, 2889}, {0x7804, 2896}, {0x7814, 2902}, - {0x781a, 2908}, {0x782c, 2919}, {0x783b, 2930}, {0x7843, 2937}, - {0x7850, 2948}, {0x785d, 2954}, {0x785f, 2965}, {0x7c04, 2977}, - {0x7c14, 2983}, {0x7c1a, 2989}, {0x7c28, 3000}, {0x7c2e, 3011}, - {0x7c3b, 3018}, {0x7c43, 3025}, {0x7c46, 3036}, {0x7c50, 3047}, - {0x7c59, 3058}, {0x7c5c, 3069}, {0x7c5d, 3081}, {0x7c5f, 3092}, - {0x7c67, 3104}, {0x7c68, 3115}, {0x7c86, 3126}, {0x7c92, 3138}, + {0x0070, 734}, {0x0071, 740}, {0x0072, 751}, {0x0073, 757}, + {0x0074, 763}, {0x0075, 769}, {0x0076, 776}, {0x0077, 783}, + {0x0078, 789}, {0x0079, 795}, {0x007a, 803}, {0x007c, 810}, + {0x007e, 817}, {0x007f, 823}, {0x0080, 824}, {0x0081, 830}, + {0x0082, 836}, {0x0083, 842}, {0x0084, 848}, {0x0085, 855}, + {0x0086, 862}, {0x0087, 874}, {0x0088, 880}, {0x008c, 886}, + {0x0091, 893}, {0x0092, 899}, {0x0400, 910}, {0x0401, 916}, + {0x0402, 922}, {0x0403, 928}, {0x0404, 934}, {0x0405, 940}, + {0x0406, 946}, {0x0407, 952}, {0x0408, 958}, {0x0409, 964}, + {0x040a, 970}, {0x040b, 983}, {0x040c, 989}, {0x040d, 995}, + {0x040e, 1001}, {0x040f, 1007}, {0x0410, 1013}, {0x0411, 1019}, + {0x0412, 1025}, {0x0413, 1031}, {0x0414, 1037}, {0x0415, 1043}, + {0x0416, 1049}, {0x0417, 1055}, {0x0418, 1061}, {0x0419, 1067}, + {0x041a, 1073}, {0x041b, 1079}, {0x041c, 1085}, {0x041d, 1091}, + {0x041e, 1097}, {0x041f, 1103}, {0x0420, 1109}, {0x0421, 1115}, + {0x0422, 1121}, {0x0423, 1127}, {0x0424, 1133}, {0x0425, 1139}, + {0x0426, 1145}, {0x0427, 1151}, {0x0428, 1157}, {0x0429, 1168}, + {0x042a, 1174}, {0x042b, 1180}, {0x042c, 1186}, {0x042d, 1197}, + {0x042e, 1203}, {0x042f, 1210}, {0x0430, 1216}, {0x0431, 1222}, + {0x0432, 1228}, {0x0433, 1234}, {0x0434, 1240}, {0x0435, 1246}, + {0x0436, 1252}, {0x0437, 1258}, {0x0438, 1264}, {0x0439, 1270}, + {0x043a, 1276}, {0x043b, 1282}, {0x043d, 1288}, {0x043e, 1295}, + {0x043f, 1301}, {0x0440, 1307}, {0x0441, 1313}, {0x0442, 1319}, + {0x0443, 1325}, {0x0444, 1336}, {0x0445, 1342}, {0x0446, 1348}, + {0x0447, 1354}, {0x0448, 1360}, {0x0449, 1366}, {0x044a, 1372}, + {0x044b, 1378}, {0x044c, 1384}, {0x044d, 1390}, {0x044e, 1396}, + {0x044f, 1402}, {0x0450, 1408}, {0x0451, 1414}, {0x0452, 1420}, + {0x0453, 1426}, {0x0454, 1432}, {0x0455, 1438}, {0x0456, 1444}, + {0x0457, 1450}, {0x0458, 1457}, {0x0459, 1464}, {0x045a, 1475}, + {0x045b, 1482}, {0x045c, 1488}, {0x045d, 1500}, {0x045e, 1511}, + {0x045f, 1517}, {0x0460, 1529}, {0x0461, 1540}, {0x0462, 1546}, + {0x0463, 1552}, {0x0464, 1558}, {0x0465, 1565}, {0x0466, 1571}, + {0x0467, 1578}, {0x0468, 1589}, {0x0469, 1600}, {0x046a, 1607}, + {0x046b, 1613}, {0x046c, 1620}, {0x046d, 1627}, {0x046e, 1633}, + {0x046f, 1639}, {0x0470, 1645}, {0x0471, 1651}, {0x0472, 1662}, + {0x0473, 1668}, {0x0474, 1674}, {0x0475, 1680}, {0x0476, 1687}, + {0x0477, 1694}, {0x0478, 1700}, {0x0479, 1706}, {0x047a, 1714}, + {0x047c, 1721}, {0x047e, 1728}, {0x0480, 1734}, {0x0481, 1740}, + {0x0482, 1746}, {0x0483, 1752}, {0x0484, 1758}, {0x0485, 1765}, + {0x0486, 1772}, {0x0487, 1784}, {0x0488, 1790}, {0x048c, 1796}, + {0x0491, 1803}, {0x0492, 1809}, {0x0501, 1820}, {0x05fe, 1829}, + {0x0800, 1839}, {0x0801, 1845}, {0x0803, 1851}, {0x0804, 1866}, + {0x0807, 1872}, {0x0809, 1878}, {0x080a, 1884}, {0x080c, 1890}, + {0x0810, 1896}, {0x0813, 1902}, {0x0814, 1908}, {0x0816, 1914}, + {0x0818, 1920}, {0x0819, 1926}, {0x081a, 1932}, {0x081d, 1943}, + {0x0820, 1949}, {0x082c, 1955}, {0x082e, 1966}, {0x0832, 1973}, + {0x083b, 1979}, {0x083c, 1985}, {0x083e, 1991}, {0x0843, 1997}, + {0x0845, 2008}, {0x0846, 2014}, {0x0849, 2025}, {0x0850, 2031}, + {0x0859, 2042}, {0x085d, 2053}, {0x085f, 2064}, {0x0860, 2076}, + {0x0861, 2087}, {0x0867, 2093}, {0x086b, 2104}, {0x0873, 2111}, + {0x0901, 2117}, {0x09ff, 2131}, {0x0c00, 2141}, {0x0c01, 2147}, + {0x0c04, 2153}, {0x0c07, 2159}, {0x0c09, 2165}, {0x0c0a, 2171}, + {0x0c0c, 2177}, {0x0c1a, 2183}, {0x0c3b, 2194}, {0x0c50, 2200}, + {0x0c51, 2211}, {0x0c6b, 2217}, {0x1000, 2224}, {0x1001, 2235}, + {0x1004, 2241}, {0x1007, 2247}, {0x1009, 2253}, {0x100a, 2259}, + {0x100c, 2265}, {0x101a, 2271}, {0x103b, 2277}, {0x105f, 2284}, + {0x1401, 2296}, {0x1404, 2302}, {0x1407, 2308}, {0x1409, 2314}, + {0x140a, 2320}, {0x140c, 2326}, {0x141a, 2332}, {0x143b, 2343}, + {0x1801, 2350}, {0x1809, 2356}, {0x180a, 2362}, {0x180c, 2368}, + {0x181a, 2374}, {0x183b, 2385}, {0x1c01, 2392}, {0x1c09, 2398}, + {0x1c0a, 2404}, {0x1c0c, 2410}, {0x1c1a, 2417}, {0x1c3b, 2428}, + {0x2000, 2435}, {0x2001, 2441}, {0x2009, 2447}, {0x200a, 2453}, + {0x200c, 2459}, {0x201a, 2465}, {0x203b, 2476}, {0x2400, 2483}, + {0x2401, 2489}, {0x2409, 2495}, {0x240a, 2502}, {0x240c, 2508}, + {0x241a, 2514}, {0x243b, 2525}, {0x2800, 2532}, {0x2801, 2538}, + {0x2809, 2544}, {0x280a, 2550}, {0x280c, 2556}, {0x281a, 2562}, + {0x2c00, 2573}, {0x2c01, 2579}, {0x2c09, 2585}, {0x2c0a, 2591}, + {0x2c0c, 2597}, {0x2c1a, 2603}, {0x3000, 2614}, {0x3001, 2620}, + {0x3009, 2626}, {0x300a, 2632}, {0x300c, 2638}, {0x301a, 2644}, + {0x3400, 2655}, {0x3401, 2661}, {0x3409, 2667}, {0x340a, 2673}, + {0x340c, 2679}, {0x3800, 2685}, {0x3801, 2691}, {0x3809, 2697}, + {0x380a, 2703}, {0x380c, 2709}, {0x3c00, 2715}, {0x3c01, 2721}, + {0x3c09, 2727}, {0x3c0a, 2733}, {0x3c0c, 2739}, {0x4000, 2745}, + {0x4001, 2751}, {0x4009, 2757}, {0x400a, 2763}, {0x4400, 2769}, + {0x4409, 2775}, {0x440a, 2781}, {0x4800, 2787}, {0x4809, 2793}, + {0x480a, 2799}, {0x4c00, 2805}, {0x4c09, 2811}, {0x4c0a, 2817}, + {0x500a, 2823}, {0x540a, 2829}, {0x580a, 2835}, {0x5c0a, 2842}, + {0x641a, 2848}, {0x681a, 2859}, {0x6c1a, 2870}, {0x701a, 2881}, + {0x703b, 2892}, {0x742c, 2899}, {0x743b, 2910}, {0x7804, 2917}, + {0x7814, 2923}, {0x781a, 2929}, {0x782c, 2940}, {0x783b, 2951}, + {0x7843, 2958}, {0x7850, 2969}, {0x785d, 2975}, {0x785f, 2986}, + {0x7c04, 2998}, {0x7c14, 3004}, {0x7c1a, 3010}, {0x7c28, 3021}, + {0x7c2e, 3032}, {0x7c3b, 3039}, {0x7c43, 3046}, {0x7c46, 3057}, + {0x7c50, 3068}, {0x7c59, 3079}, {0x7c5c, 3090}, {0x7c5d, 3102}, + {0x7c5f, 3113}, {0x7c67, 3125}, {0x7c68, 3136}, {0x7c86, 3147}, + {0x7c92, 3159}, }; /* All the language names; generated by tools/generate_language_id_map.c. * For compactness, this is a 'char' string rather than a 'tchar' string. */ -static const char language_names[3149] = +static const char language_names[3170] = "en-US\0ar-SA\0bg-BG\0ca-ES\0zh-CN\0cs-CZ\0da-DK\0de-DE\0el-GR\0en-US\0" "es-ES\0fi-FI\0fr-FR\0he-IL\0hu-HU\0is-IS\0it-IT\0ja-JP\0ko-KR\0nl-NL\0" "nb-NO\0pl-PL\0pt-BR\0rm-CH\0ro-RO\0ru-RU\0hr-HR\0sk-SK\0sq-AL\0sv-SE\0" @@ -298,14 +281,14 @@ static const char language_names[3149] = "tg-Cyrl-TJ\0fa-IR\0vi-VN\0hy-AM\0az-Latn-AZ\0eu-ES\0hsb-DE\0mk-MK\0" "st-ZA\0ts-ZA\0tn-ZA\0ve-ZA\0xh-ZA\0zu-ZA\0af-ZA\0ka-GE\0fo-FO\0hi-IN\0" "mt-MT\0se-NO\0ga-IE\0yi-001\0ms-MY\0kk-KZ\0ky-KG\0sw-KE\0tk-TM\0" - "uz-Latn-UZ\0tt-RU\0bn-IN\0pa-IN\0gu-IN\0or-IN\0ta-IN\0te-IN\0kn-IN\0" + "uz-Latn-UZ\0tt-RU\0bn-BD\0pa-IN\0gu-IN\0or-IN\0ta-IN\0te-IN\0kn-IN\0" "ml-IN\0as-IN\0mr-IN\0sa-IN\0mn-MN\0bo-CN\0cy-GB\0km-KH\0lo-LA\0my-MM\0" "gl-ES\0kok-IN\0mni-IN\0sd-Arab-PK\0syr-SY\0si-LK\0chr-Cher-US\0" "iu-Latn-CA\0am-ET\0tzm-Latn-DZ\0ks-Arab-IN\0ne-NP\0fy-NL\0ps-AF\0" "fil-PH\0dv-MV\0bin-NG\0ff-Latn-SN\0ha-Latn-NG\0ibb-NG\0yo-NG\0quz-BO\0" - "nso-ZA\0ba-RU\0lb-LU\0kl-GL\0ig-NG\0kr-NG\0om-ET\0ti-ER\0gn-PY\0" + "nso-ZA\0ba-RU\0lb-LU\0kl-GL\0ig-NG\0kr-Latn-NG\0om-ET\0ti-ER\0gn-PY\0" "haw-US\0la-001\0so-SO\0ii-CN\0pap-029\0arn-CL\0moh-CA\0br-FR\0\0" - "ug-CN\0mi-NZ\0oc-FR\0co-FR\0gsw-FR\0sah-RU\0quc-Latn-GT\0rw-RW\0" + "ug-CN\0mi-NZ\0oc-FR\0co-FR\0gsw-CH\0sah-RU\0quc-Latn-GT\0rw-RW\0" "wo-SN\0prs-AF\0gd-GB\0ku-Arab-IQ\0en-US\0ar-SA\0bg-BG\0ca-ES\0zh-TW\0" "cs-CZ\0da-DK\0de-DE\0el-GR\0en-US\0es-ES_tradnl\0fi-FI\0fr-FR\0he-IL\0" "hu-HU\0is-IS\0it-IT\0ja-JP\0ko-KR\0nl-NL\0nb-NO\0pl-PL\0pt-BR\0rm-CH\0" @@ -317,9 +300,9 @@ static const char language_names[3149] = "gu-IN\0or-IN\0ta-IN\0te-IN\0kn-IN\0ml-IN\0as-IN\0mr-IN\0sa-IN\0mn-MN\0" "bo-CN\0cy-GB\0km-KH\0lo-LA\0my-MM\0gl-ES\0kok-IN\0mni-IN\0sd-Deva-IN\0" "syr-SY\0si-LK\0chr-Cher-US\0iu-Cans-CA\0am-ET\0tzm-Arab-MA\0" - "ks-Arab-IN\0ne-NP\0fy-NL\0ps-AF\0fil-PH\0dv-MV\0bin-NG\0ff-NG\0" + "ks-Arab-IN\0ne-NP\0fy-NL\0ps-AF\0fil-PH\0dv-MV\0bin-NG\0ff-Latn-NG\0" "ha-Latn-NG\0ibb-NG\0yo-NG\0quz-BO\0nso-ZA\0ba-RU\0lb-LU\0kl-GL\0" - "ig-NG\0kr-NG\0om-ET\0ti-ET\0gn-PY\0haw-US\0la-001\0so-SO\0ii-CN\0" + "ig-NG\0kr-Latn-NG\0om-ET\0ti-ET\0gn-PY\0haw-US\0la-001\0so-SO\0ii-CN\0" "pap-029\0arn-CL\0moh-CA\0br-FR\0ug-CN\0mi-NZ\0oc-FR\0co-FR\0gsw-FR\0" "sah-RU\0quc-Latn-GT\0rw-RW\0wo-SN\0prs-AF\0gd-GB\0ku-Arab-IQ\0" "qps-ploc\0qps-ploca\0en-US\0ar-IQ\0ca-ES-valencia\0zh-CN\0de-CH\0" @@ -338,13 +321,13 @@ static const char language_names[3149] = "en-TT\0es-AR\0fr-CM\0sr-Latn-ME\0en-US\0ar-LB\0en-ZW\0es-EC\0fr-CI\0" "sr-Cyrl-ME\0en-US\0ar-KW\0en-PH\0es-CL\0fr-ML\0en-US\0ar-AE\0en-ID\0" "es-UY\0fr-MA\0en-US\0ar-BH\0en-HK\0es-PY\0fr-HT\0en-US\0ar-QA\0en-IN\0" - "es-BO\0en-US\0en-MY\0es-SV\0en-US\0en-SG\0es-HN\0en-US\0es-NI\0es-PR\0" - "es-US\0es-419\0es-CU\0bs-Cyrl-BA\0bs-Latn-BA\0sr-Cyrl-RS\0sr-Latn-RS\0" - "smn-FI\0az-Cyrl-AZ\0sms-FI\0zh-CN\0nn-NO\0bs-Latn-BA\0az-Latn-AZ\0" - "sma-SE\0uz-Cyrl-UZ\0mn-MN\0iu-Cans-CA\0tzm-Tfng-MA\0zh-HK\0nb-NO\0" - "sr-Latn-RS\0tg-Cyrl-TJ\0dsb-DE\0smj-SE\0uz-Latn-UZ\0pa-Arab-PK\0" - "mn-Mong-CN\0sd-Arab-PK\0chr-Cher-US\0iu-Latn-CA\0tzm-Latn-DZ\0" - "ff-Latn-SN\0ha-Latn-NG\0quc-Latn-GT\0ku-Arab-IQ\0"; + "es-BO\0en-US\0en-MY\0es-SV\0en-US\0en-SG\0es-HN\0en-US\0en-AE\0es-NI\0" + "es-PR\0es-US\0es-419\0es-CU\0bs-Cyrl-BA\0bs-Latn-BA\0sr-Cyrl-RS\0" + "sr-Latn-RS\0smn-FI\0az-Cyrl-AZ\0sms-FI\0zh-CN\0nn-NO\0bs-Latn-BA\0" + "az-Latn-AZ\0sma-SE\0uz-Cyrl-UZ\0mn-MN\0iu-Cans-CA\0tzm-Tfng-MA\0" + "zh-HK\0nb-NO\0sr-Latn-RS\0tg-Cyrl-TJ\0dsb-DE\0smj-SE\0uz-Latn-UZ\0" + "pa-Arab-PK\0mn-Mong-CN\0sd-Arab-PK\0chr-Cher-US\0iu-Latn-CA\0" + "tzm-Latn-DZ\0ff-Latn-SN\0ha-Latn-NG\0quc-Latn-GT\0ku-Arab-IQ\0"; /* Translate a Windows language ID to its name. Returns NULL if the ID is not * recognized. */ @@ -372,12 +355,14 @@ language_id_to_name(u16 id) #define IMAGE_FILE_MACHINE_THUMB 0x01C2 #define IMAGE_FILE_MACHINE_IA64 0x0200 #define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 /* Windows API processor architecture codes (common ones only) */ #define PROCESSOR_ARCHITECTURE_INTEL 0 #define PROCESSOR_ARCHITECTURE_ARM 5 #define PROCESSOR_ARCHITECTURE_IA64 6 #define PROCESSOR_ARCHITECTURE_AMD64 9 +#define PROCESSOR_ARCHITECTURE_ARM64 12 /* Translate a processor architecture code as given in a PE binary to the code * used by the Windows API. Returns -1 if the code is not recognized. */ @@ -395,6 +380,8 @@ pe_arch_to_windows_arch(unsigned pe_arch) return PROCESSOR_ARCHITECTURE_IA64; case IMAGE_FILE_MACHINE_AMD64: return PROCESSOR_ARCHITECTURE_AMD64; + case IMAGE_FILE_MACHINE_ARM64: + return PROCESSOR_ARCHITECTURE_ARM64; } return -1; } @@ -419,7 +406,7 @@ set_info_from_kernel32(struct windows_info_ctx *ctx, goto invalid; pe_hdr = (u8 *)contents + e_lfanew; - if (*(u32 *)pe_hdr != cpu_to_le32(0x00004550)) /* "PE\0\0" */ + if (*(le32 *)pe_hdr != cpu_to_le32(0x00004550)) /* "PE\0\0" */ goto invalid; pe_arch = le16_to_cpu(*(le16 *)(pe_hdr + 4)); @@ -446,6 +433,7 @@ set_info_from_software_hive(struct windows_info_ctx *ctx, s64 major_version = -1; s64 minor_version = -1; tchar *version_string; + tchar *build_string; /* Image flags */ copy_registry_string(ctx, regf, version_key, T("EditionID"), @@ -508,8 +496,28 @@ set_info_from_software_hive(struct windows_info_ctx *ctx, } /* Build number */ - copy_registry_string(ctx, regf, version_key, T("CurrentBuild"), - T("WINDOWS/VERSION/BUILD")); + + /* Note: "CurrentBuild" is marked as obsolete in Windows XP registries + * (example value: "1.511.1 () (Obsolete data - do not use)"), and + * "CurrentBuildNumber" contains the correct value. But oddly enough, + * it is "CurrentBuild" that contains the correct value on *later* + * versions of Windows. */ + if (get_string_from_registry(ctx, regf, version_key, T("CurrentBuild"), + &build_string)) + { + if (tstrchr(build_string, T('.'))) { + FREE(build_string); + build_string = NULL; + get_string_from_registry(ctx, regf, version_key, + T("CurrentBuildNumber"), + &build_string); + } + if (build_string) { + set_string_property(ctx, T("WINDOWS/VERSION/BUILD"), + build_string); + FREE(build_string); + } + } } /* Gather the default language from the SYSTEM registry hive. */ @@ -595,30 +603,29 @@ set_info_from_system_hive(struct windows_info_ctx *ctx, const struct regf *regf) */ static void * load_file_contents(struct windows_info_ctx *ctx, - const tchar *path, size_t *size_ret) + const struct wim_dentry *dentry, const char *filename, + size_t *size_ret) { - const struct wim_dentry *dentry; const struct blob_descriptor *blob; void *contents; int ret; - dentry = get_dentry(ctx->wim, path, WIMLIB_CASE_INSENSITIVE); if (!dentry) { - XML_WARN("File \"%"TS"\" not found", path); + XML_WARN("%s does not exist", filename); return NULL; } blob = inode_get_blob_for_unnamed_data_stream(dentry->d_inode, ctx->wim->blob_table); if (!blob) { - XML_WARN("File \"%"TS"\" has no contents", path); + XML_WARN("%s has no contents", filename); return NULL; } ret = read_blob_into_alloc_buf(blob, &contents); if (ret) { - XML_WARN("Error loading file \"%"TS"\" (size=%"PRIu64"): %"TS, - path, blob->size, wimlib_get_error_string(ret)); + XML_WARN("Error loading %s (size=%"PRIu64"): %"TS, + filename, blob->size, wimlib_get_error_string(ret)); ctx->oom_encountered |= (ret == WIMLIB_ERR_NOMEM && blob->size < 100000000); return NULL; @@ -630,31 +637,62 @@ load_file_contents(struct windows_info_ctx *ctx, /* Load and validate a registry hive file. */ static void * -load_hive(struct windows_info_ctx *ctx, const tchar *path) +load_hive(struct windows_info_ctx *ctx, const struct wim_dentry *dentry, + const char *filename) { void *hive_mem; size_t hive_size; - hive_mem = load_file_contents(ctx, path, &hive_size); + hive_mem = load_file_contents(ctx, dentry, filename, &hive_size); if (hive_mem && !is_registry_valid(ctx, hive_mem, hive_size)) { - XML_WARN("\"%"TS"\" is not a valid registry hive!", path); + XML_WARN("%s is not a valid registry hive!", filename); FREE(hive_mem); hive_mem = NULL; } return hive_mem; } -/* - * Set Windows-specific XML information for the currently selected WIM image. - * - * This process is heavily based on heuristics and hard-coded logic related to - * where Windows stores certain types of information. Therefore, it simply - * tries to set as much information as possible. If there's a problem, it skips - * the affected information and proceeds to the next part. It only returns an - * error code if there was a severe problem such as out-of-memory. - */ -int -set_windows_specific_info(WIMStruct *wim) +/* Set the WINDOWS/SYSTEMROOT property to the name of the directory specified by + * 'systemroot'. */ +static void +set_systemroot_property(struct windows_info_ctx *ctx, + const struct wim_dentry *systemroot) +{ + utf16lechar *uname; + const tchar *name; + size_t name_nbytes; + int ret; + + /* to uppercase ... */ + uname = utf16le_dupz(systemroot->d_name, systemroot->d_name_nbytes); + if (!uname) { + ctx->oom_encountered = true; + goto out; + } + for (size_t i = 0; i < systemroot->d_name_nbytes / 2; i++) + uname[i] = cpu_to_le16(upcase[le16_to_cpu(uname[i])]); + + /* to tstring ... */ + ret = utf16le_get_tstr(uname, systemroot->d_name_nbytes, + &name, &name_nbytes); + if (ret) { + ctx->oom_encountered |= (ret == WIMLIB_ERR_NOMEM); + XML_WARN("Failed to get systemroot name: %"TS, + wimlib_get_error_string(ret)); + goto out; + } + set_string_property(ctx, T("WINDOWS/SYSTEMROOT"), name); + utf16le_put_tstr(name); +out: + FREE(uname); +} + +static int +do_set_windows_specific_info(WIMStruct *wim, + const struct wim_dentry *systemroot, + const struct wim_dentry *kernel32, + const struct wim_dentry *software, + const struct wim_dentry *system) { void *contents; size_t size; @@ -665,18 +703,19 @@ set_windows_specific_info(WIMStruct *wim) .debug_enabled = (tgetenv(T("WIMLIB_DEBUG_XML_INFO")) != NULL), }, *ctx = &_ctx; - if ((contents = load_file_contents(ctx, kernel32_dll_path, &size))) { - set_string_property(ctx, T("WINDOWS/SYSTEMROOT"), T("WINDOWS")); + set_systemroot_property(ctx, systemroot); + + if ((contents = load_file_contents(ctx, kernel32, "kernel32.dll", &size))) { set_info_from_kernel32(ctx, contents, size); FREE(contents); } - if ((contents = load_hive(ctx, software_hive_path))) { + if ((contents = load_hive(ctx, software, "SOFTWARE"))) { set_info_from_software_hive(ctx, contents); FREE(contents); } - if ((contents = load_hive(ctx, system_hive_path))) { + if ((contents = load_hive(ctx, system, "SYSTEM"))) { set_info_from_system_hive(ctx, contents); FREE(contents); } @@ -689,3 +728,128 @@ set_windows_specific_info(WIMStruct *wim) return 0; } + +/* Windows */ +static const utf16lechar windows_name[] = { + cpu_to_le16('W'), cpu_to_le16('i'), cpu_to_le16('n'), + cpu_to_le16('d'), cpu_to_le16('o'), cpu_to_le16('w'), + cpu_to_le16('s'), +}; + +/* System32 */ +static const utf16lechar system32_name[] = { + cpu_to_le16('S'), cpu_to_le16('y'), cpu_to_le16('s'), + cpu_to_le16('t'), cpu_to_le16('e'), cpu_to_le16('m'), + cpu_to_le16('3'), cpu_to_le16('2'), +}; + +/* kernel32.dll */ +static const utf16lechar kernel32_name[] = { + cpu_to_le16('k'), cpu_to_le16('e'), cpu_to_le16('r'), + cpu_to_le16('n'), cpu_to_le16('e'), cpu_to_le16('l'), + cpu_to_le16('3'), cpu_to_le16('2'), cpu_to_le16('.'), + cpu_to_le16('d'), cpu_to_le16('l'), cpu_to_le16('l'), +}; + +/* config */ +static const utf16lechar config_name[] = { + cpu_to_le16('c'), cpu_to_le16('o'), cpu_to_le16('n'), + cpu_to_le16('f'), cpu_to_le16('i'), cpu_to_le16('g'), +}; + +/* SOFTWARE */ +static const utf16lechar software_name[] = { + cpu_to_le16('S'), cpu_to_le16('O'), cpu_to_le16('F'), + cpu_to_le16('T'), cpu_to_le16('W'), cpu_to_le16('A'), + cpu_to_le16('R'), cpu_to_le16('E'), +}; + +/* SYSTEM */ +static const utf16lechar system_name[] = { + cpu_to_le16('S'), cpu_to_le16('Y'), cpu_to_le16('S'), + cpu_to_le16('T'), cpu_to_le16('E'), cpu_to_le16('M'), +}; + +#define GET_CHILD(parent, child_name) \ + get_dentry_child_with_utf16le_name(parent, \ + child_name, \ + sizeof(child_name), \ + WIMLIB_CASE_INSENSITIVE) + +static bool +is_default_systemroot(const struct wim_dentry *potential_systemroot) +{ + return !cmp_utf16le_strings(potential_systemroot->d_name, + potential_systemroot->d_name_nbytes / 2, + windows_name, + ARRAY_LEN(windows_name), + true); +} + +/* + * Set Windows-specific XML information for the currently selected WIM image. + * + * This process is heavily based on heuristics and hard-coded logic related to + * where Windows stores certain types of information. Therefore, it simply + * tries to set as much information as possible. If there's a problem, it skips + * the affected information and proceeds to the next part. It only returns an + * error code if there was a severe problem such as out-of-memory. + */ +int +set_windows_specific_info(WIMStruct *wim) +{ + const struct wim_dentry *root, *potential_systemroot, + *best_systemroot = NULL, + *best_kernel32 = NULL, + *best_software = NULL, + *best_system = NULL; + int best_score = 0; + + root = wim_get_current_root_dentry(wim); + if (!root) + return 0; + + /* Find the system root. This is usually the toplevel directory + * "Windows", but it might be a different toplevel directory. Choose + * the directory that contains the greatest number of the files we want: + * System32/kernel32.dll, System32/config/SOFTWARE, and + * System32/config/SYSTEM. Compare all names case insensitively. */ + for_dentry_child(potential_systemroot, root) { + const struct wim_dentry *system32, *kernel32, *config, + *software = NULL, *system = NULL; + int score; + + if (!dentry_is_directory(potential_systemroot)) + continue; + system32 = GET_CHILD(potential_systemroot, system32_name); + if (!system32) + continue; + kernel32 = GET_CHILD(system32, kernel32_name); + config = GET_CHILD(system32, config_name); + if (config) { + software = GET_CHILD(config, software_name); + system = GET_CHILD(config, system_name); + } + + score = !!kernel32 + !!software + !!system; + if (score >= best_score) { + /* If there's a tie, prefer the "Windows" directory. */ + if (score > best_score || + is_default_systemroot(potential_systemroot)) + { + best_score = score; + best_systemroot = potential_systemroot; + best_kernel32 = kernel32; + best_software = software; + best_system = system; + } + } + } + + if (likely(best_score == 0)) + return 0; /* No Windows system root found. */ + + /* Found the Windows system root. */ + return do_set_windows_specific_info(wim, best_systemroot, best_kernel32, + best_software, best_system); +}