Coverage Report

Created: 2026-01-16 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/rust/src/rdp/windows.rs
Line
Count
Source
1
/* Copyright (C) 2019 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
// Author: Zach Kelly <zach.kelly@lmco.com>
19
20
/// converts a locale identifier into a locale name
21
/// <https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/70feba9f-294e-491e-b6eb-56532684c37f>
22
24
pub fn lcid_to_string(lcid: u32, default: &str) -> String {
23
24
    let s = match lcid {
24
0
        0x0001 => "ar",
25
0
        0x0002 => "bg",
26
0
        0x0003 => "ca",
27
0
        0x0004 => "zh-Hans",
28
0
        0x0005 => "cs",
29
0
        0x0006 => "da",
30
0
        0x0007 => "de",
31
0
        0x0008 => "el",
32
0
        0x0009 => "en",
33
0
        0x000A => "es",
34
0
        0x000B => "fi",
35
0
        0x000C => "fr",
36
0
        0x000D => "he",
37
0
        0x000E => "hu",
38
0
        0x000F => "is",
39
0
        0x0010 => "it",
40
0
        0x0011 => "ja",
41
0
        0x0012 => "ko",
42
0
        0x0013 => "nl",
43
0
        0x0014 => "no",
44
0
        0x0015 => "pl",
45
0
        0x0016 => "pt",
46
0
        0x0017 => "rm",
47
0
        0x0018 => "ro",
48
0
        0x0019 => "ru",
49
0
        0x001A => "hr",
50
0
        0x001B => "sk",
51
0
        0x001C => "sq",
52
0
        0x001D => "sv",
53
0
        0x001E => "th",
54
0
        0x001F => "tr",
55
0
        0x0020 => "ur",
56
0
        0x0021 => "id",
57
0
        0x0022 => "uk",
58
0
        0x0023 => "be",
59
0
        0x0024 => "sl",
60
0
        0x0025 => "et",
61
0
        0x0026 => "lv",
62
0
        0x0027 => "lt",
63
0
        0x0028 => "tg",
64
0
        0x0029 => "fa",
65
0
        0x002A => "vi",
66
0
        0x002B => "hy",
67
0
        0x002C => "az",
68
0
        0x002D => "eu",
69
0
        0x002E => "hsb",
70
0
        0x002F => "mk",
71
0
        0x0030 => "st",
72
0
        0x0031 => "ts",
73
0
        0x0032 => "tn",
74
0
        0x0033 => "ve",
75
0
        0x0034 => "xh",
76
0
        0x0035 => "zu",
77
0
        0x0036 => "af",
78
0
        0x0037 => "ka",
79
0
        0x0038 => "fo",
80
0
        0x0039 => "hi",
81
0
        0x003A => "mt",
82
0
        0x003B => "se",
83
0
        0x003C => "ga",
84
0
        0x003D => "yi",
85
0
        0x003E => "ms",
86
0
        0x003F => "kk",
87
0
        0x0040 => "ky",
88
0
        0x0041 => "sw",
89
0
        0x0042 => "tk",
90
0
        0x0043 => "uz",
91
0
        0x0044 => "tt",
92
0
        0x0045 => "bn",
93
0
        0x0046 => "pa",
94
0
        0x0047 => "gu",
95
0
        0x0048 => "or",
96
0
        0x0049 => "ta",
97
0
        0x004A => "te",
98
0
        0x004B => "kn",
99
0
        0x004C => "ml",
100
0
        0x004D => "as",
101
0
        0x004E => "mr",
102
0
        0x004F => "sa",
103
0
        0x0050 => "mn",
104
0
        0x0051 => "bo",
105
0
        0x0052 => "cy",
106
0
        0x0053 => "km",
107
0
        0x0054 => "lo",
108
0
        0x0055 => "my",
109
0
        0x0056 => "gl",
110
0
        0x0057 => "kok",
111
0
        0x0058 => "mni",
112
0
        0x0059 => "sd",
113
0
        0x005A => "syr",
114
0
        0x005B => "si",
115
0
        0x005C => "chr",
116
0
        0x005D => "iu",
117
0
        0x005E => "am",
118
0
        0x005F => "tzm",
119
0
        0x0060 => "ks",
120
0
        0x0061 => "ne",
121
0
        0x0062 => "fy",
122
0
        0x0063 => "ps",
123
0
        0x0064 => "fil",
124
0
        0x0065 => "dv",
125
0
        0x0066 => "bin",
126
0
        0x0067 => "ff",
127
0
        0x0068 => "ha",
128
0
        0x0069 => "ibb",
129
0
        0x006A => "yo",
130
0
        0x006B => "quz",
131
0
        0x006C => "nso",
132
0
        0x006D => "ba",
133
0
        0x006E => "lb",
134
0
        0x006F => "kl",
135
0
        0x0070 => "ig",
136
0
        0x0071 => "kr",
137
0
        0x0072 => "om",
138
0
        0x0073 => "ti",
139
0
        0x0074 => "gn",
140
0
        0x0075 => "haw",
141
0
        0x0076 => "la",
142
0
        0x0077 => "so",
143
0
        0x0078 => "ii",
144
0
        0x0079 => "pap",
145
0
        0x007A => "arn",
146
0
        0x007C => "moh",
147
0
        0x007E => "br",
148
0
        0x0080 => "ug",
149
0
        0x0081 => "mi",
150
0
        0x0082 => "oc",
151
0
        0x0083 => "co",
152
0
        0x0084 => "gsw",
153
0
        0x0085 => "sah",
154
0
        0x0086 => "qut",
155
0
        0x0087 => "rw",
156
0
        0x0088 => "wo",
157
0
        0x008C => "prs",
158
0
        0x0091 => "gd",
159
0
        0x0092 => "ku",
160
0
        0x0093 => "quc",
161
0
        0x0401 => "ar-SA",
162
0
        0x0402 => "bg-BG",
163
0
        0x0403 => "ca-ES",
164
0
        0x0404 => "zh-TW",
165
0
        0x0405 => "cs-CZ",
166
0
        0x0406 => "da-DK",
167
0
        0x0407 => "de-DE",
168
0
        0x0408 => "el-GR",
169
17
        0x0409 => "en-US",
170
0
        0x040A => "es-ES_tradnl",
171
0
        0x040B => "fi-FI",
172
0
        0x040C => "fr-FR",
173
0
        0x040D => "he-IL",
174
0
        0x040E => "hu-HU",
175
0
        0x040F => "is-IS",
176
0
        0x0410 => "it-IT",
177
0
        0x0411 => "ja-JP",
178
0
        0x0412 => "ko-KR",
179
0
        0x0413 => "nl-NL",
180
0
        0x0414 => "nb-NO",
181
0
        0x0415 => "pl-PL",
182
0
        0x0416 => "pt-BR",
183
0
        0x0417 => "rm-CH",
184
0
        0x0418 => "ro-RO",
185
0
        0x0419 => "ru-RU",
186
0
        0x041A => "hr-HR",
187
0
        0x041B => "sk-SK",
188
0
        0x041C => "sq-AL",
189
0
        0x041D => "sv-SE",
190
0
        0x041E => "th-TH",
191
0
        0x041F => "tr-TR",
192
0
        0x0420 => "ur-PK",
193
0
        0x0421 => "id-ID",
194
0
        0x0422 => "uk-UA",
195
0
        0x0423 => "be-BY",
196
0
        0x0424 => "sl-SI",
197
0
        0x0425 => "et-EE",
198
0
        0x0426 => "lv-LV",
199
0
        0x0427 => "lt-LT",
200
0
        0x0428 => "tg-Cyrl-TJ",
201
0
        0x0429 => "fa-IR",
202
0
        0x042A => "vi-VN",
203
0
        0x042B => "hy-AM",
204
0
        0x042C => "az-Latn-AZ",
205
0
        0x042D => "eu-ES",
206
0
        0x042E => "hsb-DE",
207
0
        0x042F => "mk-MK",
208
0
        0x0430 => "st-ZA",
209
0
        0x0431 => "ts-ZA",
210
0
        0x0432 => "tn-ZA",
211
0
        0x0433 => "ve-ZA",
212
0
        0x0434 => "xh-ZA",
213
0
        0x0435 => "zu-ZA",
214
0
        0x0436 => "af-ZA",
215
0
        0x0437 => "ka-GE",
216
0
        0x0438 => "fo-FO",
217
0
        0x0439 => "hi-IN",
218
0
        0x043A => "mt-MT",
219
0
        0x043B => "se-NO",
220
0
        0x043D => "yi-Hebr",
221
0
        0x043E => "ms-MY",
222
0
        0x043F => "kk-KZ",
223
0
        0x0440 => "ky-KG",
224
0
        0x0441 => "sw-KE",
225
0
        0x0442 => "tk-TM",
226
0
        0x0443 => "uz-Latn-UZ",
227
0
        0x0444 => "tt-RU",
228
0
        0x0445 => "bn-IN",
229
0
        0x0446 => "pa-IN",
230
0
        0x0447 => "gu-IN",
231
0
        0x0448 => "or-IN",
232
0
        0x0449 => "ta-IN",
233
0
        0x044A => "te-IN",
234
0
        0x044B => "kn-IN",
235
0
        0x044C => "ml-IN",
236
0
        0x044D => "as-IN",
237
0
        0x044E => "mr-IN",
238
0
        0x044F => "sa-IN",
239
0
        0x0450 => "mn-MN",
240
0
        0x0451 => "bo-CN",
241
0
        0x0452 => "cy-GB",
242
0
        0x0453 => "km-KH",
243
0
        0x0454 => "lo-LA",
244
0
        0x0455 => "my-MM",
245
0
        0x0456 => "gl-ES",
246
0
        0x0457 => "kok-IN",
247
0
        0x0458 => "mni-IN",
248
0
        0x0459 => "sd-Deva-IN",
249
0
        0x045A => "syr-SY",
250
0
        0x045B => "si-LK",
251
0
        0x045C => "chr-Cher-US",
252
0
        0x045D => "iu-Cans-CA",
253
0
        0x045E => "am-ET",
254
0
        0x045F => "tzm-Arab-MA",
255
0
        0x0460 => "ks-Arab",
256
0
        0x0461 => "ne-NP",
257
0
        0x0462 => "fy-NL",
258
0
        0x0463 => "ps-AF",
259
0
        0x0464 => "fil-PH",
260
0
        0x0465 => "dv-MV",
261
0
        0x0466 => "bin-NG",
262
0
        0x0467 => "fuv-NG",
263
0
        0x0468 => "ha-Latn-NG",
264
0
        0x0469 => "ibb-NG",
265
0
        0x046A => "yo-NG",
266
0
        0x046B => "quz-BO",
267
0
        0x046C => "nso-ZA",
268
0
        0x046D => "ba-RU",
269
0
        0x046E => "lb-LU",
270
0
        0x046F => "kl-GL",
271
0
        0x0470 => "ig-NG",
272
0
        0x0471 => "kr-NG",
273
0
        0x0472 => "om-ET",
274
0
        0x0473 => "ti-ET",
275
0
        0x0474 => "gn-PY",
276
0
        0x0475 => "haw-US",
277
0
        0x0476 => "la-Latn",
278
0
        0x0477 => "so-SO",
279
0
        0x0478 => "ii-CN",
280
0
        0x0479 => "pap-029",
281
0
        0x047A => "arn-CL",
282
0
        0x047C => "moh-CA",
283
0
        0x047E => "br-FR",
284
0
        0x0480 => "ug-CN",
285
0
        0x0481 => "mi-NZ",
286
0
        0x0482 => "oc-FR",
287
0
        0x0483 => "co-FR",
288
0
        0x0484 => "gsw-FR",
289
0
        0x0485 => "sah-RU",
290
0
        0x0486 => "qut-GT",
291
0
        0x0487 => "rw-RW",
292
0
        0x0488 => "wo-SN",
293
0
        0x048C => "prs-AF",
294
0
        0x048D => "plt-MG",
295
0
        0x048E => "zh-yue-HK",
296
0
        0x048F => "tdd-Tale-CN",
297
0
        0x0490 => "khb-Talu-CN",
298
0
        0x0491 => "gd-GB",
299
0
        0x0492 => "ku-Arab-IQ",
300
0
        0x0493 => "quc-CO",
301
0
        0x0501 => "qps-ploc",
302
0
        0x05FE => "qps-ploca",
303
0
        0x0801 => "ar-IQ",
304
0
        0x0803 => "ca-ES-valencia",
305
0
        0x0804 => "zh-CN",
306
0
        0x0807 => "de-CH",
307
0
        0x0809 => "en-GB",
308
0
        0x080A => "es-MX",
309
0
        0x080C => "fr-BE",
310
0
        0x0810 => "it-CH",
311
0
        0x0811 => "ja-Ploc-JP",
312
0
        0x0813 => "nl-BE",
313
0
        0x0814 => "nn-NO",
314
0
        0x0816 => "pt-PT",
315
0
        0x0818 => "ro-MD",
316
0
        0x0819 => "ru-MD",
317
0
        0x081A => "sr-Latn-CS",
318
0
        0x081D => "sv-FI",
319
0
        0x0820 => "ur-IN",
320
0
        0x082C => "az-Cyrl-AZ",
321
0
        0x082E => "dsb-DE",
322
0
        0x0832 => "tn-BW",
323
0
        0x083B => "se-SE",
324
0
        0x083C => "ga-IE",
325
0
        0x083E => "ms-BN",
326
0
        0x0843 => "uz-Cyrl-UZ",
327
0
        0x0845 => "bn-BD",
328
0
        0x0846 => "pa-Arab-PK",
329
0
        0x0849 => "ta-LK",
330
0
        0x0850 => "mn-Mong-CN",
331
0
        0x0851 => "bo-BT",
332
0
        0x0859 => "sd-Arab-PK",
333
0
        0x085D => "iu-Latn-CA",
334
0
        0x085F => "tzm-Latn-DZ",
335
0
        0x0860 => "ks-Deva",
336
0
        0x0861 => "ne-IN",
337
0
        0x0867 => "ff-Latn-SN",
338
0
        0x086B => "quz-EC",
339
0
        0x0873 => "ti-ER",
340
0
        0x09FF => "qps-plocm",
341
0
        0x0C01 => "ar-EG",
342
0
        0x0C04 => "zh-HK",
343
0
        0x0C07 => "de-AT",
344
0
        0x0C09 => "en-AU",
345
0
        0x0C0A => "es-ES",
346
0
        0x0C0C => "fr-CA",
347
0
        0x0C1A => "sr-Cyrl-CS",
348
0
        0x0C3B => "se-FI",
349
0
        0x0C50 => "mn-Mong-MN",
350
0
        0x0C51 => "dz-BT",
351
0
        0x0C5F => "tmz-MA",
352
0
        0x0C6B => "quz-PE",
353
0
        0x1001 => "ar-LY",
354
0
        0x1004 => "zh-SG",
355
0
        0x1007 => "de-LU",
356
0
        0x1009 => "en-CA",
357
0
        0x100A => "es-GT",
358
0
        0x100C => "fr-CH",
359
0
        0x101A => "hr-BA",
360
0
        0x103B => "smj-NO",
361
0
        0x105F => "tzm-Tfng-MA",
362
0
        0x1401 => "ar-DZ",
363
0
        0x1404 => "zh-MO",
364
0
        0x1407 => "de-LI",
365
0
        0x1409 => "en-NZ",
366
0
        0x140A => "es-CR",
367
0
        0x140C => "fr-LU",
368
0
        0x141A => "bs-Latn-BA",
369
0
        0x143B => "smj-SE",
370
0
        0x1801 => "ar-MA",
371
0
        0x1809 => "en-IE",
372
0
        0x180A => "es-PA",
373
0
        0x180C => "fr-MC",
374
0
        0x181A => "sr-Latn-BA",
375
0
        0x183B => "sma-NO",
376
0
        0x1C01 => "ar-TN",
377
0
        0x1C09 => "en-ZA",
378
0
        0x1C0A => "es-DO",
379
0
        0x1C1A => "sr-Cyrl-BA",
380
0
        0x1C3B => "sma-SE",
381
0
        0x2001 => "ar-OM",
382
0
        0x2009 => "en-JM",
383
0
        0x200A => "es-VE",
384
0
        0x200C => "fr-RE",
385
0
        0x201A => "bs-Cyrl-BA",
386
0
        0x203B => "sms-FI",
387
0
        0x2401 => "ar-YE",
388
0
        0x2409 => "en-029",
389
0
        0x240A => "es-CO",
390
0
        0x240C => "fr-CD",
391
0
        0x241A => "sr-Latn-RS",
392
0
        0x243B => "smn-FI",
393
0
        0x2801 => "ar-SY",
394
0
        0x2809 => "en-BZ",
395
0
        0x280A => "es-PE",
396
0
        0x280C => "fr-SN",
397
0
        0x281A => "sr-Cyrl-RS",
398
0
        0x2C01 => "ar-JO",
399
0
        0x2C09 => "en-TT",
400
0
        0x2C0A => "es-AR",
401
0
        0x2C0C => "fr-CM",
402
0
        0x2C1A => "sr-Latn-ME",
403
0
        0x3001 => "ar-LB",
404
0
        0x3009 => "en-ZW",
405
0
        0x300A => "es-EC",
406
0
        0x300C => "fr-CI",
407
0
        0x301A => "sr-Cyrl-ME",
408
0
        0x3401 => "ar-KW",
409
0
        0x3409 => "en-PH",
410
0
        0x340A => "es-CL",
411
0
        0x340C => "fr-ML",
412
0
        0x3801 => "ar-AE",
413
0
        0x3809 => "en-ID",
414
0
        0x380A => "es-UY",
415
0
        0x380C => "fr-MA",
416
0
        0x3c01 => "ar-BH",
417
0
        0x3c09 => "en-HK",
418
0
        0x3C0A => "es-PY",
419
0
        0x3C0C => "fr-HT",
420
0
        0x4001 => "ar-QA",
421
0
        0x4009 => "en-IN",
422
0
        0x400A => "es-BO",
423
0
        0x4401 => "ar-Ploc-SA",
424
0
        0x4409 => "en-MY",
425
0
        0x440A => "es-SV",
426
0
        0x4801 => "ar-145",
427
0
        0x4809 => "en-SG",
428
0
        0x480A => "es-HN",
429
0
        0x4C09 => "en-AE",
430
0
        0x4C0A => "es-NI",
431
0
        0x5009 => "en-BH",
432
0
        0x500A => "es-PR",
433
0
        0x5409 => "en-EG",
434
0
        0x540A => "es-US",
435
0
        0x5809 => "en-JO",
436
0
        0x580A => "es-419",
437
0
        0x5C09 => "en-KW",
438
0
        0x5C0A => "es-CU",
439
0
        0x6009 => "en-TR",
440
0
        0x6409 => "en-YE",
441
0
        0x641A => "bs-Cyrl",
442
0
        0x681A => "bs-Latn",
443
0
        0x6C1A => "sr-Cyrl",
444
0
        0x701A => "sr-Latn",
445
0
        0x703B => "smn",
446
0
        0x742C => "az-Cyrl",
447
0
        0x743B => "sms",
448
0
        0x7804 => "zh",
449
0
        0x7814 => "nn",
450
0
        0x781A => "bs",
451
0
        0x782C => "az-Latn",
452
0
        0x783B => "sma",
453
0
        0x7843 => "uz-Cyrl",
454
0
        0x7850 => "mn-Cyrl",
455
0
        0x785D => "iu-Cans",
456
0
        0x785F => "tzm-Tfng",
457
0
        0x7C04 => "zh-Hant",
458
0
        0x7C14 => "nb",
459
0
        0x7C1A => "sr",
460
0
        0x7C28 => "tg-Cyrl",
461
0
        0x7C2E => "dsb",
462
0
        0x7C3B => "smj",
463
0
        0x7C43 => "uz-Latn",
464
0
        0x7C46 => "pa-Arab",
465
0
        0x7C50 => "mn-Mong",
466
0
        0x7C59 => "sd-Arab",
467
0
        0x7C5C => "chr-Cher",
468
0
        0x7C5D => "iu-Latn",
469
0
        0x7C5F => "tzm-Latn",
470
0
        0x7C67 => "ff-Latn",
471
0
        0x7C68 => "ha-Latn",
472
0
        0x7C92 => "ku-Arab",
473
7
        _ => default,
474
    };
475
24
    String::from(s)
476
24
}
477
478
/// Windows operating system type (build and suffix/pack)
479
#[derive(Clone, Debug, PartialEq, Eq)]
480
pub struct OperatingSystem {
481
    pub build: Build,
482
    pub suffix: Suffix,
483
}
484
485
// <https://en.wikipedia.org/wiki/Windows_NT#Releases>
486
#[derive(Clone, Debug, FromPrimitive, PartialEq, Eq)]
487
#[allow(non_camel_case_types)]
488
pub enum Build {
489
    Other,
490
    Win31 = 528,
491
    Win35 = 807,
492
    Win351 = 1057,
493
    Win40 = 1381,
494
    Win2000 = 2195,
495
    WinXP = 2600,
496
    Vista_6000 = 6000,
497
    Vista_6001 = 6001,
498
    Vista_6002 = 6002,
499
    Win7_7600 = 7600,
500
    Win7_7601 = 7601,
501
    Win8 = 9200,
502
    Win81 = 9600,
503
    Win10_10240 = 10240,
504
    Win10_10586 = 10586,
505
    Win10_14393 = 14393,
506
    Win10_15063 = 15063,
507
    Win10_16299 = 16299,
508
    Win10_17134 = 17134,
509
    Win10_17763 = 17763,
510
    Server2003 = 3790,
511
}
512
513
#[derive(Clone, Debug, PartialEq, Eq)]
514
pub enum Suffix {
515
    Empty,
516
    Rtm,
517
    Sp1,
518
    Sp2,
519
    Th1,
520
    Th2,
521
    Rs1,
522
    Rs2,
523
    Rs3,
524
    Rs4,
525
    Rs5,
526
}
527
528
/// convert a build number into an OperatingSystem type
529
17.2k
pub fn build_number_to_os(number: u32) -> OperatingSystem {
530
17.2k
    let build = match num::FromPrimitive::from_u32(number) {
531
5.29k
        Some(x) => x,
532
11.9k
        None => Build::Other,
533
    };
534
17.2k
    let suffix = match number {
535
194
        6000 => Suffix::Rtm,
536
194
        7600 => Suffix::Rtm,
537
194
        6001 => Suffix::Sp1,
538
194
        6002 => Suffix::Sp2,
539
196
        7601 => Suffix::Sp1,
540
380
        10240 => Suffix::Th1,
541
194
        10586 => Suffix::Th2,
542
194
        14393 => Suffix::Rs1,
543
194
        15063 => Suffix::Rs2,
544
197
        16299 => Suffix::Rs3,
545
194
        17134 => Suffix::Rs4,
546
226
        17763 => Suffix::Rs5,
547
14.6k
        _ => Suffix::Empty,
548
    };
549
17.2k
    OperatingSystem { build, suffix }
550
17.2k
}
551
552
/// convert an OperatingSystem into a string description
553
24
pub fn os_to_string(os: &OperatingSystem, default: &str) -> String {
554
24
    let s = match os.build {
555
0
        Build::Win31 => "Windows NT 3.1",
556
0
        Build::Win35 => "Windows NT 3.5",
557
0
        Build::Win351 => "Windows NT 3.51",
558
0
        Build::Win40 => "Windows NT 4.0",
559
0
        Build::Win2000 => "Windows 2000",
560
15
        Build::WinXP => "Windows XP",
561
0
        Build::Vista_6000 => "Windows Vista",
562
0
        Build::Vista_6001 => "Windows Vista",
563
0
        Build::Vista_6002 => "Windows Vista",
564
0
        Build::Win7_7600 => "Windows 7",
565
0
        Build::Win7_7601 => "Windows 7",
566
0
        Build::Win8 => "Windows 8",
567
0
        Build::Win81 => "Windows 8.1",
568
0
        Build::Win10_10240 => "Windows 10",
569
0
        Build::Win10_10586 => "Windows 10",
570
0
        Build::Win10_14393 => "Windows 10",
571
0
        Build::Win10_15063 => "Windows 10",
572
0
        Build::Win10_16299 => "Windows 10",
573
0
        Build::Win10_17134 => "Windows 10",
574
0
        Build::Win10_17763 => "Windows 10",
575
0
        Build::Server2003 => "Windows Server 2003",
576
9
        Build::Other => default,
577
    };
578
24
    let mut result = String::from(s);
579
24
    match os.suffix {
580
0
        Suffix::Rtm => result.push_str(" RTM"),
581
0
        Suffix::Sp1 => result.push_str(" SP1"),
582
0
        Suffix::Sp2 => result.push_str(" SP2"),
583
0
        Suffix::Th1 => result.push_str(" TH1"),
584
0
        Suffix::Th2 => result.push_str(" TH2"),
585
0
        Suffix::Rs1 => result.push_str(" RS1"),
586
0
        Suffix::Rs2 => result.push_str(" RS2"),
587
0
        Suffix::Rs3 => result.push_str(" RS3"),
588
0
        Suffix::Rs4 => result.push_str(" RS4"),
589
0
        Suffix::Rs5 => result.push_str(" RS5"),
590
24
        Suffix::Empty => (),
591
    };
592
24
    result
593
24
}
594
595
#[cfg(test)]
596
mod tests {
597
    use super::*;
598
599
    #[test]
600
    fn test_lcid_string_en() {
601
        let default = "default-lcid-name";
602
        assert_eq!("en-US", lcid_to_string(0x409, default));
603
    }
604
605
    #[test]
606
    fn test_lcid_string_default() {
607
        let default = "default-lcid-name";
608
        assert_eq!(default, lcid_to_string(0xffff, default));
609
    }
610
611
    #[test]
612
    fn test_build_os_win10() {
613
        let w10_rs5 = OperatingSystem {
614
            build: Build::Win10_17763,
615
            suffix: Suffix::Rs5,
616
        };
617
        assert_eq!(w10_rs5, build_number_to_os(17763));
618
    }
619
620
    #[test]
621
    fn test_build_os_other() {
622
        let other = OperatingSystem {
623
            build: Build::Other,
624
            suffix: Suffix::Empty,
625
        };
626
        assert_eq!(other, build_number_to_os(1));
627
    }
628
629
    #[test]
630
    fn test_os_string_win7_sp1() {
631
        let w7_sp1 = "Windows 7 SP1";
632
        let default = "default-os-name";
633
        let w7_os = OperatingSystem {
634
            build: Build::Win7_7601,
635
            suffix: Suffix::Sp1,
636
        };
637
        assert_eq!(w7_sp1, os_to_string(&w7_os, default));
638
    }
639
640
    #[test]
641
    fn test_os_string_win81() {
642
        let w81 = "Windows 8.1";
643
        let default = "default-os-name";
644
        let w81_os = OperatingSystem {
645
            build: Build::Win81,
646
            suffix: Suffix::Empty,
647
        };
648
        assert_eq!(w81, os_to_string(&w81_os, default));
649
    }
650
651
    #[test]
652
    fn test_os_string_default() {
653
        let default = "default-os-name";
654
        let other_os = OperatingSystem {
655
            build: Build::Other,
656
            suffix: Suffix::Empty,
657
        };
658
        assert_eq!(default, os_to_string(&other_os, default));
659
    }
660
}