Commits

Wang Dingwei committed 62049d5

First commit.

Comments (0)

Files changed (9)

+syntax: glob
+*.pyc
+
+syntax: regexp

ABC.ico

Added
New image
+#!python
+#
+# Author: Joel Wang <Joel_Wang@wistron.com>
+#
+# History:
+# 2010-08-25, V3.0, colorful output
+# 2010-06-19, V2.1, fixed MUI logic. Added py2exe support.
+# 2010-05-24, V2.0, code refactored.
+# 2010-05-20, V1.4, better mui support.
+# 2010-05-20, V1.3, fixed spanish OS description, more error check code added.
+# 2010-05-19, V1.2, read system language from registry instead of locale
+# settings.
+# 2010-05-10, V1.1, minor tweaks, now it uses optparse module.
+# 2010-05-06, V1.0, first release.
+#
+
+"""
+Compares Installed OS information with SDR information. Reports failure if they
+are not matched.
+"""
+
+import os
+import sys
+import optparse
+import msvcrt
+import ostype
+import sdrparse
+
+from pyreadline.console import Console
+
+version = '3.0'
+
+c = Console() #(default=green)
+cprint = c.write_color
+
+red =lambda s: '\033[1;31m' + s + '\033[0;0m' + '\n'
+green =lambda s: '\033[1;32m' + s + '\033[0;0m' + '\n'
+yellow = lambda s: '\033[1;33m' + s + '\033[0;0m' + '\n'
+
+def print_error(s):
+    print_ng()
+    cprint(yellow(s))
+    exit(1)
+
+def print_mui(sdrobj):
+    cprint(green("#######################################"))
+    cprint(green("     ##     ##    ##     ##    ####"))
+    cprint(green("     ###   ###    ##     ##     ##"))
+    cprint(green("     #### ####    ##     ##     ##"))
+    cprint(green("     ## ### ##    ##     ##     ##"))
+    cprint(green("     ##     ##    ##     ##     ##"))
+    cprint(green("     ##     ##    ##     ##     ##"))
+    cprint(green("     ##     ##     #######     ####"))
+    cprint(green("#######################################"))
+    print
+    print "MUI Order! There are %s languages:" % len(sdrobj.mui_parts())
+    print
+
+    for (pn, desc) in sdrobj.mui_parts():
+        print "*", sdrparse.get_sdr_lang(desc)
+        if VERBOSE:
+            print "*", pn, desc
+    print
+    print "PO:       ", sdrobj.get_po()
+    return
+
+def print_mui_ng(sdrobj, os_mui):
+    print_ng()
+    print "MUI order NG!"
+    print
+    print "==========SDR MUI Info============="
+    for (pn, desc) in sdrobj.mui_parts():
+        print "*", sdrparse.get_sdr_lang(desc)
+        if VERBOSE:
+            print "*", pn, desc
+    print "==========OS MUI Info=============="
+    for i in os_mui:
+        print "*", i
+    else:
+        print "None"
+    print
+    print "PO:       ", sdrobj.get_po()
+    return
+
+def print_ok():
+    cprint(green("###################################"))
+    cprint(green("      #######     ##    ## "))
+    cprint(green("     ##     ##    ##   ##  "))
+    cprint(green("     ##     ##    ##  ##   "))
+    cprint(green("     ##     ##    #####    "))
+    cprint(green("     ##     ##    ##  ##   "))
+    cprint(green("     ##     ##    ##   ##  "))
+    cprint(green("      #######     ##    ## "))
+    cprint(green("###################################"))
+    print
+
+def print_ng():
+    cprint(red("###################################"))
+    cprint(red("     ##    ##     ######   "))
+    cprint(red("     ###   ##    ##    ##  "))
+    cprint(red("     ####  ##    ##        "))
+    cprint(red("     ## ## ##    ##   #### "))
+    cprint(red("     ##  ####    ##    ##  "))
+    cprint(red("     ##   ###    ##    ##  "))
+    cprint(red("     ##    ##     ######  "))
+    cprint(red("###################################"))
+    print
+
+def print_os_info(os_type, os_lang):
+    print "==========System Info=============="
+    print "OS:       ", os_type
+    print "Language: ", os_lang[0]
+    print "Region:   ", os_lang[1]
+    print
+
+def print_sdr_info(sdrobj):
+    print "=============SDR Info=============="
+    print "OS:       ", sdrobj.os_type()
+    print "Language: ", sdrobj.os_lang()[0]
+    print "Region:   ", sdrobj.os_lang()[1]
+    print
+    print "PO:       ", sdrobj.get_po()
+    if VERBOSE:
+        print "SRV:      ", sdrobj.os_srv()
+    print
+
+def lang_matched(sdr_lang, os_lang):
+    if sdr_lang[0] == os_lang[0]:
+        if not sdr_lang[1] or os_lang[1] in sdr_lang[1]:
+            return True
+        else:
+            return False
+    else:
+        return False
+
+def mui_matched(os_mui, sdr_mui):
+    "Compares all mui parts with registry info, return True if OK."
+    if len(os_mui) == len(sdr_mui):
+        zipped = zip(sdr_mui, os_mui)
+        for (sdr_lang, os_lang) in zipped:
+            if not lang_matched(sdr_lang, os_lang):
+                return False
+        return True
+    else:
+        return False
+
+def check_table(sdrobj):
+    "Validates OS SRVs against the SRV dictionary."
+    print 'checks table'
+    if not sdrobj.has_valid_srv():
+        print_ng()
+        print "The OS SRV is not in the dictionary."
+        print sdrobj.os_srv()
+
+def process_mui_sdr(sdrobj):
+    os_type = ostype.GetWindowsVersion()
+    os_lang = ostype.GetWindowsLanguage()
+    if sdrobj.is_mui():
+        os_mui = ostype.GetWindowsMUI() # A list of (Lang, Region) tuples
+        os_mui.sort(key=lambda x: x[0])
+        sdr_mui = [sdrparse.get_sdr_lang(x[1]) for x in sdrobj.mui_parts()]
+        sdr_mui.sort(key=lambda x: x[0])
+        if mui_matched(os_mui, sdr_mui):
+            print_mui(sdrobj)
+            msvcrt.getch()
+            sys.exit(0)
+        else:
+            print_mui_ng(sdrobj, os_mui)
+            print_os_info(os_type, os_lang)
+            msvcrt.getch()
+            sys.exit(1)
+
+def process_normal_sdr(sdrobj):
+    os_type = ostype.GetWindowsVersion()
+    os_lang = ostype.GetWindowsLanguage()
+    if os_type == sdrobj.os_type() and lang_matched(sdrobj.os_lang(), os_lang):
+        print_ok()
+        print_os_info(os_type, os_lang)
+        print_sdr_info(sdrobj)
+        msvcrt.getch()
+        sys.exit(0)
+    else:
+        print_ng()
+        print_os_info(os_type, os_lang)
+        print_sdr_info(sdrobj)
+        msvcrt.getch()
+        sys.exit(1)
+
+def main():
+    global VERBOSE, DEBUG
+    VERBOSE = False
+    USAGE = 'usage: %prog [options]'
+
+    # Parsing arguments
+    opts = optparse.OptionParser(usage=USAGE, version=version)
+    opts.add_option('-c', '--check-table', action="store_true",
+            dest='CHECK_TABLE')
+    opts.add_option('-v', '--verbose', action="store_true", dest='VERBOSE')
+    opts.add_option('-d', '--debug', action="store_true", dest='DEBUG')
+    options, args = opts.parse_args()
+    VERBOSE = options.VERBOSE
+    DEBUG = options.DEBUG
+
+    # Read SDR information
+    sdr_path = 'C:\\dell.sdr'
+    if not os.path.exists(sdr_path):
+        print_error("SDR not found!")
+    sdrobj = sdrparse.SDR(sdr_path)
+
+    process_mui_sdr(sdrobj)
+    if options.CHECK_TABLE:
+        check_table(sdrobj)
+    process_normal_sdr(sdrobj)
+
+if __name__ == '__main__':
+    sys.exit(main())
+#!python
+#
+# Author: Joel Wang <Joel_Wang@wistron.com>
+#
+# History:
+# 2010-09-17, V4.0, output as html, opens in browser instead of cmd
+# 2010-08-25, V3.0, colorful output
+# 2010-06-19, V2.1, fixed MUI logic. Added py2exe support.
+# 2010-05-24, V2.0, code refactored.
+# 2010-05-20, V1.4, better mui support.
+# 2010-05-20, V1.3, fixed spanish OS description, more error check code added.
+# 2010-05-19, V1.2, read system language from registry instead of locale
+# settings.
+# 2010-05-10, V1.1, minor tweaks, now it uses optparse module.
+# 2010-05-06, V1.0, first release.
+#
+
+"""
+Compares Installed OS information with SDR information. Reports failure if they
+are not matched.
+"""
+
+import os
+import sys
+import optparse
+import msvcrt
+import ostype
+import sdrparse
+
+from pyreadline.console import Console
+
+version = '3.0'
+
+c = Console() #(default=green)
+cprint = c.write_color
+
+red = lambda s: '\033[1;31m' + s + '\033[0;0m' + '\n'
+green = lambda s: '\033[1;32m' + s + '\033[0;0m' + '\n'
+yellow = lambda s: '\033[1;33m' + s + '\033[0;0m' + '\n'
+
+def print_error(s):
+    print_ng()
+    cprint(yellow(s))
+    exit(1)
+
+def print_mui(sdrobj):
+    cprint(green("#######################################"))
+    cprint(green("     ##     ##    ##     ##    ####"))
+    cprint(green("     ###   ###    ##     ##     ##"))
+    cprint(green("     #### ####    ##     ##     ##"))
+    cprint(green("     ## ### ##    ##     ##     ##"))
+    cprint(green("     ##     ##    ##     ##     ##"))
+    cprint(green("     ##     ##    ##     ##     ##"))
+    cprint(green("     ##     ##     #######     ####"))
+    cprint(green("#######################################"))
+    print
+    print "MUI Order! There are %s languages:" % len(sdrobj.mui_parts())
+    print
+
+    for (pn, desc) in sdrobj.mui_parts():
+        print "*", sdrparse.get_sdr_lang(desc)
+        if VERBOSE:
+            print "*", pn, desc
+    print
+    print "PO:       ", sdrobj.get_po()
+    return
+
+def print_mui_ng(sdrobj, os_mui):
+    print_ng()
+    print "MUI order NG!"
+    print
+    print "==========SDR MUI Info============="
+    for (pn, desc) in sdrobj.mui_parts():
+        print "*", sdrparse.get_sdr_lang(desc)
+        if VERBOSE:
+            print "*", pn, desc
+    print "==========OS MUI Info=============="
+    for i in os_mui:
+        print "*", i
+    else:
+        print "None"
+    print
+    print "PO:       ", sdrobj.get_po()
+    return
+
+def print_ok():
+    cprint(green("###################################"))
+    cprint(green("      #######     ##    ## "))
+    cprint(green("     ##     ##    ##   ##  "))
+    cprint(green("     ##     ##    ##  ##   "))
+    cprint(green("     ##     ##    #####    "))
+    cprint(green("     ##     ##    ##  ##   "))
+    cprint(green("     ##     ##    ##   ##  "))
+    cprint(green("      #######     ##    ## "))
+    cprint(green("###################################"))
+    print
+
+def print_ng():
+    cprint(red("###################################"))
+    cprint(red("     ##    ##     ######   "))
+    cprint(red("     ###   ##    ##    ##  "))
+    cprint(red("     ####  ##    ##        "))
+    cprint(red("     ## ## ##    ##   #### "))
+    cprint(red("     ##  ####    ##    ##  "))
+    cprint(red("     ##   ###    ##    ##  "))
+    cprint(red("     ##    ##     ######  "))
+    cprint(red("###################################"))
+    print
+
+def print_os_info(os_type, os_lang):
+    print "==========System Info=============="
+    print "OS:       ", os_type
+    print "Language: ", os_lang[0]
+    print "Region:   ", os_lang[1]
+    print
+
+def print_sdr_info(sdrobj):
+    print "=============SDR Info=============="
+    print "OS:       ", sdrobj.os_type()
+    print "Language: ", sdrobj.os_lang()[0]
+    print "Region:   ", sdrobj.os_lang()[1]
+    print
+    print "PO:       ", sdrobj.get_po()
+    if VERBOSE:
+        print "SRV:      ", sdrobj.os_srv()
+    print
+
+def lang_matched(sdr_lang, os_lang):
+    if sdr_lang[0] == os_lang[0]:
+        if not sdr_lang[1] or os_lang[1] in sdr_lang[1]:
+            return True
+        else:
+            return False
+    else:
+        return False
+
+def mui_matched(os_mui, sdr_mui):
+    "Compares all mui parts with registry info, return True if OK."
+    if len(os_mui) == len(sdr_mui):
+        zipped = zip(sdr_mui, os_mui)
+        for (sdr_lang, os_lang) in zipped:
+            if not lang_matched(sdr_lang, os_lang):
+                return False
+        return True
+    else:
+        return False
+
+def check_table(sdrobj):
+    "Validates OS SRVs against the SRV dictionary."
+    print 'checks table'
+    if not sdrobj.has_valid_srv():
+        print_ng()
+        print "The OS SRV is not in the dictionary."
+        print sdrobj.os_srv()
+
+def process_mui_sdr(sdrobj):
+    os_type = ostype.GetWindowsVersion()
+    os_lang = ostype.GetWindowsLanguage()
+    if sdrobj.is_mui():
+        os_mui = ostype.GetWindowsMUI() # A list of (Lang, Region) tuples
+        os_mui.sort(key=lambda x: x[0])
+        sdr_mui = [sdrparse.get_sdr_lang(x[1]) for x in sdrobj.mui_parts()]
+        sdr_mui.sort(key=lambda x: x[0])
+        if mui_matched(os_mui, sdr_mui):
+            print_mui(sdrobj)
+            msvcrt.getch()
+            sys.exit(0)
+        else:
+            print_mui_ng(sdrobj, os_mui)
+            print_os_info(os_type, os_lang)
+            msvcrt.getch()
+            sys.exit(1)
+
+def process_normal_sdr(sdrobj):
+    os_type = ostype.GetWindowsVersion()
+    os_lang = ostype.GetWindowsLanguage()
+    if os_type == sdrobj.os_type() and lang_matched(sdrobj.os_lang(), os_lang):
+        print_ok()
+        print_os_info(os_type, os_lang)
+        print_sdr_info(sdrobj)
+        msvcrt.getch()
+        sys.exit(0)
+    else:
+        print_ng()
+        print_os_info(os_type, os_lang)
+        print_sdr_info(sdrobj)
+        msvcrt.getch()
+        sys.exit(1)
+
+def main():
+    global VERBOSE, DEBUG
+    VERBOSE = False
+    USAGE = 'usage: %prog [options]'
+
+    # Parsing arguments
+    opts = optparse.OptionParser(usage=USAGE, version=version)
+    opts.add_option('-c', '--check-table', action="store_true",
+            dest='CHECK_TABLE')
+    opts.add_option('-v', '--verbose', action="store_true", dest='VERBOSE')
+    opts.add_option('-d', '--debug', action="store_true", dest='DEBUG')
+    options, args = opts.parse_args()
+    VERBOSE = options.VERBOSE
+    DEBUG = options.DEBUG
+
+    # Read SDR information
+    sdr_path = 'C:\\dell.sdr'
+    if not os.path.exists(sdr_path):
+        print_error("SDR not found!")
+    sdrobj = sdrparse.SDR(sdr_path)
+
+    process_mui_sdr(sdrobj)
+    if options.CHECK_TABLE:
+        check_table(sdrobj)
+    process_normal_sdr(sdrobj)
+
+if __name__ == '__main__':
+    sys.exit(main())
+"All language code got from MS website."
+code = {1025: ('Arabic', 'Saudi Arabia'),
+ 1026: ('Bulgarian', None),
+ 1027: ('Catalan', None),
+ 1028: ('Chinese', 'Taiwan'),
+ 1029: ('Czech', None),
+ 1030: ('Danish', None),
+ 1031: ('German', 'Germany'),
+ 1032: ('Greek', None),
+ 1033: ('English', 'United States'),
+ 1034: ('Spanish', 'Spain (Traditional Sort)'),
+ 1035: ('Finnish', None),
+ 1036: ('French', 'France'),
+ 1037: ('Hebrew', None),
+ 1038: ('Hungarian', None),
+ 1039: ('Icelandic', None),
+ 1040: ('Italian', 'Italy'),
+ 1041: ('Japanese', None),
+ 1042: ('Korean', None),
+ 1043: ('Dutch', 'Netherlands'),
+ 1044: ('Norwegian', 'Bokmal'),
+ 1045: ('Polish', None),
+ 1046: ('Portuguese', 'Brazil'),
+ 1047: ('Rhaeto', 'Romanic'),
+ 1048: ('Romanian', None),
+ 1049: ('Russian', None),
+ 1050: ('Croatian', None),
+ 1051: ('Slovak', None),
+ 1052: ('Albanian', 'Albania'),
+ 1053: ('Swedish', None),
+ 1054: ('Thai', None),
+ 1055: ('Turkish', None),
+ 1056: ('Urdu', None),
+ 1057: ('Indonesian', None),
+ 1058: ('Ukrainian', None),
+ 1059: ('Belarusian', None),
+ 1060: ('Slovenian', None),
+ 1061: ('Estonian', None),
+ 1062: ('Latvian', None),
+ 1063: ('Lithuanian', None),
+ 1064: ('Tajik', None),
+ 1065: ('Farsi', None),
+ 1066: ('Vietnamese', None),
+ 1067: ('Armenian', 'Armenia'),
+ 1068: ('Azeri', 'Latin'),
+ 1069: ('Basque', None),
+ 1070: ('Sorbian', None),
+ 1071: ('FYRO Macedonian', None),
+ 1072: ('Sutu', None),
+ 1073: ('Tsonga', None),
+ 1074: ('Tswana', None),
+ 1075: ('Venda', None),
+ 1076: ('Xhosa', None),
+ 1077: ('Zulu', None),
+ 1078: ('Afrikaans', 'South Africa'),
+ 1079: ('Georgian', None),
+ 1080: ('Faroese', None),
+ 1081: ('Hindi', None),
+ 1082: ('Maltese', None),
+ 1083: ('Sami', 'Lappish'),
+ 1084: ('Gaelic', 'Scotland'),
+ 1085: ('Yiddish', None),
+ 1086: ('Malay', 'Malaysia'),
+ 1087: ('Kazakh', None),
+ 1088: ('Kyrgyz', 'Cyrillic'),
+ 1089: ('Swahili', None),
+ 1090: ('Turkmen', None),
+ 1091: ('Uzbek', 'Latin'),
+ 1092: ('Tatar', None),
+ 1093: ('Bengali', 'India'),
+ 1094: ('Punjabi', None),
+ 1095: ('Gujarati', None),
+ 1096: ('Oriya', None),
+ 1097: ('Tamil', None),
+ 1098: ('Telugu', None),
+ 1099: ('Kannada', None),
+ 1100: ('Malayalam', None),
+ 1101: ('Assamese', None),
+ 1102: ('Marathi', None),
+ 1103: ('Sanskrit', None),
+ 1104: ('Mongolian', 'Cyrillic'),
+ 1105: ('Tibetan', "PRC"),
+ 1106: ('Welsh', None),
+ 1107: ('Khmer', None),
+ 1108: ('Lao', None),
+ 1109: ('Burmese', None),
+ 1110: ('Galician', None),
+ 1111: ('Konkani', None),
+ 1112: ('Manipuri', None),
+ 1113: ('Sindhi', 'India'),
+ 1114: ('Syriac', None),
+ 1115: ('Sinhalese', 'Sri Lanka'),
+ 1116: ('Cherokee', 'United States'),
+ 1117: ('Inuktitut', None),
+ 1118: ('Amharic', 'Ethiopia'),
+ 1119: ('Tamazight', 'Arabic'),
+ 1120: ('Kashmiri', 'Arabic'),
+ 1121: ('Nepali', None),
+ 1122: ('Frisian', 'Netherlands'),
+ 1123: ('Pashto', None),
+ 1124: ('Filipino', None),
+ 1125: ('Divehi', None),
+ 1126: ('Edo', None),
+ 1127: ('Fulfulde', 'Nigeria'),
+ 1128: ('Hausa', 'Nigeria'),
+ 1129: ('Ibibio', 'Nigeria'),
+ 1130: ('Yoruba', None),
+ 1131: ('Quecha', 'Bolivia'),
+ 1132: ('Sepedi', None),
+ 1136: ('Igbo', 'Nigeria'),
+ 1137: ('Kanuri', 'Nigeria'),
+ 1138: ('Oromo', None),
+ 1139: ('Tigrigna', 'Ethiopia'),
+ 1140: ('Guarani', 'Paraguay'),
+ 1141: ('Hawaiian', 'United States'),
+ 1142: ('Latin', None),
+ 1143: ('Somali', None),
+ 1144: ('Yi', None),
+ 1145: ('Papiamentu', None),
+ 1152: ('Uighur', 'China'),
+ 1153: ('Maori', 'New Zealand'),
+ 1279: ('HID', 'Human Interface Device'),
+ 2049: ('Arabic', 'Iraq'),
+ 2052: ('Chinese', "PRC"),
+ 2055: ('German', 'Switzerland'),
+ 2057: ('English', 'United Kingdom'),
+ 2058: ('Spanish', 'Mexico'),
+ 2060: ('French', 'Belgium'),
+ 2064: ('Italian', 'Switzerland'),
+ 2067: ('Dutch', 'Belgium'),
+ 2068: ('Norwegian', 'Nynorsk'),
+ 2070: ('Portuguese', 'Portugal'),
+ 2072: ('Romanian', 'Moldava'),
+ 2073: ('Russian', 'Moldava'),
+ 2074: ('Serbian', 'Latin'),
+ 2077: ('Swedish', 'Finland'),
+ 2080: ('Urdu', 'India'),
+ 2092: ('Azeri', 'Cyrillic'),
+ 2108: ('Gaelic', 'Ireland'),
+ 2110: ('Malay', 'Brunei Darussalam'),
+ 2115: ('Uzbek', 'Cyrillic'),
+ 2117: ('Bengali', 'Bangladesh'),
+ 2118: ('Punjabi', 'Pakistan'),
+ 2128: ('Mongolian', 'Mongolian'),
+ 2129: ('Tibetan', 'Bhutan'),
+ 2137: ('Sindhi', 'Pakistan'),
+ 2143: ('Tamazight', 'Latin'),
+ 2144: ('Kashmiri', None),
+ 2145: ('Nepali', 'India'),
+ 2155: ('Quecha', 'Ecuador'),
+ 2163: ('Tigrigna', 'Eritrea'),
+ 3073: ('Arabic', 'Egypt'),
+ 3076: ('Chinese', 'Hong Kong SAR'),
+ 3079: ('German', 'Austria'),
+ 3081: ('English', 'Australia'),
+ 3082: ('Spanish', 'Spain (Modern Sort)'),
+ 3084: ('French', 'Canada'),
+ 3098: ('Serbian', 'Cyrillic'),
+ 3179: ('Quecha', 'Peru'),
+ 4097: ('Arabic', 'Libya'),
+ 4100: ('Chinese', 'Singapore'),
+ 4103: ('German', 'Luxembourg'),
+ 4105: ('English', 'Canada'),
+ 4106: ('Spanish', 'Guatemala'),
+ 4108: ('French', 'Switzerland'),
+ 4122: ('Croatian', 'Bosnia/Herzegovina'),
+ 5121: ('Arabic', 'Algeria'),
+ 5124: ('Chinese', 'Macao SAR'),
+ 5127: ('German', 'Liechtenstein'),
+ 5129: ('English', 'New Zealand'),
+ 5130: ('Spanish', 'Costa Rica'),
+ 5132: ('French', 'Luxembourg'),
+ 5146: ('Bosnian', 'Bosnia/Herzegovina'),
+ 6145: ('Arabic', 'Morocco'),
+ 6153: ('English', 'Ireland'),
+ 6154: ('Spanish', 'Panama'),
+ 6156: ('French', 'Monaco'),
+ 7169: ('Arabic', 'Tunisia'),
+ 7177: ('English', 'South Africa'),
+ 7178: ('Spanish', 'Dominican Republic'),
+ 7180: ('French', 'West Indies'),
+ 8193: ('Arabic', 'Oman'),
+ 8201: ('English', 'Jamaica'),
+ 8202: ('Spanish', 'Venezuela'),
+ 8204: ('French', 'Reunion'),
+ 9217: ('Arabic', 'Yemen'),
+ 9225: ('English', 'Caribbean'),
+ 9226: ('Spanish', 'Colombia'),
+ 9228: ('French', 'Democratic Rep. of Congo'),
+ 10241: ('Arabic', 'Syria'),
+ 10249: ('English', 'Belize'),
+ 10250: ('Spanish', 'Peru'),
+ 10252: ('French', 'Senegal'),
+ 11265: ('Arabic', 'Jordan'),
+ 11273: ('English', 'Trinidad'),
+ 11274: ('Spanish', 'Argentina'),
+ 11276: ('French', 'Cameroon'),
+ 12289: ('Arabic', 'Lebanon'),
+ 12297: ('English', 'Zimbabwe'),
+ 12298: ('Spanish', 'Ecuador'),
+ 12300: ('French', "Cote d'Ivoire"),
+ 13313: ('Arabic', 'Kuwait'),
+ 13321: ('English', 'Philippines'),
+ 13322: ('Spanish', 'Chile'),
+ 13324: ('French', 'Mali'),
+ 14337: ('Arabic', 'U.A.E.'),
+ 14345: ('English', 'Indonesia'),
+ 14346: ('Spanish', 'Uruguay'),
+ 14348: ('French', 'Morocco'),
+ 15361: ('Arabic', 'Bahrain'),
+ 15369: ('English', 'Hong Kong SAR'),
+ 15370: ('Spanish', 'Paraguay'),
+ 15372: ('French', 'Haiti'),
+ 16385: ('Arabic', 'Qatar'),
+ 16393: ('English', 'India'),
+ 16394: ('Spanish', 'Bolivia'),
+ 17417: ('English', 'Malaysia'),
+ 17418: ('Spanish', 'El Salvador'),
+ 18441: ('English', 'Singapore'),
+ 18442: ('Spanish', 'Honduras'),
+ 19466: ('Spanish', 'Nicaragua'),
+ 20490: ('Spanish', 'Puerto Rico'),
+ 21514: ('Spanish', 'United States'),
+ 22538: ('Spanish', 'Latin America'),
+ 58380: ('French', 'North Africa')
+ }
+
+
+# Test
+if __name__ == '__main__':
+    for k, (v1, v2) in code.iteritems():
+        assert isinstance(k, int)
+        assert isinstance(v1, str)
+        assert isinstance(v2, str) or v2 is None
+# -*- coding: utf-8 -*-
+
+from ctypes import windll, Structure, sizeof, byref
+from ctypes.wintypes import DWORD, WCHAR, WORD, BYTE, LPVOID, POINTER
+import win32api
+import _winreg
+import langcode
+
+VER_NT_WORKSTATION = 1
+VER_SUITE_ENTERPRISE = 0x0002
+VER_SUITE_DATACENTER = 0x0080
+VER_SUITE_PERSONAL = 0x0200
+VER_SUITE_BLADE = 0x0400
+VER_SUITE_STORAGE_SERVER = 0x2000
+VER_SUITE_COMPUTE_SERVER = 0x4000
+VER_SUITE_WH_SERVER = 0x8000
+PROCESSOR_ARCHITECTURE_IA64 = 6
+PROCESSOR_ARCHITECTURE_AMD64 = 9
+SM_TABLETPC = 86
+SM_MEDIACENTER = 87
+SM_STARTER = 88
+SM_SERVERR2 = 89
+
+EDITIONS = {
+    0x06: "%s Business",
+    0x10: "%s Business N",
+    0x12: "%s HPC Edition",
+    0x08: "%s Datacenter (full installation)",
+    0x0C: "%s Datacenter (core installation)",
+    0x27: "%s Datacenter without Hyper-V (core installation)",
+    0x25: "%s Datacenter without Hyper-V (full installation)",
+    0x04: "%s Enterprise",
+    0x46: "%s Enterprise E",
+    0x1B: "%s Enterprise N",
+    0x0A: "%s Enterprise (full installation)",
+    0x0E: "%s Enterprise (core installation)",
+    0x29: "%s Enterprise without Hyper-V (core installation)",
+    0x0F: "%s Enterprise for Itanium-based Systems",
+    0x26: "%s Enterprise without Hyper-V (full installation)",
+    0x02: "%s Home Basic",
+    0x43: "%s Home Basic E",
+    0x05: "%s Home Basic N",
+    0x03: "%s Home Premium",
+    0x44: "%s Home Premium E",
+    0x1A: "%s Home Premium N",
+    0x2A: "Microsoft Hyper-V %s",
+    0x1E: "Windows Essential Business %s Management Server",
+    0x20: "Windows Essential Business %s Messaging Server",
+    0x1F: "Windows Essential Business %s Security Server",
+    0x30: "%s Professional",
+    0x45: "%s Professional E",
+    0x31: "%s Professional N",
+    0x18: "Windows %s for Windows Essential Server Solutions",
+    0x23: "Windows %s without Hyper-V for Windows Essential Server Solutions",
+    0x21: "%s Foundation",
+    0x09: "Windows Small Business %s",
+    0x07: "%s Standard (full installation)",
+    0x0D: "%s Standard (core installation)",
+    0x28: "%s Standard without Hyper-V (core installation)",
+    0x24: "%s Standard without Hyper-V (full installation)",
+    0x0B: "%s Starter",
+    0x42: "%s Starter E",
+    0x2F: "%s Starter N",
+    0x17: "Storage %s Enterprise",
+    0x14: "Storage %s Express",
+    0x15: "Storage %s Standard",
+    0x16: "Storage %s Workgroup",
+    0x00: "%s An unknown product",
+    0x01: "%s Ultimate",
+    0x47: "%s Ultimate E",
+    0x1C: "%s Ultimate N",
+    0x11: "Web %s (full installation)",
+    0x1D: "Web %s (core installation)",
+}
+
+EDITIONS_ = {}
+for k, v in EDITIONS.iteritems():
+    EDITIONS_[k] = v.replace("%s ", "")
+
+GetSystemMetrics = windll.user32.GetSystemMetrics
+
+
+class OSVERSIONINFOEX(Structure):
+    _fields_ = [
+        ('dwOSVersionInfoSize', DWORD),
+        ('dwMajorVersion', DWORD),
+        ('dwMinorVersion', DWORD),
+        ('dwBuildNumber', DWORD),
+        ('dwPlatformId', DWORD),
+        ('szCSDVersion', WCHAR * 128),
+        ('wServicePackMajor', WORD),
+        ('wServicePackMinor', WORD),
+        ('wSuiteMask', WORD),
+        ('wProductType', BYTE),
+        ('wReserved', BYTE),
+    ]
+
+
+class SYSTEM_INFO(Structure):
+    _fields_ = [
+        ('wProcessorArchitecture', WORD),
+        ('wReserved', WORD),
+        ('dwPageSize', DWORD),
+        ('lpMinimumApplicationAddress', LPVOID),
+        ('lpMaximumApplicationAddress', LPVOID),
+        ('dwActiveProcessorMask', POINTER(DWORD)),
+        ('dwNumberOfProcessors', DWORD),
+        ('dwProcessorType', DWORD),
+        ('dwAllocationGranularity', DWORD),
+        ('wProcessorLevel', WORD),
+        ('wProcessorRevision', WORD),
+    ]
+
+
+def GetWindowsVersion():
+    "returns (os_type, edition, SP, arch)"
+    system_info = SYSTEM_INFO()
+    osvi = OSVERSIONINFOEX()
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX)
+    windll.kernel32.GetVersionExW(byref(osvi))
+    try:
+        MyGetSystemInfo = windll.kernel32.GetNativeSystemInfo
+    except AttributeError:
+        MyGetSystemInfo = windll.kernel32.GetSystemInfo
+    MyGetSystemInfo(byref(system_info))
+    name = []
+    major_version = osvi.dwMajorVersion
+    minor_version = osvi.dwMinorVersion
+
+    if major_version == 5:
+        suiteMask = osvi.wSuiteMask
+        if minor_version == 0:
+            name.append("2000")
+            if osvi.wProductType == VER_NT_WORKSTATION:
+                name.append("Professional")
+            else:
+                if suiteMask & VER_SUITE_DATACENTER:
+                    name.append("Datacenter Server")
+                elif suiteMask & VER_SUITE_ENTERPRISE:
+                    name.append("Advanced Server")
+                else:
+                    name.append("Server")
+        elif minor_version == 1:
+            name.append("XP")
+            if GetSystemMetrics(SM_MEDIACENTER):
+                name.append("Media Center Edition")
+            elif GetSystemMetrics(SM_TABLETPC):
+                name.append("Tablet PC Edition")
+            elif GetSystemMetrics(SM_STARTER):
+                name.append("Starter Edition")
+            elif suiteMask & VER_SUITE_PERSONAL:
+                name.append("Home Edition")
+            else:
+                name.append("Professional")
+        elif minor_version == 2:
+            if GetSystemMetrics(SM_SERVERR2):
+                name.append("Server 2003 R2")
+            elif suiteMask == VER_SUITE_STORAGE_SERVER:
+                name.append("Storage Server 2003")
+            elif suiteMask == VER_SUITE_WH_SERVER:
+                name.append("Home Server")
+            elif osvi.wProductType == VER_NT_WORKSTATION:
+                # Windows XP Professional x64 Edition
+                name.extend(["XP", "Professional"])
+            else:
+                name.append("Server 2003")
+            if osvi.wProductType != VER_NT_WORKSTATION:
+                if suiteMask & VER_SUITE_COMPUTE_SERVER:
+                    name.append("Compute Cluster Edition")
+                elif suiteMask & VER_SUITE_DATACENTER:
+                    name.append("Datacenter Edition")
+                elif suiteMask & VER_SUITE_ENTERPRISE:
+                    name.append("Enterprise Edition")
+                elif suiteMask & VER_SUITE_BLADE:
+                    name.append("Web Edition")
+                else:
+                    name.append("Standard Edition")
+    elif major_version == 6:
+        try:
+            os_type = {
+                (0, True): "Vista",
+                (0, False): "Server 2008",
+                (1, True): "7",
+                (1, False): "Server 2008 R2",
+            }[(minor_version, osvi.wProductType == VER_NT_WORKSTATION)]
+        except KeyError:
+            os_type = "Unknown OS 6.%d" % minor_version
+        dwType = DWORD()
+        windll.kernel32.GetProductInfo(
+            major_version, minor_version, 0, 0, byref(dwType)
+        )
+        try:
+            #name = EDITIONS[dwType.value] % os_type
+            name = [os_type, EDITIONS_[dwType.value]]
+        except KeyError:
+            #name = "%s (Unknown Edition %d)" % (os_type, dwType.value)
+            name = [os_type, "(Unknown Edition %d)" % dwType.value]
+
+    if osvi.wServicePackMajor:
+        spname = "SP%d" % osvi.wServicePackMajor
+        if osvi.wServicePackMinor:
+            spname += ".%d" % osvi.wServicePackMinor
+        name.append(spname)
+    else:
+        name.append(None)
+
+    if system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64:
+        name.append("64-bit")
+    elif system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64:
+        name.append("Itanium")
+    else:
+        name.append("32-bit")
+    #name.append("(build %d)" % osvi.dwBuildNumber)
+    #return "Microsoft Windows " + name
+    return tuple(name)
+
+def GetWindowsLanguage():
+    r"""Get OS language from registry.
+    HKLM\SYSTEM\ControlSet001\Control\Nls\Language\InstallLanguage"""
+    hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
+            r'SYSTEM\ControlSet001\Control\Nls\Language')
+    value, type = _winreg.QueryValueEx(hkey, r'InstallLanguage')
+    lang_id = int(value, 16)
+    return id2desc(lang_id)
+
+def GetWindowsLanguage2():
+    """Get windows language settings from control panel.
+    Don't use this to get system language. It may be inacurate."""
+    lang_id = win32api.GetSystemDefaultLangID()
+    return id2desc(lang_id)
+
+def id2desc(id):
+    '''id2desc(id) -> desc
+    '''
+    for k, v in langcode.code.iteritems():
+        if id == k:
+            return v
+    raise IndexError("Description not found for Language ID %d" % id)
+
+def GetWindowsMUI():
+    """Returns a list of installed MUI language packs"""
+    mui_keystr = r'SYSTEM\ControlSet001\Control\MUI\UILanguages'
+    try:
+        hkey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, mui_keystr)
+    except WindowsError:
+        return []
+    i = 0
+    mui_lang_ids = []
+    while True:
+        try:
+            subkey = _winreg.EnumKey(hkey, i)
+            i += 1
+        except WindowsError:
+            break
+        subkeystr = mui_keystr + '\\' + subkey
+        h_muikey = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkeystr)
+        value, type = _winreg.QueryValueEx(h_muikey, 'LCID')
+        mui_lang_ids.append(value)
+    return [id2desc(id) for id in mui_lang_ids]
+
+# Test
+if __name__ == "__main__":
+    print "Windows version:", GetWindowsVersion()
+    print "Installed language:", GetWindowsLanguage()
+    print "System language ID:", GetWindowsLanguage2()
+    mui = GetWindowsMUI()
+    if mui:
+        print "MUI Info:"
+        for (lang, region) in mui:
+            print "%s - %s" % (lang, region)
+
+import re
+import srvdesc
+
+class SDR:
+    def __init__(self, sdr):
+        f = open(sdr)
+        self.sdr = [line.strip() for line in f.readlines()]
+        f.close()
+
+    def get_po(self):
+        "Returns PO number of the SDR if exists."
+        po_ = self.sdr[-1].split(' ')[2]
+        if po_.isdigit(): return po_
+
+    def is_mui(self):
+        "Returns True if is MUI order."
+        return True if len(self.mui_parts()) > 0 else False
+
+    def mui_parts(self):
+        "Returns a list of mui info parts contained in the sdr"
+        muilist = []
+        re_mui = re.compile(r'^INFO ([0-9A-Z]{5}) INFO,XTRA-LANG@V,([A-Z]+)')
+        for s in self.sdr:
+            if s.startswith('INFO'):
+                matchobj = re_mui.match(s)
+                if matchobj:
+                    muilist.append((matchobj.group(1), matchobj.group(2)))
+        return muilist
+
+    def os_srv(self, valid=False):
+        "Returns first 'SI SW' part in the SDR, which should be the OS part."
+        for item in self.sdr:
+            if item.startswith('SI SW'):
+                return item
+        return None
+
+    def has_valid_srv(self):
+        "Checks the srv description, to see if it matches certain format."
+        srvli = srvdesc.srv_desc    # !!! srv_desc may not be acurate
+        for srv, desc in srvli:
+            fulldesc = 'SI SW %s %s' % (srv, desc)
+            if fulldesc in self.os_srv():   # !!! the two may not be equal
+                return True
+        return False
+
+    def os_info(self):
+        "os_info() -> (OS_SRV, OS_TYPE, OS_LANG)"
+        re_xp_sp3 = re.compile(r'SI SW ([0-9A-Z]{5}) SRV,OS,(WXP[HP]SP3),128,([A-Z]+)')
+        re_vista_sp2 = re.compile(r'SI SW ([0-9A-Z]{5}) SRV,OS,(V(?:HB|HP|B|U)(?:32|64)SP2),([A-Z]+)')
+        re_win7 = re.compile(r'SI SW ([0-9A-Z]{5}) SRV,OS,(W7(?:S|HB|HP|P|U)(?:32|64)),([A-Z]+)')
+
+        srv = self.os_srv()
+        for r in (re_win7, re_vista_sp2, re_xp_sp3):
+            matchobj = r.match(srv)
+            if matchobj:
+                return matchobj.groups()
+        raise ValueError("Unable to get OS info from SDR")
+
+    def os_pn(self):
+        return get_sdr_os(self.os_info()[0])
+
+    def os_type(self):
+        return get_sdr_os(self.os_info()[1])
+
+    def os_lang(self):
+        return get_sdr_lang(self.os_info()[2])
+
+lang_list = [('ARA', 'Arabic', []),
+             ('BPOR', 'Portuguese', ['Brazil']),
+             ('BULG', 'Bulgarian', []),
+             ('CRO', 'Crotian', []),
+             ('CZE', 'Czech', []),
+             ('DAN', 'Danish', []),
+             ('DUT', 'Dutch', []),
+             ('ENG', 'English', []),
+             ('FIN', 'Finnish', []),
+             ('FR', 'French', []),
+             ('GER', 'German', []),
+             ('GRE', 'Greek', []),
+             ('HEB', 'Hebrew', []),
+             ('HUN', 'Hungarian', []),
+             ('IPOR', 'Portuguese', ['Portugal']),
+             ('ITL', 'Italian', []),
+             ('JPN', 'Japanese', []),
+             ('KOR', 'Korean', []),
+             ('NOR', 'Norwegian', []),
+             ('NORW', 'Norwegian', []),
+             ('POL', 'Polish', []),
+             ('ROMA', 'Romanian', []),
+             ('RUS', 'Russian', []),
+             ('SCHI', 'Chinese', ['PRC', 'Singapore']),
+             ('SLK', 'Slovak', []),
+             ('SLN', 'Slovenian', []),
+             ('SPN', 'Spanish', []),
+             ('SRB', 'Serbrian', []),
+             ('SWE', 'Swedish', []),
+             ('TCHI', 'Chinese', ['Taiwan']),
+             ('TCHK', 'Chinese', ['Hong Kong SAR']),
+             ('THAI', 'Thai', []),
+             ('TUR', 'Turkish', []),
+             #('MUI,CANADA', 'Canadian MUI', []),
+             #('MUI,EMF,NORDIC', 'Nordic MUI', []),
+             #('MUI,EMF,SWI', 'Swiss MUI', []),
+             #('MUI,EMF,BNLX', 'Benelux MUL', []),
+             #('MUI,EMF,EURC', 'EMEA MUI', [])
+             ]
+
+os_desc_dict = {'WXPPSP3': ('XP', 'Professional', 'SP3', '32-bit'),
+                'WXPHSP3': ('XP', 'Home', 'SP3', '32-bit'),
+                'VHB32SP2': ('Vista', 'Home Basic', 'SP2', '32-bit'),
+                'VHP32SP2': ('Vista', 'Home Premium', 'SP2', '32-bit'),
+                'VB32SP2': ('Vista', 'Business', 'SP2', '32-bit'),
+                'VU32SP2': ('Vista', 'Ultimate', 'SP2', '32-bit'),
+                'VHB64SP2': ('Vista', 'Home Basic', 'SP2', '64-bit'),
+                'VHP64SP2': ('Vista', 'Home Premium', 'SP2', '64-bit'),
+                'VB64SP2': ('Vista', 'Business', 'SP2', '64-bit'),
+                'VU64SP2': ('Vista', 'Ultimate', 'SP2', '64-bit'),
+                'W7S32': ('7', 'Starter', None, '32-bit'),
+                'W7HB32': ('7', 'Home Basic', None, '32-bit'),
+                'W7HP32': ('7', 'Home Premium', None, '32-bit'),
+                'W7P32': ('7', 'Professional', None, '32-bit'),
+                'W7U32': ('7', 'Ultimate', None, '32-bit'),
+                'W7HB64': ('7', 'Home Basic', None, '64-bit'),
+                'W7HP64': ('7', 'Home Premium', None, '64-bit'),
+                'W7P64': ('7', 'Professional', None, '64-bit'),
+                'W7U64': ('7', 'Ultimate', None, '64-bit'),
+                }
+
+def get_sdr_os(desc):
+    "Returns a tuple of OS information according to the SDR"
+    try:
+        return os_desc_dict[desc]
+    except:
+        raise IndexError("Unable to get OS info from SDR")
+
+def get_sdr_lang(desc):
+    "Returns (os, region) tuple for desc"
+    for (s, d, r) in lang_list:
+        if desc == s:
+            return (d, r)
+    raise IndexError("Unable to get language srv info from SDR")
+
+if __name__ == '__main__':
+    for v in os_desc_dict.itervalues():
+        assert(len(v) == 4)
+    for i in lang_list:
+        assert(len(i) == 3)
+        assert(isinstance(i[0], str))
+        assert(isinstance(i[1], str))
+        assert(isinstance(i[2], list))
+        for j in i[2]:
+            assert(isinstance(j, str))
+from cx_Freeze import setup, Executable
+
+setup(
+    name = "check_os",
+    version = "3.0",
+    description = "Checks OS info against SDR",
+    executables = [Executable("check_os.py")],
+    appendScriptToExe = 1,
+    )
+"All OS SRV descriptions"
+
+srv_desc = [('807HW', 'SRV,OS,VB32SP2,ARA'),
+ ('VD1KG', 'SRV,OS,VB32SP2,BPOR'),
+ ('D7JCC', 'SRV,OS,VB32SP2,CZE'),
+ ('5XFD8', 'SRV,OS,VB32SP2,DAN'),
+ ('33R68', 'SRV,OS,VB32SP2,DUT'),
+ ('M033N', 'SRV,OS,VB32SP2,ENG'),
+ ('73PX1', 'SRV,OS,VB32SP2,FIN'),
+ ('P271N', 'SRV,OS,VB32SP2,FR'),
+ ('T259N', 'SRV,OS,VB32SP2,GER'),
+ ('T43VG', 'SRV,OS,VB32SP2,GRE'),
+ ('51MDN', 'SRV,OS,VB32SP2,HEB'),
+ ('3W88X', 'SRV,OS,VB32SP2,HUN'),
+ ('FH3YP', 'SRV,OS,VB32SP2,IPOR'),
+ ('MNC3W', 'SRV,OS,VB32SP2,ITL'),
+ ('J013N', 'SRV,OS,VB32SP2,JPN'),
+ ('DP1XM', 'SRV,OS,VB32SP2,KOR'),
+ ('W2KPP', 'SRV,OS,VB32SP2,NORW'),
+ ('WN1J2', 'SRV,OS,VB32SP2,POL'),
+ ('1P5VD', 'SRV,OS,VB32SP2,RUS'),
+ ('R32MT', 'SRV,OS,VB32SP2,SCHI'),
+ ('N270N', 'SRV,OS,VB32SP2,SPN'),
+ ('194CK', 'SRV,OS,VB32SP2,SWE'),
+ ('MP0N8', 'SRV,OS,VB32SP2,TCHI'),
+ ('68NHW', 'SRV,OS,VB32SP2,TCHK'),
+ ('W52M4', 'SRV,OS,VB32SP2,TUR'),
+ ('C5MK4', 'SRV,OS,VB64SP2,ARA'),
+ ('N5T5M', 'SRV,OS,VB64SP2,BPOR'),
+ ('KXX7Y', 'SRV,OS,VB64SP2,CZE'),
+ ('2YMK9', 'SRV,OS,VB64SP2,DAN'),
+ ('C20F2', 'SRV,OS,VB64SP2,DUT'),
+ ('M035N', 'SRV,OS,VB64SP2,ENG'),
+ ('01GXD', 'SRV,OS,VB64SP2,FIN'),
+ ('P272N', 'SRV,OS,VB64SP2,FR'),
+ ('T260N', 'SRV,OS,VB64SP2,GER'),
+ ('82C7G', 'SRV,OS,VB64SP2,GRE'),
+ ('FYGKG', 'SRV,OS,VB64SP2,HEB'),
+ ('W5XFH', 'SRV,OS,VB64SP2,HUN'),
+ ('C37PC', 'SRV,OS,VB64SP2,IPOR'),
+ ('T0HRX', 'SRV,OS,VB64SP2,ITL'),
+ ('J016N', 'SRV,OS,VB64SP2,JPN'),
+ ('D1M4X', 'SRV,OS,VB64SP2,KOR'),
+ ('9VF3G', 'SRV,OS,VB64SP2,NORW'),
+ ('NM4Y2', 'SRV,OS,VB64SP2,POL'),
+ ('KCWDN', 'SRV,OS,VB64SP2,RUS'),
+ ('17VW7', 'SRV,OS,VB64SP2,SCHI'),
+ ('N271N', 'SRV,OS,VB64SP2,SPN'),
+ ('6VGKP', 'SRV,OS,VB64SP2,SWE'),
+ ('DT5TP', 'SRV,OS,VB64SP2,TCHI'),
+ ('MPV7V', 'SRV,OS,VB64SP2,TCHK'),
+ ('9V48N', 'SRV,OS,VB64SP2,TUR'),
+ ('YXNM5', 'SRV,OS,VHB32SP2,ARA'),
+ ('TG8F1', 'SRV,OS,VHB32SP2,BPOR'),
+ ('91MN0', 'SRV,OS,VHB32SP2,CZE'),
+ ('MY5F6', 'SRV,OS,VHB32SP2,DAN'),
+ ('4K89R', 'SRV,OS,VHB32SP2,DUT'),
+ ('M031N', 'SRV,OS,VHB32SP2,ENG'),
+ ('H88M3', 'SRV,OS,VHB32SP2,FIN'),
+ ('P269N', 'SRV,OS,VHB32SP2,FR'),
+ ('T257N', 'SRV,OS,VHB32SP2,GER'),
+ ('V87CT', 'SRV,OS,VHB32SP2,GRE'),
+ ('C21TG', 'SRV,OS,VHB32SP2,HEB'),
+ ('WPD1K', 'SRV,OS,VHB32SP2,HUN'),
+ ('M9K69', 'SRV,OS,VHB32SP2,IPOR'),
+ ('665Y3', 'SRV,OS,VHB32SP2,ITL'),
+ ('J007N', 'SRV,OS,VHB32SP2,JPN'),
+ ('R2JHC', 'SRV,OS,VHB32SP2,KOR'),
+ ('VH7RM', 'SRV,OS,VHB32SP2,NORW'),
+ ('8V57R', 'SRV,OS,VHB32SP2,POL'),
+ ('HVC63', 'SRV,OS,VHB32SP2,RUS'),
+ ('633HF', 'SRV,OS,VHB32SP2,SCHI'),
+ ('N268N', 'SRV,OS,VHB32SP2,SPN'),
+ ('767JP', 'SRV,OS,VHB32SP2,SWE'),
+ ('F1FT4', 'SRV,OS,VHB32SP2,TCHI'),
+ ('VC518', 'SRV,OS,VHB32SP2,TCHK'),
+ ('7NFPK', 'SRV,OS,VHB32SP2,TUR'),
+ ('V2VVC', 'SRV,OS,VHB64SP2,ARA'),
+ ('0HDFH', 'SRV,OS,VHB64SP2,BPOR'),
+ ('YDHMF', 'SRV,OS,VHB64SP2,CZE'),
+ ('K58VW', 'SRV,OS,VHB64SP2,DAN'),
+ ('F7WGJ', 'SRV,OS,VHB64SP2,DUT'),
+ ('M032N', 'SRV,OS,VHB64SP2,ENG'),
+ ('KDT4P', 'SRV,OS,VHB64SP2,FIN'),
+ ('P270N', 'SRV,OS,VHB64SP2,FR'),
+ ('T258N', 'SRV,OS,VHB64SP2,GER'),
+ ('NDPM6', 'SRV,OS,VHB64SP2,GRE'),
+ ('GX1TX', 'SRV,OS,VHB64SP2,HEB'),
+ ('9493M', 'SRV,OS,VHB64SP2,HUN'),
+ ('59CW9', 'SRV,OS,VHB64SP2,IPOR'),
+ ('M15GD', 'SRV,OS,VHB64SP2,ITL'),
+ ('J012N', 'SRV,OS,VHB64SP2,JPN'),
+ ('PVKRD', 'SRV,OS,VHB64SP2,KOR'),
+ ('2VT59', 'SRV,OS,VHB64SP2,NORW'),
+ ('C3T5G', 'SRV,OS,VHB64SP2,POL'),
+ ('X4PTJ', 'SRV,OS,VHB64SP2,RUS'),
+ ('6D6MC', 'SRV,OS,VHB64SP2,SCHI'),
+ ('N269N', 'SRV,OS,VHB64SP2,SPN'),
+ ('PFXK1', 'SRV,OS,VHB64SP2,SWE'),
+ ('YGP4J', 'SRV,OS,VHB64SP2,TCHI'),
+ ('5RY49', 'SRV,OS,VHB64SP2,TCHK'),
+ ('51V49', 'SRV,OS,VHB64SP2,TUR'),
+ ('TK6YR', 'SRV,OS,VU32SP2,ARA'),
+ ('HRT2N', 'SRV,OS,VU32SP2,BPOR'),
+ ('5NKY4', 'SRV,OS,VU32SP2,CZE'),
+ ('JX1W0', 'SRV,OS,VU32SP2,DAN'),
+ ('5M8X5', 'SRV,OS,VU32SP2,DUT'),
+ ('M038N', 'SRV,OS,VU32SP2,ENG'),
+ ('74GH8', 'SRV,OS,VU32SP2,FIN'),
+ ('P275N', 'SRV,OS,VU32SP2,FR'),
+ ('T263N', 'SRV,OS,VU32SP2,GER'),
+ ('F0TJ2', 'SRV,OS,VU32SP2,GRE'),
+ ('KXW1T', 'SRV,OS,VU32SP2,HEB'),
+ ('72THG', 'SRV,OS,VU32SP2,HUN'),
+ ('594KV', 'SRV,OS,VU32SP2,IPOR'),
+ ('TXWHW', 'SRV,OS,VU32SP2,ITL'),
+ ('J026N', 'SRV,OS,VU32SP2,JPN'),
+ ('67R8C', 'SRV,OS,VU32SP2,KOR'),
+ ('2X68V', 'SRV,OS,VU32SP2,NORW'),
+ ('NXMNN', 'SRV,OS,VU32SP2,POL'),
+ ('TJ2N8', 'SRV,OS,VU32SP2,RUS'),
+ ('G68RJ', 'SRV,OS,VU32SP2,SCHI'),
+ ('N274N', 'SRV,OS,VU32SP2,SPN'),
+ ('5DF9N', 'SRV,OS,VU32SP2,SWE'),
+ ('RK9DF', 'SRV,OS,VU32SP2,TCHI'),
+ ('M8Y56', 'SRV,OS,VU32SP2,TCHK'),
+ ('5634K', 'SRV,OS,VU32SP2,TUR'),
+ ('0253F', 'SRV,OS,W7HB32,ARA'),
+ ('PCY2D', 'SRV,OS,W7HB32,BPOR'),
+ ('XR7RD', 'SRV,OS,W7HB32,BULG'),
+ ('C1FFC', 'SRV,OS,W7HB32,CRO'),
+ ('2V7CJ', 'SRV,OS,W7HB32,CZE'),
+ ('N4WXD', 'SRV,OS,W7HB32,DAN'),
+ ('C57C2', 'SRV,OS,W7HB32,DUT'),
+ ('68N7K', 'SRV,OS,W7HB32,ENG'),
+ ('C0DX1', 'SRV,OS,W7HB32,FIN'),
+ ('0MV9V', 'SRV,OS,W7HB32,FR'),
+ ('TTVF0', 'SRV,OS,W7HB32,GER'),
+ ('88CH0', 'SRV,OS,W7HB32,GRE'),
+ ('WCNX4', 'SRV,OS,W7HB32,HEB'),
+ ('G9KWC', 'SRV,OS,W7HB32,HUN'),
+ ('GD0RJ', 'SRV,OS,W7HB32,IPOR'),
+ ('4659V', 'SRV,OS,W7HB32,ITL'),
+ ('JW6T2', 'SRV,OS,W7HB32,JPN'),
+ ('0WF9V', 'SRV,OS,W7HB32,KOR'),
+ ('5M74W', 'SRV,OS,W7HB32,NORW'),
+ ('N8HD3', 'SRV,OS,W7HB32,POL'),
+ ('7YNXD', 'SRV,OS,W7HB32,ROMA'),
+ ('2K8P1', 'SRV,OS,W7HB32,RUS'),
+ ('D94P2', 'SRV,OS,W7HB32,SCHI'),
+ ('46RMR', 'SRV,OS,W7HB32,SLK'),
+ ('HDH7P', 'SRV,OS,W7HB32,SLN'),
+ ('FWH47', 'SRV,OS,W7HB32,SPN'),
+ ('JNY93', 'SRV,OS,W7HB32,SRB'),
+ ('GJHG4', 'SRV,OS,W7HB32,SWE'),
+ ('51K3T', 'SRV,OS,W7HB32,TCHI'),
+ ('0RJ54', 'SRV,OS,W7HB32,TCHK'),
+ ('4JR3C', 'SRV,OS,W7HB32,THAI'),
+ ('VXF92', 'SRV,OS,W7HB32,TUR'),
+ ('DMH9P', 'SRV,OS,W7HB64,ARA'),
+ ('7NM2C', 'SRV,OS,W7HB64,BPOR'),
+ ('WV2TH', 'SRV,OS,W7HB64,BULG'),
+ ('16RC5', 'SRV,OS,W7HB64,CRO'),
+ ('4VGFC', 'SRV,OS,W7HB64,CZE'),
+ ('39808', 'SRV,OS,W7HB64,DAN'),
+ ('F108X', 'SRV,OS,W7HB64,DUT'),
+ ('GH36N', 'SRV,OS,W7HB64,ENG'),
+ ('G28XN', 'SRV,OS,W7HB64,FIN'),
+ ('NP5NK', 'SRV,OS,W7HB64,FR'),
+ ('H7GVK', 'SRV,OS,W7HB64,GER'),
+ ('34G55', 'SRV,OS,W7HB64,GRE'),
+ ('F26PW', 'SRV,OS,W7HB64,HEB'),
+ ('V73HG', 'SRV,OS,W7HB64,HUN'),
+ ('RX8YM', 'SRV,OS,W7HB64,IPOR'),
+ ('4TND1', 'SRV,OS,W7HB64,ITL'),
+ ('C4GNH', 'SRV,OS,W7HB64,JPN'),
+ ('79J5W', 'SRV,OS,W7HB64,KOR'),
+ ('XVWJG', 'SRV,OS,W7HB64,NORW'),
+ ('TKGDV', 'SRV,OS,W7HB64,POL'),
+ ('97XTY', 'SRV,OS,W7HB64,ROMA'),
+ ('HW21M', 'SRV,OS,W7HB64,RUS'),
+ ('R0W0M', 'SRV,OS,W7HB64,SCHI'),
+ ('Y5KGM', 'SRV,OS,W7HB64,SLK'),
+ ('76VR9', 'SRV,OS,W7HB64,SLN'),
+ ('KJ95W', 'SRV,OS,W7HB64,SPN'),
+ ('3TFHX', 'SRV,OS,W7HB64,SRB'),
+ ('2YCPG', 'SRV,OS,W7HB64,SWE'),
+ ('JMNKN', 'SRV,OS,W7HB64,TCHI'),
+ ('8VHDT', 'SRV,OS,W7HB64,TCHK'),
+ ('0KY4Y', 'SRV,OS,W7HB64,THAI'),
+ ('F15YN', 'SRV,OS,W7HB64,TUR'),
+ ('0MTNY', 'SRV,OS,W7HP32,ARA'),
+ ('77V0C', 'SRV,OS,W7HP32,BPOR'),
+ ('FRXV6', 'SRV,OS,W7HP32,BULG'),
+ ('GT6NT', 'SRV,OS,W7HP32,CRO'),
+ ('JHWX4', 'SRV,OS,W7HP32,CZE'),
+ ('VYCYW', 'SRV,OS,W7HP32,DAN'),
+ ('GND7N', 'SRV,OS,W7HP32,DUT'),
+ ('WD3F1', 'SRV,OS,W7HP32,ENG'),
+ ('4XHCT', 'SRV,OS,W7HP32,FIN'),
+ ('60FXP', 'SRV,OS,W7HP32,FR'),
+ ('W5HR3', 'SRV,OS,W7HP32,GER'),
+ ('P92YP', 'SRV,OS,W7HP32,GRE'),
+ ('78X66', 'SRV,OS,W7HP32,HEB'),
+ ('G8J4K', 'SRV,OS,W7HP32,HUN'),
+ ('WCPX7', 'SRV,OS,W7HP32,IPOR'),
+ ('19D30', 'SRV,OS,W7HP32,ITL'),
+ ('VWC0C', 'SRV,OS,W7HP32,JPN'),
+ ('R92C4', 'SRV,OS,W7HP32,KOR'),
+ ('F0Y9W', 'SRV,OS,W7HP32,NORW'),
+ ('51FMV', 'SRV,OS,W7HP32,POL'),
+ ('JW0RX', 'SRV,OS,W7HP32,ROMA'),
+ ('G5C49', 'SRV,OS,W7HP32,RUS'),
+ ('55D10', 'SRV,OS,W7HP32,SCHI'),
+ ('RFTW3', 'SRV,OS,W7HP32,SLK'),
+ ('2DCNC', 'SRV,OS,W7HP32,SLN'),
+ ('8HXX9', 'SRV,OS,W7HP32,SPN'),
+ ('4X7P1', 'SRV,OS,W7HP32,SRB'),
+ ('YK18T', 'SRV,OS,W7HP32,SWE'),
+ ('1R7R6', 'SRV,OS,W7HP32,TCHI'),
+ ('RHMR7', 'SRV,OS,W7HP32,TCHK'),
+ ('41WR8', 'SRV,OS,W7HP32,THAI'),
+ ('Y74FR', 'SRV,OS,W7HP32,TUR'),
+ ('5KGKD', 'SRV,OS,W7HP64,ARA'),
+ ('37P7K', 'SRV,OS,W7HP64,BPOR'),
+ ('2XYM3', 'SRV,OS,W7HP64,BULG'),
+ ('849WX', 'SRV,OS,W7HP64,CRO'),
+ ('X54X1', 'SRV,OS,W7HP64,CZE'),
+ ('C1VW7', 'SRV,OS,W7HP64,DAN'),
+ ('JWFHP', 'SRV,OS,W7HP64,DUT'),
+ ('MMJKH', 'SRV,OS,W7HP64,ENG'),
+ ('4PCT0', 'SRV,OS,W7HP64,FIN'),
+ ('14DF5', 'SRV,OS,W7HP64,FR'),
+ ('3J0DF', 'SRV,OS,W7HP64,GER'),
+ ('P0F1M', 'SRV,OS,W7HP64,GRE'),
+ ('D5MTJ', 'SRV,OS,W7HP64,HEB'),
+ ('HKM13', 'SRV,OS,W7HP64,HUN'),
+ ('FJ6JF', 'SRV,OS,W7HP64,IPOR'),
+ ('KXVTK', 'SRV,OS,W7HP64,ITL'),
+ ('RWGN6', 'SRV,OS,W7HP64,JPN'),
+ ('4VFTD', 'SRV,OS,W7HP64,KOR'),
+ ('WYJPW', 'SRV,OS,W7HP64,NORW'),
+ ('C05N9', 'SRV,OS,W7HP64,POL'),
+ ('3K9HV', 'SRV,OS,W7HP64,ROMA'),
+ ('MH4XF', 'SRV,OS,W7HP64,RUS'),
+ ('VCF09', 'SRV,OS,W7HP64,SCHI'),
+ ('H42KY', 'SRV,OS,W7HP64,SLK'),
+ ('45DMK', 'SRV,OS,W7HP64,SLN'),
+ ('XDXC2', 'SRV,OS,W7HP64,SPN'),
+ ('WG7DM', 'SRV,OS,W7HP64,SRB'),
+ ('2DNFY', 'SRV,OS,W7HP64,SWE'),
+ ('ND2NK', 'SRV,OS,W7HP64,TCHI'),
+ ('2C2D8', 'SRV,OS,W7HP64,TCHK'),
+ ('XKC0F', 'SRV,OS,W7HP64,THAI'),
+ ('HTMK0', 'SRV,OS,W7HP64,TUR'),
+ ('6FR0N', 'SRV,OS,W7HP64,MUI,CANADA'),
+ ('969N3', 'SRV,OS,W7HP64,MUI,EMF,NORDIC'),
+ ('67P26', 'SRV,OS,W7HP64,MUI,EMF,SWI'),
+ ('MPPDV', 'SRV,OS,W7HP64,MUI,EMF,BNLX'),
+ ('60N7M', 'SRV,OS,W7HP64,MUI,EMF,EURC'),
+ ('296HR', 'SRV,OS,W7P32,ARA'),
+ ('KPFJN', 'SRV,OS,W7P32,BPOR'),
+ ('9WCVP', 'SRV,OS,W7P32,BULG'),
+ ('VT6PY', 'SRV,OS,W7P32,CRO'),
+ ('HGJNX', 'SRV,OS,W7P32,CZE'),
+ ('PHPC0', 'SRV,OS,W7P32,DAN'),
+ ('96M5K', 'SRV,OS,W7P32,DUT'),
+ ('5YWDT', 'SRV,OS,W7P32,ENG'),
+ ('0W8RM', 'SRV,OS,W7P32,FIN'),
+ ('6KFFP', 'SRV,OS,W7P32,FR'),
+ ('XF7W5', 'SRV,OS,W7P32,GER'),
+ ('21TKM', 'SRV,OS,W7P32,GRE'),
+ ('ND8H6', 'SRV,OS,W7P32,HEB'),
+ ('X8WNH', 'SRV,OS,W7P32,HUN'),
+ ('YW38C', 'SRV,OS,W7P32,IPOR'),
+ ('DFY3D', 'SRV,OS,W7P32,ITL'),
+ ('53V8X', 'SRV,OS,W7P32,JPN'),
+ ('3XD6G', 'SRV,OS,W7P32,KOR'),
+ ('R0WDR', 'SRV,OS,W7P32,NORW'),
+ ('N3HXN', 'SRV,OS,W7P32,POL'),
+ ('PCJFC', 'SRV,OS,W7P32,ROMA'),
+ ('79HXF', 'SRV,OS,W7P32,RUS'),
+ ('Y4YVV', 'SRV,OS,W7P32,SCHI'),
+ ('Y3VPF', 'SRV,OS,W7P32,SLK'),
+ ('771M9', 'SRV,OS,W7P32,SLN'),
+ ('4025V', 'SRV,OS,W7P32,SPN'),
+ ('G0RVH', 'SRV,OS,W7P32,SRB'),
+ ('13NV1', 'SRV,OS,W7P32,SWE'),
+ ('MVN05', 'SRV,OS,W7P32,TCHI'),
+ ('CRFYG', 'SRV,OS,W7P32,TCHK'),
+ ('88T2D', 'SRV,OS,W7P32,THAI'),
+ ('FJJ3X', 'SRV,OS,W7P32,TUR'),
+ ('JW2RK', 'SRV,OS,W7P32,MUI,CANADA'),
+ ('CMYN3', 'SRV,OS,W7P32,MUI,NORDIC'),
+ ('CNMX0', 'SRV,OS,W7P32,MUI,EMF,SWI'),
+ ('X7FJ2', 'SRV,OS,W7P32,MUI,BNLX'),
+ ('KY7H2', 'SRV,OS,W7P32,MUI,EURC'),
+ ('46HMJ', 'SRV,OS,W7P64,ARA'),
+ ('CVWJV', 'SRV,OS,W7P64,BPOR'),
+ ('4FRDD', 'SRV,OS,W7P64,BULG'),
+ ('N685Y', 'SRV,OS,W7P64,CRO'),
+ ('4CTNP', 'SRV,OS,W7P64,CZE'),
+ ('3NMTH', 'SRV,OS,W7P64,DAN'),
+ ('V1V64', 'SRV,OS,W7P64,DUT'),
+ ('7G98V', 'SRV,OS,W7P64,ENG'),
+ ('RRF23', 'SRV,OS,W7P64,FIN'),
+ ('488H0', 'SRV,OS,W7P64,FR'),
+ ('VWY3P', 'SRV,OS,W7P64,GER'),
+ ('VWF80', 'SRV,OS,W7P64,GRE'),
+ ('HM73F', 'SRV,OS,W7P64,HEB'),
+ ('R12M8', 'SRV,OS,W7P64,HUN'),
+ ('FG7P9', 'SRV,OS,W7P64,IPOR'),
+ ('MYRY9', 'SRV,OS,W7P64,ITL'),
+ ('DV4FG', 'SRV,OS,W7P64,JPN'),
+ ('YVRHM', 'SRV,OS,W7P64,KOR'),
+ ('05RX4', 'SRV,OS,W7P64,NORW'),
+ ('G27J3', 'SRV,OS,W7P64,POL'),
+ ('FGPXK', 'SRV,OS,W7P64,ROMA'),
+ ('9T7X4', 'SRV,OS,W7P64,RUS'),
+ ('T33YG', 'SRV,OS,W7P64,SCHI'),
+ ('RP65J', 'SRV,OS,W7P64,SLK'),
+ ('THGGX', 'SRV,OS,W7P64,SLN'),
+ ('3HH84', 'SRV,OS,W7P64,SPN'),
+ ('CCGJ0', 'SRV,OS,W7P64,SRB'),
+ ('M5H9J', 'SRV,OS,W7P64,SWE'),
+ ('5635H', 'SRV,OS,W7P64,TCHI'),
+ ('JVKT2', 'SRV,OS,W7P64,TCHK'),
+ ('4YGW9', 'SRV,OS,W7P64,THAI'),
+ ('DYFX1', 'SRV,OS,W7P64,TUR'),
+ ('RCNGN', 'SRV,OS,W7P64,MUI,CANADA'),
+ ('7WK0K', 'SRV,OS,W7P64,MUI,NORDIC'),
+ ('R3GPN', 'SRV,OS,W7P64,MUI,EMF,SWI'),
+ ('WMMJ1', 'SRV,OS,W7P64,MUI,BNLX'),
+ ('JYH2M', 'SRV,OS,W7P64,MUI,EURC'),
+ ('13M16', 'SRV,OS,W7S32,ARA'),
+ ('86VY5', 'SRV,OS,W7S32,BPOR'),
+ ('W1PHT', 'SRV,OS,W7S32,BULG'),
+ ('0GX1P', 'SRV,OS,W7S32,CRO'),
+ ('JGJY2', 'SRV,OS,W7S32,CZE'),
+ ('5YKF2', 'SRV,OS,W7S32,DAN'),
+ ('R59H5', 'SRV,OS,W7S32,DUT'),
+ ('M9D2X', 'SRV,OS,W7S32,ENG'),
+ ('JF3HK', 'SRV,OS,W7S32,FIN'),
+ ('V71XV', 'SRV,OS,W7S32,FR'),
+ ('NFVH8', 'SRV,OS,W7S32,GER'),
+ ('R4FC1', 'SRV,OS,W7S32,GRE'),
+ ('VYGKH', 'SRV,OS,W7S32,HEB'),
+ ('HMT0P', 'SRV,OS,W7S32,HUN'),
+ ('20CMP', 'SRV,OS,W7S32,IPOR'),
+ ('6R5J6', 'SRV,OS,W7S32,ITL'),
+ ('YXCXD', 'SRV,OS,W7S32,JPN'),
+ ('648GV', 'SRV,OS,W7S32,KOR'),
+ ('39MD4', 'SRV,OS,W7S32,NORW'),
+ ('H9NR2', 'SRV,OS,W7S32,POL'),
+ ('7CMRX', 'SRV,OS,W7S32,ROMA'),
+ ('R4WM4', 'SRV,OS,W7S32,RUS'),
+ ('Y8D25', 'SRV,OS,W7S32,SCHI'),
+ ('18R7N', 'SRV,OS,W7S32,SLK'),
+ ('5M61D', 'SRV,OS,W7S32,SLN'),
+ ('PPCYW', 'SRV,OS,W7S32,SPN'),
+ ('WC2N0', 'SRV,OS,W7S32,SRB'),
+ ('6V8NM', 'SRV,OS,W7S32,SWE'),
+ ('C76CM', 'SRV,OS,W7S32,TCHI'),
+ ('PFVR8', 'SRV,OS,W7S32,TCHK'),
+ ('F6YHM', 'SRV,OS,W7S32,THAI'),
+ ('62KFF', 'SRV,OS,W7S32,TUR'),
+ ('N277J', 'SRV,OS,W7U32,ARA'),
+ ('N278J', 'SRV,OS,W7U32,BPOR'),
+ ('H2J8V', 'SRV,OS,W7U32,BULG'),
+ ('N279J', 'SRV,OS,W7U32,CRO'),
+ ('N280J', 'SRV,OS,W7U32,CZE'),
+ ('N281J', 'SRV,OS,W7U32,DAN'),
+ ('N282J', 'SRV,OS,W7U32,DUT'),
+ ('N283J', 'SRV,OS,W7U32,ENG'),
+ ('N284J', 'SRV,OS,W7U32,FIN'),
+ ('N285J', 'SRV,OS,W7U32,FR'),
+ ('N286J', 'SRV,OS,W7U32,GER'),
+ ('N287J', 'SRV,OS,W7U32,GRE'),
+ ('N288J', 'SRV,OS,W7U32,HEB'),
+ ('N289J', 'SRV,OS,W7U32,HUN'),
+ ('N290J', 'SRV,OS,W7U32,IPOR'),
+ ('N291J', 'SRV,OS,W7U32,ITL'),
+ ('N292J', 'SRV,OS,W7U32,JPN'),
+ ('N293J', 'SRV,OS,W7U32,KOR'),
+ ('N294J', 'SRV,OS,W7U32,NORW'),
+ ('N295J', 'SRV,OS,W7U32,POL'),
+ ('N296J', 'SRV,OS,W7U32,ROMA'),
+ ('N297J', 'SRV,OS,W7U32,RUS'),
+ ('N298J', 'SRV,OS,W7U32,SCHI'),
+ ('N299J', 'SRV,OS,W7U32,SLK'),
+ ('N300J', 'SRV,OS,W7U32,SLN'),
+ ('N301J', 'SRV,OS,W7U32,SPN'),
+ ('CKXCV', 'SRV,OS,W7U32,SRB'),
+ ('N302J', 'SRV,OS,W7U32,SWE'),
+ ('N303J', 'SRV,OS,W7U32,TCHI'),
+ ('N305J', 'SRV,OS,W7U32,TCHK'),
+ ('N306J', 'SRV,OS,W7U32,THAI'),
+ ('N307J', 'SRV,OS,W7U32,TUR'),
+ ('NDFGM', 'SRV,OS,W7U64,ARA'),
+ ('N3YVK', 'SRV,OS,W7U64,BPOR'),
+ ('YF7DM', 'SRV,OS,W7U64,BULG.E'),
+ ('T1VNV', 'SRV,OS,W7U64,CRO'),
+ ('TJXG7', 'SRV,OS,W7U64,CZE'),
+ ('9PFNW', 'SRV,OS,W7U64,DAN'),
+ ('NY9XF', 'SRV,OS,W7U64,DUT'),
+ ('J8WR2', 'SRV,OS,W7U64,ENG'),
+ ('60TTM', 'SRV,OS,W7U64,FIN'),
+ ('4PTPX', 'SRV,OS,W7U64,FR'),
+ ('9XT77', 'SRV,OS,W7U64,GER'),
+ ('70GYH', 'SRV,OS,W7U64,GRE'),
+ ('5V7FW', 'SRV,OS,W7U64,HEB'),
+ ('R5P08', 'SRV,OS,W7U64,HUN'),
+ ('PRJ8G', 'SRV,OS,W7U64,IPOR'),
+ ('515VY', 'SRV,OS,W7U64,ITL'),
+ ('PHG3R', 'SRV,OS,W7U64,JPN'),
+ ('P40GY', 'SRV,OS,W7U64,KOR'),
+ ('0F1D6', 'SRV,OS,W7U64,NORW'),
+ ('387V5', 'SRV,OS,W7U64,POL'),
+ ('0FMT9', 'SRV,OS,W7U64,ROMA'),
+ ('29XG4', 'SRV,OS,W7U64,RUS'),
+ ('5GM8N', 'SRV,OS,W7U64,SCHI'),
+ ('P4DKH', 'SRV,OS,W7U64,SLK'),
+ ('3PFP2', 'SRV,OS,W7U64,SLN'),
+ ('K9DD5', 'SRV,OS,W7U64,SPN'),
+ ('JF1V6', 'SRV,OS,W7U64,SRB'),
+ ('GMG1R', 'SRV,OS,W7U64,SWE'),
+ ('WCY35', 'SRV,OS,W7U64,TCHI'),
+ ('5R0CP', 'SRV,OS,W7U64,TCHK'),
+ ('2X2CP', 'SRV,OS,W7U64,THAI'),
+ ('PP2GJ', 'SRV,OS,W7U64,TUR'),
+ ('YU425', 'SRV,OS,WXPHSP3,128,ENG'),
+ ('YU426', 'SRV,OS,WXPHSP3,128,GER'),
+ ('YU427', 'SRV,OS,WXPHSP3,128,JPN'),
+ ('YU428', 'SRV,OS,WXPHSP3,128,ARA'),
+ ('YU429', 'SRV,OS,WXPHSP3,128,BPOR'),
+ ('YU430', 'SRV,OS,WXPHSP3,128,CZE'),
+ ('YU431', 'SRV,OS,WXPHSP3,128,DAN'),
+ ('YU432', 'SRV,OS,WXPHSP3,128,DUT'),
+ ('YU436', 'SRV,OS,WXPHSP3,128,FIN'),
+ ('YU439', 'SRV,OS,WXPHSP3,128,FR'),
+ ('YU440', 'SRV,OS,WXPHSP3,128,GRE'),
+ ('YU441', 'SRV,OS,WXPHSP3,128,HEB'),
+ ('YU442', 'SRV,OS,WXPHSP3,128,HUN'),
+ ('YU443', 'SRV,OS,WXPHSP3,128,IPOR'),
+ ('YU444', 'SRV,OS,WXPHSP3,128,ITL'),
+ ('YU445', 'SRV,OS,WXPHSP3,128,KOR'),
+ ('YU446', 'SRV,OS,WXPHSP3,128,NOR'),
+ ('YU447', 'SRV,OS,WXPHSP3,128,POL'),
+ ('YU448', 'SRV,OS,WXPHSP3,128,RUS'),
+ ('YU449', 'SRV,OS,WXPHSP3,128,SCHI'),
+ ('YU450', 'SRV,OS,WXPHSP3,128,SPN'),
+ ('YU451', 'SRV,OS,WXPHSP3,128,SWE'),
+ ('YU452', 'SRV,OS,WXPHSP3,128,TCHI'),
+ ('YU453', 'SRV,OS,WXPHSP3,128,TCHK'),
+ ('YU454', 'SRV,OS,WXPHSP3,128,TUR'),
+ ('PP316', 'SRV,OS,WXPPSP3,128,ENG'),
+ ('PP326', 'SRV,OS,WXPPSP3,128,BPOR'),
+ ('PP331', 'SRV,OS,WXPPSP3,128,FR'),
+ ('PP342', 'SRV,OS,WXPPSP3,128,SPN'),
+ ('PP317', 'SRV,OS,WXPPSP3,128,GER'),
+ ('PP318', 'SRV,OS,WXPPSP3,128,JPN'),
+ ('PP341', 'SRV,OS,WXPPSP3,128,SCHI'),
+ ('PP344', 'SRV,OS,WXPPSP3,128,TCHI'),
+ ('PP325', 'SRV,OS,WXPPSP3,128,ARA'),
+ ('PP327', 'SRV,OS,WXPPSP3,128,CZE'),
+ ('PP328', 'SRV,OS,WXPPSP3,128,DAN'),
+ ('PP329', 'SRV,OS,WXPPSP3,128,DUT'),
+ ('PP330', 'SRV,OS,WXPPSP3,128,FIN'),
+ ('PP332', 'SRV,OS,WXPPSP3,128,GRE'),
+ ('PP333', 'SRV,OS,WXPPSP3,128,HEB'),
+ ('PP334', 'SRV,OS,WXPPSP3,128,HUN'),
+ ('PP335', 'SRV,OS,WXPPSP3,128,IPOR'),
+ ('PP336', 'SRV,OS,WXPPSP3,128,ITL'),
+ ('PP338', 'SRV,OS,WXPPSP3,128,NOR'),
+ ('PP339', 'SRV,OS,WXPPSP3,128,POL'),
+ ('PP340', 'SRV,OS,WXPPSP3,128,RUS'),
+ ('PP343', 'SRV,OS,WXPPSP3,128,SWE'),
+ ('PP346', 'SRV,OS,WXPPSP3,128,TUR'),
+ ('PP337', 'SRV,OS,WXPPSP3,128,KOR'),
+ ('PP345', 'SRV,OS,WXPPSP3,128,TCHK')]
+
+
+# Test
+if __name__ == '__main__':
+    for (srv, desc) in srv_desc:
+        assert isinstance(srv, str)
+        assert isinstance(desc, str)