diff --git a/res/localization/rufus.loc b/res/localization/rufus.loc
new file mode 100644
index 00000000..fb1edfa8
--- /dev/null
+++ b/res/localization/rufus.loc
@@ -0,0 +1,690 @@
+# This file should be saved as UTF-8, no-BOM
+
+################################################################################
+l "en_US" "English (US)" 0x0409, 0x0809, 0x0c09, 0x1009, 0x1409, 0x1809, 0x1c09, 0x2009, 0x2409, 0x2809, 0x2c09, 0x3009, 0x3409, 0x3809, 0x3c09, 0x4009, 0x4409, 0x4809
+g IDD_MESSAGES
+t MSG_001 "Other instance detected"
+t MSG_002 "Another Rufus application is running.\n"
+ "Please close the first application before running another one."
+t MSG_003 "WARNING: ALL DATA ON DEVICE '%s' WILL BE DESTROYED.\n"
+ "To continue with this operation, click OK. To quit click CANCEL."
+t MSG_004 "Rufus update policy"
+t MSG_005 "Do you want to allow Rufus to check for application updates online?"
+t MSG_006 "Close" # Must be the same as IDD_DIALOG:IDCANCEL (i.e. "Close" - I know it's confusing)
+t MSG_007 "Cancel"
+t MSG_008 "Yes"
+t MSG_009 "No"
+t MSG_010 "Bad blocks found"
+t MSG_011 "Check completed: %u bad block(s) found\n"
+ " %d read error(s)\n %d write error(s)\n %d corruption error(s)\n"
+# The following will contain the formatted message above as well as the name of the bad blocks logfile
+t MSG_012 "%s\nA more detailed report can be found in:\n%s"
+t MSG_013 "Disabled"
+t MSG_014 "Daily"
+t MSG_015 "Weekly"
+t MSG_016 "Monthly"
+t MSG_017 "Custom"
+t MSG_018 "Your version: %d.%d.%d (Build %d)"
+t MSG_019 "Latest version: %d.%d.%d (Build %d)"
+# *Short* size names. These can be used as suffixes
+t MSG_020 "bytes"
+t MSG_021 "KB"
+t MSG_022 "MB"
+t MSG_023 "GB"
+t MSG_024 "TB"
+t MSG_025 "PB"
+# *Long* size names, as they are displayed for the cluster size in the MS format dialog.
+t MSG_026 "bytes" # Yes, this is a repeat from MSG_020
+t MSG_027 "kilobytes"
+t MSG_028 "megabytes"
+t MSG_029 "Default"
+# The following gets appended to the file system, cluster size, etc.
+t MSG_030 "%s (Default)"
+t MSG_031 "%s partition scheme for BIOS computer"
+t MSG_032 "%s partition scheme for UEFI computer"
+t MSG_033 "%s partition scheme for BIOS or UEFI computers"
+# Number of bad block check passes (singular for 1 pass, plural for 2 or more passes)
+t MSG_034 "%d Pass"
+t MSG_035 "%d Passes"
+t MSG_036 "ISO Image"
+t MSG_037 "Application"
+t MSG_038 "Abort"
+t MSG_039 "Launch"
+t MSG_040 "Download"
+t MSG_041 "Operation cancelled by the user"
+t MSG_042 "Error"
+t MSG_043 "Error: %s"
+t MSG_044 "File download"
+t MSG_045 "USB Storage Device (Generic)"
+t MSG_046 "%s (Disk %d)"
+t MSG_047 "%s (%c:)"
+t MSG_048 "Rufus - Flushing buffers"
+t MSG_049 "Rufus - Cancellation"
+
+# Error messages
+t MSG_050 "Success."
+t MSG_051 "Undetermined error while formatting."
+t MSG_052 "Cannot use the selected file system for this media."
+t MSG_053 "Access to the device is denied."
+t MSG_054 "Media is write protected."
+t MSG_055 "The device is in use by another process. "
+ "Please close any other process that may be accessing the device."
+t MSG_056 "Quick format is not available for this device."
+t MSG_057 "The volume label is invalid."
+t MSG_058 "The device handle is invalid."
+t MSG_059 "The selected cluster size is not valid for this device."
+t MSG_060 "The volume size is invalid."
+t MSG_061 "Please insert a media in drive."
+t MSG_062 "An unsupported command was received."
+t MSG_063 "Memory allocation error."
+t MSG_064 "Read error."
+t MSG_065 "Write error."
+t MSG_066 "Installation failure"
+t MSG_067 "Could not open media. It may be in use by another process. "
+ "Please re-plug the media and try again."
+t MSG_068 "Error while partitioning drive."
+t MSG_069 "Could not copy files to target drive."
+t MSG_070 "Cancelled by user."
+t MSG_071 "Unable to create formatting thread."
+t MSG_072 "Bad blocks check didn't complete."
+t MSG_073 "ISO image scan failure."
+t MSG_074 "ISO image extraction failure."
+t MSG_075 "Unable to remount volume."
+t MSG_076 "Unable to patch/setup files for boot."
+t MSG_077 "Unable to assign a drive letter."
+t MSG_078 "Can't mount GUID volume."
+
+t MSG_080 "Rufus detected that Windows is still flushing its internal buffers onto the USB device.\n\n"
+ "Depending on the speed of your USB device, this operation may take a long time to complete, "
+ "especially for large files.\n\nWe recommend that you let Windows finish, to avoid corruption. "
+ "But if you grow tired of waiting, you can just unplug the device..."
+t MSG_081 "Unsupported ISO"
+t MSG_082 "This version of Rufus only supports bootable ISOs based on bootmgr/WinPE, isolinux or EFI.\n"
+ "This ISO doesn't appear to use either..."
+t MSG_083 "Replace %s?"
+t MSG_084 "This ISO image seems to use an obsolete version of '%s'.\n"
+ "Boot menus may not display properly because of this.\n\n"
+ "A newer version can be downloaded by Rufus to fix this issue:\n"
+ "- Choose 'Yes' to connect to the internet and download the file\n"
+ "- Choose 'No' to leave the existing ISO file unmodified\n"
+ "If you don't know what to do, you should select 'Yes'.\n\n"
+ "Note: The new file will be downloaded in the current directory and once a "
+ "'%s' exists there, it will be reused automatically."
+t MSG_085 "Downloading %s"
+t MSG_086 "No ISO image selected"
+# The content between the quotes below (\"Create a bootable disk\") should match
+# the beginning of the IDC_BOOT text
+t MSG_087 "Please click on the disc button to select a bootable ISO, "
+ "or uncheck the \"Create a bootable disk...\" checkbox."
+t MSG_088 "ISO too big"
+t MSG_089 "This ISO image is too big for the selected target."
+t MSG_090 "Unsupported ISO"
+t MSG_091 "When using UEFI Target Type, only EFI bootable ISO images are supported. "
+ "Please select an EFI bootable ISO or set the Target Type to BIOS."
+t MSG_092 "Unsupported filesystem"
+t MSG_093 "When using UEFI Target Type, only FAT/FAT32 is supported. "
+ "Please select FAT/FAT32 as the File system or set the Target Type to BIOS."
+t MSG_094 "Non UEFI compatible ISO"
+t MSG_095 "This ISO image contains a file larger than 4 GB and cannot be used to create an EFI bootable USB.\n"
+ "This is a limitation of UEFI/FAT32, not Rufus."
+t MSG_096 "Only FAT/FAT32 is supported for this type of ISO. Please select FAT/FAT32 as the File system."
+t MSG_097 "Only 'bootmgr' or 'WinPE' based ISO images can currently be used with NTFS."
+t MSG_098 "FAT/FAT32 can only be used for isolinux based ISO images or when the Target Type is UEFI."
+t MSG_099 "Filesystem limitation"
+t MSG_100 "This iso image contains a file larger than 4GB file, which is more than the "
+ "maximum size allowed for a FAT or FAT32 file system."
+t MSG_101 "Missing WIM support"
+t MSG_102 "Your platform cannot extract files from WIM archives. WIM extraction "
+ "is required to create EFI bootable Windows 7 and Windows Vista USB drives. You can fix that "
+ "by installing a recent version of 7-Zip.\nDo you want to visit the 7-zip download page?"
+t MSG_103 "Download %s?"
+t MSG_104 "Syslinux v5.0 or later requires a '%s' file to be installed.\n"
+ "Because this file is more than 100 KB in size, and always present on Syslinux v5+ ISO images, "
+ "it is not embedded in Rufus.\n\nRufus can download the missing file for you:\n"
+ "- Select 'Yes' to connect to the internet and download the file\n"
+ "- Select 'No' if you want to manually copy this file on the drive later\n\n"
+ "Note: The file will be downloaded in the current directory and once a "
+ "'%s' exists there, it will be reused automatically.\n"
+t MSG_105 "Cancelling may leave the device in an UNUSABLE state.\n"
+ "If you are sure you want to cancel, click YES. Otherwise, click NO."
+t MSG_106 "Please select folder"
+t MSG_107 "All files"
+t MSG_108 "Rufus log"
+t MSG_109 "0x%02X (Disk %d)"
+
+# Tootips
+# Partition Scheme and Target Type
+t MSG_150 "Usually the safest choice. If you have an UEFI computer and want to install "
+ "an OS in EFI mode however, you should select one of the options below"
+t MSG_151 "Use this if you want to install an OS in EFI mode, but need to access "
+ "the USB content from Windows XP"
+t MSG_152 "The preferred option to install an OS in EFI mode and when "
+ "USB access is not required for Windows XP"
+t MSG_153 "Test pattern: 0x%02X"
+t MSG_154 "Test pattern: 0x%02X, 0x%02X"
+t MSG_155 "Test pattern: 0x%02X, 0x%02X, 0x%02X"
+t MSG_156 "Test pattern: 0x%02X, 0x%02X, 0x%02X, 0x%02X"
+t MSG_157 "Sets the target filesystem"
+t MSG_158 "Minimum size that a block of data will occupy in the filesystem"
+t MSG_159 "Use this field to set the drive label\nInternational characters are accepted"
+t MSG_160 "Toggle advanced options"
+t MSG_161 "Check the device for bad blocks using a test pattern"
+t MSG_162 "Uncheck this box to use the \"slow\" format method"
+t MSG_163 "Check this box to make the USB drive bootable"
+t MSG_164 "Method that will be used to make the drive bootable"
+t MSG_165 "Click to select an ISO..."
+t MSG_166 "Check this box to allow the display of international labels "
+ "and set a device icon (creates an autorun.inf)"
+t MSG_167 "Install an MBR that allows boot selection and can masquerade the BIOS USB drive ID"
+t MSG_168 "Try to masquerade first bootable USB drive (usually 0x80) as a different disk.\n"
+ "This should only be necessary if you install Windows XP and have more than one disk"
+t MSG_169 "Create an extra hidden partition and try to align partitions boundaries.\n"
+ "This can improve boot detection for older BIOSes"
+t MSG_170 "Enable detection for disks not normally detected by Rufus. USE AT YOUR OWN RISKS!!!"
+t MSG_171 "Start the formatting operation.\nThis will DESTROY any data on the target!"
+t MSG_172 "Licensing information and credits"
+t MSG_173 "Click to select..."
+# The following will appear in the about dialog
+t MSG_174 "Rufus - The Reliable USB Formatting Utility"
+t MSG_175 "Version %d.%d.%d (Build %d)"
+t MSG_176 ""
+t MSG_177 "Report bugs or request enhancements at:"
+t MSG_178 "Additional Copyrights:"
+t MSG_179 "Update Policy:"
+t MSG_180 "If you choose to allow this program to check for application updates, "
+ "you agree that the following information may be collected on our server(s):"
+t MSG_181 "Your operating system's architecture and version"
+t MSG_182 "The version of the application you use"
+t MSG_183 "Your IP address"
+t MSG_184 "For the purpose of generating private usage statistics, we may keep the information collected, "
+ "\\b for at most a year\\b0 . However, we will not willingly disclose any of this individual data to third parties."
+t MSG_185 "Update Process:"
+t MSG_186 "Rufus does not install or run background services, therefore update checks are performed only when the main application is running.\\line\n"
+ "Internet access is of course required when checking for updates."
+
+# Status messages - these messages will appear on the status bar
+t MSG_201 "Cancelling - Please wait..."
+t MSG_202 "Scanning ISO image..."
+t MSG_203 "Failed to scan ISO image"
+# Parameter: the name of an obsolete Syslinux .c32 module. eg: "Obsolete vesamenu.c32 detected"
+t MSG_204 "Obsolete %s detected"
+# Display the name of the ISO selected. eg: "Using ISO: en_win7_x64_sp1.iso"
+t MSG_205 "Using ISO: %s"
+# Typically "Missing ldlinux.c32 file"
+t MSG_206 "Missing %s file"
+# Same message, once for singular and plural ("1 device found", "2 devices found")
+t MSG_208 "%d device found"
+t MSG_209 "%d devices found"
+t MSG_210 "DONE."
+t MSG_211 "Cancelled."
+t MSG_212 "FAILED."
+# Used when a new update has been downloaded and lauched
+t MSG_213 "Launching new application..."
+t MSG_214 "Failed to launch new application"
+# Open/Save file
+t MSG_215 "Opened %s"
+t MSG_216 "Saved %s"
+# Formatting status (make sure you use a double % to print the percent sign)
+t MSG_217 "Formatting: %0.1f%% completed"
+t MSG_218 "Creating file system: Task %d/%d completed"
+t MSG_219 "NTFS Fixup: %d%% completed"
+t MSG_221 "Setting Label (This may take while)..."
+# Parameter: the file system. eg. "Formatting (NTFS)..."
+t MSG_222 "Formatting (%s)..."
+t MSG_223 "NTFS Fixup (Checkdisk)..."
+t MSG_224 "Clearing MBR/PBR/GPT structures..."
+t MSG_225 "Requesting disk access..."
+t MSG_226 "Analyzing existing boot records..."
+t MSG_227 "Closing existing volume..."
+t MSG_228 "Writing master boot record..."
+t MSG_229 "Writing partition boot record..."
+t MSG_230 "Copying DOS files..."
+t MSG_231 "Copying ISO files..."
+t MSG_232 "Win7 EFI boot setup (this may take a while)..."
+t MSG_233 "Finalizing, please wait..."
+# Takes the Syslinux version as paramete. eg. "Installing Syslinux v5..."
+t MSG_234 "Installing Syslinux v%d..."
+# Bad blocks status. eg: "Bad Blocks: PASS 1/2 - 12.34% (0/0/1 errors)"
+t MSG_235 "Bad Blocks: PASS %d/%d - %0.2f%% (%d/%d/%d errors)"
+t MSG_236 "Bad Blocks: Testing with random pattern"
+t MSG_237 "Bad Blocks: Testing with pattern 0x%02X"
+# eg. "Partitioning (MBR)..."
+t MSG_238 "Partitioning (%s)..."
+t MSG_239 "Deleting partitions..."
+t MSG_240 "Downloading %s: Connecting..."
+t MSG_241 "Downloading: %0.1f%%"
+t MSG_242 "Failed to download file."
+t MSG_243 "Checking for Rufus updates..."
+t MSG_244 "Updates: Unable to connect to the internet"
+t MSG_245 "Updates: Unable to acces version data"
+t MSG_246 "A new version of Rufus is available!"
+t MSG_247 "No new version of Rufus was found"
+t MSG_248 "Application registry keys successfully deleted"
+t MSG_249 "Failed to delete application registry keys"
+# eg. "Fixed disk detection enabled" "ISO size check disabled"
+t MSG_250 "%s enabled"
+t MSG_251 "%s disabled"
+t MSG_252 "Size checks"
+t MSG_253 "Fixed disks detection"
+t MSG_254 "Force large FAT32 formatting"
+t MSG_255 "NoDriveTypeAutorun will be deleted on exit"
+t MSG_256 "Fake drive detection"
+t MSG_257 "Joliet support"
+t MSG_258 "Rock Ridge support"
+
+################################################################################
+l "fr_FR" "French" 0x040c, 0x080c, 0x0c0c, 0x100c, 0x140c, 0x180c, 0x1c0c, 0x200c, 0x240c, 0x280c, 0x2c0c, 0x300c, 0x340c, 0x380c, 0xe40c
+g IDD_DIALOG
+t IDS_DEVICE_TXT "Periphérique"
+t IDS_PARTITION_TYPE_TXT "Type de partition et système de destination"
+t IDS_FILESYSTEM_TXT "Système de fichiers"
+t IDS_CLUSTERSIZE_TXT "Taille de clusters"
+t IDS_LABEL_TXT "Nouveau label"
+t IDS_FORMAT_OPTIONS_GRP "Options de Formattage "
+t IDC_BADBLOCKS "Vérification de mauvais blocs:"
+s IDC_BADBLOCKS +10,0
+m IDC_NBPASSES +5,0
+t IDC_QUICKFORMAT "Formattage rapide"
+t IDC_BOOT "Disque de démarrage utilisant:"
+s IDC_BOOT +5,0
+m IDC_BOOTTYPE +5,0
+m IDC_SELECT_ISO +3,0
+t IDC_SET_ICON "Ajouter un label étendu et une icône"
+m IDC_ADVANCED +36,0
+t IDC_ABOUT "A propos..."
+t IDCANCEL "Fermer"
+t IDC_START "Démarrer"
+t IDS_ADVANCED_OPTIONS_GRP "Options avancées"
+t IDC_ENABLE_FIXED_DISKS "Lister les disques fixes ou non partitionés"
+t IDC_EXTRA_PARTITION "Options de compatibilité avec anciens BIOS"
+t IDC_RUFUS_MBR "Ajout du MBR Rufus, ID BIOS:"
+m IDC_DISK_ID +5,0
+s IDC_DISK_ID -2,0
+
+g IDD_ABOUTBOX
+t IDD_ABOUTBOX "A propos de Rufus"
+t IDC_ABOUT_LICENSE "License"
+t IDC_ABOUT_UPDATES "Mises à jour"
+
+g IDD_LICENSE
+t IDD_LICENSE "License Rufus"
+
+g IDD_NOTIFICATION
+t IDC_MORE_INFO "Plus d'info..."
+t IDYES "Oui"
+t IDNO "Non"
+
+g IDD_LOG
+t IDC_LOG_CLEAR "Effacer"
+t IDC_LOG_SAVE "Enregistrer"
+t IDCANCEL "Fermer"
+
+g IDD_UPDATE_POLICY
+s IDD_UPDATE_POLICY +30,0
+t IDD_UPDATE_POLICY "Paramètres de mises à jour"
+s IDC_POLICY +30,0
+t IDS_UPDATE_SETTINGS_GRP "Options"
+s IDS_UPDATE_SETTINGS_GRP +20,0
+t IDS_UPDATE_FREQUENCY_TXT "Recherche mises à jour:"
+s IDS_UPDATE_FREQUENCY_TXT -3,0
+t IDS_INCLUDE_BETAS_TXT "Inclure les bétas:"
+m IDC_UPDATE_FREQUENCY -3,0
+m IDC_INCLUDE_BETAS -3,0
+s IDC_UPDATE_FREQUENCY +25,0
+m IDS_CHECK_NOW_GRP 20,0
+s IDS_CHECK_NOW_GRP +10,0
+t IDC_CHECK_NOW "Chercher maintenant"
+m IDC_CHECK_NOW 9,0
+s IDC_CHECK_NOW +31,0
+t IDCANCEL "Fermer"
+m IDCANCEL 9,0
+
+g IDD_NEW_VERSION
+t IDD_NEW_VERSION "Mise à jour de Rufus"
+t IDS_NEW_VERSION_AVAIL_TXT "Une nouvelle version est disponible. Veuillez télécharger la nouvelle version !"
+t IDC_WEBSITE "Cliquez ici pour aller sur le site de Rufus"
+t IDS_NEW_VERSION_NOTES_GRP "Notes relatives à cette version"
+t IDS_NEW_VERSION_DOWNLOAD_GRP "Téléchargement"
+t IDC_DOWNLOAD ""Télécharger""
+t IDCANCEL "Fermer"
+
+g IDD_ISO_EXTRACT
+t IDD_ISO_EXTRACT "Copie des fichier ISO..."
+t IDC_ISO_FILENAME "Ouverture de l'image - veuillez patienter..."
+t IDC_ISO_ABORT "Annuler"
+
+g IDD_MESSAGES
+t MSG_001 "Autre instance detectée"
+t MSG_002 "Une autre instance de Rufus est en cours d'exécution.\n"
+ "Veuillez fermer la première instance avant d'en lancer une seconde."
+t MSG_003 "ATTENTION: TOUTES LES DONNEES DU VOLUME '%s' VONT ETRE EFFACEES.\n"
+ "Pour continuer cette operation, cliquez sur OK.\nPour quitter cliquez sur ANNULER."
+t MSG_004 "Mises à jour"
+t MSG_005 "Voulez-vous authoriser Rufus à chercher des mises à jour en ligne?"
+t MSG_006 "Fermer"
+t MSG_007 "Annuler"
+t MSG_008 "Oui"
+t MSG_009 "Non"
+t MSG_010 "Blocs défectueux détectés"
+t MSG_011 "Vérification complète: %u bloc(s) défectueux détecté(s)\n"
+ " %d erreur(s) de lecture\n %d erreur(s) d'écriture\n %d erreur(s) de corruption\n"
+t MSG_012 "%s\nUn rapport plus détaillé peut être obtenu à:\n%s"
+t MSG_013 "Jamais"
+t MSG_014 "Quotidienne"
+t MSG_015 "Hebdomadaire"
+t MSG_016 "Mensuelle"
+t MSG_017 "Personalisée"
+t MSG_018 "Votre version: %d.%d.%d (Build %d)"
+t MSG_019 "Dernière version: %d.%d.%d (Build %d)"
+t MSG_020 "octets"
+t MSG_021 "Ko"
+t MSG_022 "Mo"
+t MSG_023 "Go"
+t MSG_024 "To"
+t MSG_025 "Po"
+t MSG_026 "octets"
+t MSG_027 "kilo-octets"
+t MSG_028 "mega-octets"
+t MSG_029 "Défaut"
+t MSG_030 "%s (Défaut)"
+t MSG_031 "Type de partition %s pour ordinateur BIOS"
+t MSG_032 "Type de partition %s pour ordinateur UEFI"
+t MSG_033 "Type de partition %s pour ordinateur BIOS ou UEFI"
+t MSG_034 "%d passe"
+t MSG_035 "%d passes"
+t MSG_036 "Image ISO"
+t MSG_037 "Application"
+t MSG_038 "Annuler"
+t MSG_039 "Lancer"
+t MSG_040 "Télécharger"
+t MSG_041 "Operation annulée par l'utilisateur"
+t MSG_042 "Erreur"
+t MSG_043 "Erreur: %s"
+t MSG_044 "Téléchargement de fichier"
+t MSG_045 "Pérpih. de stockage USB (Générique)"
+t MSG_046 "%s (Disque %d)"
+t MSG_047 "%s (%c:)"
+t MSG_048 "Rufus - Flush de la mémoire tampon"
+t MSG_049 "Rufus - Annulation"
+
+# Error messages
+t MSG_050 "Opération réussie."
+t MSG_051 "Erreur indéterminéee lors du formatage."
+t MSG_052 "Ce système de fichiers ne peut pas être utilisé ici."
+t MSG_053 "L'accès au périphérique est refusé."
+t MSG_054 "Le périphérique est protegé en écriture."
+t MSG_055 "Le périphérique est en cours d'utilisation par une autre application. "
+ "Veuillez fermer toute autre application succeptible d'accéder au périphérique."
+t MSG_056 "Le formatage rapide n'est pas disponible pour ce périphérique."
+t MSG_057 "Le nom de volume est invalide."
+t MSG_058 "Le handle de périphérique est invalide."
+t MSG_059 "Cette taille de cluster n'est pas appliquable ici."
+t MSG_060 "La taille du volume est invalide."
+t MSG_061 "Veuillez insérer un média dans le lecteur."
+t MSG_062 "Commande non supportée."
+t MSG_063 "Erreur d'allocation mémoire."
+t MSG_064 "Erreur de lecture."
+t MSG_065 "Erreur d'écriture."
+t MSG_066 "L'installation a échoué"
+t MSG_067 "Impossible d'accéder au média. Il peut être en cours d'utilisation par une autre application. "
+ "Essayer de déconnecter le média et essayez à nouveau."
+t MSG_068 "Erreur de partitionement."
+t MSG_069 "Impossible de copier les fichiers sur le périphérique de detination."
+t MSG_070 "Opération annulée par l'utilisateur."
+t MSG_071 "Impossible de créer le thread de formattage."
+t MSG_072 "La vérification de blocs défectueux a été interrompue."
+t MSG_073 "Echec d'analyse de l'image ISO."
+t MSG_074 "Echec d'extraction de l'image ISO."
+t MSG_075 "Echec lors du remontage du volume."
+t MSG_076 "Echec de modification des fichiers de démarrage."
+t MSG_077 "Echec d'assignation d'une lettre de volume."
+t MSG_078 "Impossible de monter le volume GUID."
+
+t MSG_080 "Rufus a detecté que Windows est en train de finir de vider la mémoire tampon.\n\n"
+ "En fonction de la vitesse de votre périphérique, cette opération peut prendre beaucoup de temps, "
+ "surtout s'il s'agit d'un fichier volumineux.\n\nNous recommandons d'attendre que Windows "
+ "complète cette opération, afin d'éviter la corruption du périphérique. Mais si jamais cela prend "
+ "trop de temps, vous pouvez toujours essayer de déconnecter le média..."
+t MSG_081 "Image ISO non supportée"
+t MSG_082 "Cette version de Rufus supporte seulement les ISOs démarrables qui utilisent bootmgr/WinPE, isolinux ou EFI.\n"
+ "Cette image ISO ne semble pas utiliser une de ces options..."
+t MSG_083 "Remplacer %s?"
+t MSG_084 "Cette image ISO utilise une version obsolète du fichier '%s'.\n"
+ "A cause de cela, les menus de démarrage peuvent de pas fonctionner.\n\n"
+ "Une nouvelle version du fichier peut être téléchargée par Rufus pour addresser ce problème:\n"
+ "- Choisissez 'Oui' pour télécharger le fichier depuis Internet\n"
+ "- Choisissez 'Non' pour garder le fichier de l'image ISO\n"
+ "Si vous ne savez pas quoi faire, sélectionnez 'Oui'.\n\n"
+ "Note: Le nouveau fichier est téléchargé dans le répertoire courrant. Une fois qu'un fichier"
+ "'%s' existe à cet endroit, il sera réutilisé automatiquement."
+t MSG_085 "Téléchargement de %s"
+t MSG_086 "Aucune image ISO sélectionnée"
+t MSG_087 "Veuillez cliquer sur le bouton avec un disque pour choisir une image ISO démarrable "
+ "ou décochez l'option \"Disque de démarrage...\"."
+t MSG_088 "Image ISO trop large"
+t MSG_089 "Cette ISO image est trop large pour le périphérique sélectionné."
+t MSG_090 "Image ISO on supportée"
+t MSG_091 "Quand UEFI est séelectionné, seules les images ISO basées sur EFI sont supportées. "
+ "Veuillez sélectionner une image ISO démarrable avec EFI ou sélectionner BIOS pour le système de destination."
+t MSG_092 "Système de fichiers non supporté"
+t MSG_093 "Quand UEFI est séelectionné, seul le système de fichiers FAT/FAT32 est supporté. "
+ "Veuillez sélectionner FAT/FAT32 comme système de fichiers ou sélectionner BIOS pour le système de destination."
+t MSG_094 "Image ISO incompatible avec UEFI"
+t MSG_095 "Cette image ISO contient un fichier de plus de 4 Go et ne peut pas être utilisée pour créer un USB démarrable par UEFI.\n"
+ "Ceci est une limitation de UEFI/FAT32, pas de Rufus."
+t MSG_096 "Seul FAT/FAT32 est supporté avec ce type d'image ISO. Veuillez sélectionner FAT/FAT32 pour le système de fichiers."
+t MSG_097 "Seules les images ISO utilisant 'bootmgr' ou 'WinPE' peuvent être utilisées avec NTFS."
+t MSG_098 "FAT/FAT32 peut seulement être utilisé pour les images ISO utilisant 'isolinux' ou lorsque que le système de destination est UEFI."
+t MSG_099 "Limitation du système de fichiers"
+t MSG_100 "Cette image ISO contient un fichier de plus de 4 Go, ce qui est plus que la taille maximum "
+ "supportée par le système de fichiers FAT ou FAT32."
+t MSG_101 "Support pour archives WIM non disponible"
+t MSG_102 "Votre plateforme ne peut pas extraire les fichiers depuis les archives WIM. L'extraction de données WIM "
+ "est nécéssaire pour créer des médias USB démarrable avec EFI pour Windows 7/8 ou Windows Vista. Vous pouvez addresser "
+ "ce problème en téléchargeant une version récente de l'utilitaire 7-Zip.\nVoulez-vous visiter la page de téléchargements de 7-zip?"
+t MSG_103 "Télécharger %s?"
+t MSG_104 "Syslinux v5.0 ou plus récent requiert l'installtion d'un fichier '%s'.\n"
+ "Puisque ce fichier fait plus de 100 Ko et est toujours présent sur les images ISO à base de Syslinux v5+, "
+ "il n'est pas inclus dans l'application.\n\nRufus peut télécharger ce fichier pour vous:\n"
+ "- Choisissez 'Oui' pour télécharger le fichier depuis Internet\n"
+ "- Choisissez 'Non' si vous compter copier ce fichier manuellement\n"
+ "Note: Ce fichier est téléchargé dans le répertoire courrant. Une fois qu'un fichier"
+ "'%s' existe à cet endroit, il sera réutilisé automatiquement."
+t MSG_105 "Annuler peut laisser le périphérique dans un état inutilisable.\n"
+ "Si vous êtes sûr de vouloir annuler, sélectionnez OUI. Sinon, sélectionnez NON."
+t MSG_106 "Sélection de répertoire"
+t MSG_107 "Tous les fichiers"
+t MSG_108 "Log Rufus"
+t MSG_109 "0x%02X (disque %d)"
+
+# Tootips
+t MSG_150 "Choix le plus sûr. Si toutefois vous possédez un ordinateur à base de UEFI et voulez installer "
+ "un Système d’exploitation en mode EFI, vous devriez plutôt sélectionner l’une des options ci-dessous"
+t MSG_151 "Utilisez cette options si vous comptez installer un Système d’exploitation en mode EFI "
+ "et avez aussi besoin d’accéder au contenu du média sous Windows XP"
+t MSG_152 "Option préférée pour installer un Système d’exploitation en mode EFI, "
+ "quand l’accès au média depuis Windows XP n’est pas nécessaire"
+t MSG_153 "Motif de test: 0x%02X"
+t MSG_154 "Motif de test: 0x%02X, 0x%02X"
+t MSG_155 "Motif de test: 0x%02X, 0x%02X, 0x%02X"
+t MSG_156 "Motif de test: 0x%02X, 0x%02X, 0x%02X, 0x%02X"
+t MSG_157 "Sélectionne le système de fichiers"
+t MSG_158 "La taille minimum qu’un bloc de données occupera sur le système de fichiers"
+t MSG_159 "Utilisez ce champ pour mettre à jour le nom du volume\n"
+ "Les caractères étendus et les accents sont acceptés "
+t MSG_160 "Affiche/Cache les options avancées "
+t MSG_161 "Détecte la présence de blocs défectueux en utilisant un motif de test"
+t MSG_162 "Décochez cette case pour utiliser la méthode de formatage \"lente\" "
+t MSG_163 "Cochez cette case pour rendre le périphérique démarrable"
+t MSG_164 "Méthode à utiliser pour rendre le périphérique démarrable "
+t MSG_165 "Cliquez ici pour sélectionner une image ISO..."
+t MSG_166 "Cochez cette case pour permettre l’affichage des caractères étendus/internationaux "
+ "et ajouter une icône (créé un fichier autorun.inf)"
+t MSG_167 "Installe un MBR permettant la sélection du périphérique de démarrage. Peut aussi "
+ "camoufler l’ID de disque pour le BIOS "
+t MSG_168 "Camoufle le premier disque USB démarrable (généralement 0x80) sous une ID différente.\n"
+ "Changez cette option si vous installez Windows XP avec plus d’un disque dur"
+t MSG_169 "Créé une petite partition supplémentaire et essaye d’aligner les partitions.\n"
+ "Peut améliorer la détection USB pour les vieux BIOS"
+t MSG_170 "Active la détection de disque non normalement listés par Rufus. UTILISEZ A VOS PROPRES RISQUES !!! "
+t MSG_171 "Lance le formatage. DETRUIT toutes les données existantes sur la cible !"
+t MSG_172 "Licence d’utilisation et remerciements"
+t MSG_173 "Cliquez pour sélectionner..."
+t MSG_174 "Rufus - The Reliable USB Formatting Utility"
+t MSG_175 "Version %d.%d.%d (Build %d)"
+t MSG_176 "Traduction Française: Pete Batard"
+t MSG_177 "Soumettre un bug ou une demande d'amélioration à:"
+t MSG_178 "Copyrights supplémentaires:"
+t MSG_179 "Politique de mises à jour:"
+t MSG_180 "Si vous autorisez ce programme à chercher les mises à jour, vous acceptez "
+ "que les informations suivantes peuvent être collectées sur nos serveurs:"
+t MSG_181 "L’architecture de votre système d’exploitation ainsi que sa version"
+t MSG_182 "La version de l’application que vous utilisez"
+t MSG_183 "Votre adresse IP"
+t MSG_184 "Afin de générer des statistiques d’utilisation privées, il se peut que nous gardions "
+ "les informations ainsi obtenues \\b au plus un an\\b0 . A moins d’y être contraint par la loi, "
+ "nous nous engageons aussi à ne pas diffuser ces informations à de tierce parties."
+t MSG_185 "Processus de mise à jour:"
+t MSG_186 "Aucun service ou tâche de fond ne sont installés ou lancés par Rufus. Cela veut dire que les "
+ "test de mises à jour interviennent seulement lorsque l’application principale s'exécute.\\line\n"
+ "Bien entendu, un accès à internet est requis pour vérifier la disponibilité des mises à jour."
+
+# Status messages
+t MSG_201 "Annulation - Veuillez patienter..."
+t MSG_202 "Analyse de l'image ISO..."
+t MSG_203 "Echec d'analyse de l'image ISO"
+t MSG_204 "Fichier %s obsolète detecté"
+t MSG_205 "ISO utilisée: %s"
+t MSG_206 "Fichier %s manquant"
+t MSG_208 "%d périphérique détecté"
+t MSG_209 "%d périphériques détectés"
+t MSG_210 "Opération terminée."
+t MSG_211 "Opération annulée."
+t MSG_212 "ECHEC."
+t MSG_213 "Lancement de la nouvelle application..."
+t MSG_214 "Echec de lancement de l'application"
+t MSG_215 "%s ouvert"
+t MSG_216 "%s sauvegardé"
+t MSG_217 "Formatage: %0.1f%% complet"
+t MSG_218 "Création du système de fichiers: Tâche %d/%d complète"
+t MSG_219 "Finalisation NTFS: %d%% complète"
+t MSG_221 "Ecriture du label (peut prendre du temps)..."
+t MSG_222 "Formatage (%s)..."
+t MSG_223 "Finalisation NTFS (Checkdisk)..."
+t MSG_224 "Effacement des structures MBR/PBR/GPT..."
+t MSG_225 "Requête d'accès disque..."
+t MSG_226 "Analyse des structures de boot existantes..."
+t MSG_227 "Fermeture des volumes existants..."
+t MSG_228 "Ecriture du MBR..."
+t MSG_229 "Ecriture du PBR..."
+t MSG_230 "Copie des fichiers DOS..."
+t MSG_231 "Copie des fichiers ISO..."
+t MSG_232 "Ecriture boot Win7 EFI (peut prendre du temps)..."
+t MSG_233 "Finalisation, veuillez patienter..."
+t MSG_234 "Installation de Syslinux v%d..."
+t MSG_235 "Défauts: PASSE %d/%d - %0.2f%% (%d/%d/%d erreurs)"
+t MSG_236 "Défauts: Test avec motif aléatoire"
+t MSG_237 "Défauts: Test avec motif 0x%02X"
+t MSG_238 "Partitionage (%s)..."
+t MSG_239 "Effaçement des partitions..."
+t MSG_240 "Télechargement de %s: Connection..."
+t MSG_241 "Télechargement: %0.1f%%"
+t MSG_242 "Echec de télechargement du fichier"
+t MSG_243 "Recherche des mises à jour..."
+t MSG_244 "MAJ: Impossible de se connecter"
+t MSG_245 "MAJ: Pas d'accès aux données de mises à jour"
+t MSG_246 "Une nouvelle version de Rufus est disponible !"
+t MSG_247 "Pas de mise à jour"
+t MSG_248 "Clés de registre supprimées"
+t MSG_249 "Echec de suppression des clés registres"
+t MSG_250 "%s activé"
+t MSG_251 "%s désactivé"
+t MSG_252 "Tests de dépassement de taille"
+t MSG_253 "Détection de disques fixes"
+t MSG_254 "Force 'large FAT32'"
+t MSG_255 "NoDriveTypeAutorun sera effacé en sortie"
+t MSG_256 "Test de contrefaçons"
+t MSG_257 "Support Joliet"
+t MSG_258 "Support Rock Ridge"
+
+################################################################################
+l "zh_CN" "Chinese (Traditional)" 0x0404, 0x0804, 0x0c04, 0x1004, 0x1404
+g IDD_DIALOG
+t IDS_DEVICE_TXT "设备"
+t IDS_PARTITION_TYPE_TXT "分区计划和目标系统类型"
+t IDS_FILESYSTEM_TXT "文件系统"
+t IDS_CLUSTERSIZE_TXT "簇的大小"
+t IDS_LABEL_TXT "新卷标"
+t IDS_FORMAT_OPTIONS_GRP "格式选项 "
+t IDC_BADBLOCKS "检查设备的坏块:"
+t IDC_QUICKFORMAT "快速格式化"
+t IDC_BOOT "创建一个可启动的磁盘使用:"
+s IDC_BOOT +10,0
+t IDC_SET_ICON "创建扩展标签和图标文件"
+m IDC_ADVANCED -24,0
+m IDC_NBPASSES 8,0
+m IDC_BOOTTYPE 8,0
+m IDC_SELECT_ISO 6,0
+t IDC_ABOUT "关于..."
+t IDC_LOG "日志"
+m IDC_LOG -5,0
+s IDC_LOG +5,0
+t IDCANCEL "关闭"
+t IDC_START "开始"
+t IDS_ADVANCED_OPTIONS_GRP "高级选项"
+t IDC_ENABLE_FIXED_DISKS "列表固定(非flash)或USB磁盘分区"
+t IDC_EXTRA_PARTITION "添加修复旧的BIOS(额外的分区,校准等等)"
+t IDC_RUFUS_MBR "使用 Rufus MBR BIOS ID:"
+
+g IDD_ABOUTBOX
+t IDD_ABOUTBOX "关于 Rufus"
+t IDC_ABOUT_LICENSE "许可证"
+t IDC_ABOUT_UPDATES "更新"
+t IDOK "确定"
+
+g IDD_LICENSE
+t IDD_LICENSE "Rufus 许可证"
+t IDOK "取消"
+
+g IDD_NOTIFICATION
+t IDD_NOTIFICATION "更新方案和设置"
+t IDC_MORE_INFO "更多信息"
+t IDYES "是"
+t IDNO "否"
+
+g IDD_LOG
+t IDD_LOG "日志"
+t IDC_LOG_CLEAR "清除日志"
+t IDC_LOG_SAVE "保存日志"
+t IDCANCEL "关闭日志"
+
+g IDD_LICENSE
+t IDOK "取消"
+
+g IDD_UPDATE_POLICY
+t IDD_UPDATE_POLICY "更新方案和设置"
+t IDS_UPDATE_SETTINGS_GRP "设置"
+t IDS_UPDATE_FREQUENCY_TXT "检查更新:"
+t IDS_INCLUDE_BETAS_TXT "包括测试版本:"
+t IDC_CHECK_NOW "立即检查"
+t IDCANCEL "取消"
+
+g IDD_NEW_VERSION
+t IDD_NEW_VERSION "检查更新 - Rufus"
+t IDS_NEW_VERSION_AVAIL_TXT "更新的版本可用。请下载最新版本!"
+t IDC_WEBSITE "点击这里进入网站"
+t IDS_NEW_VERSION_NOTES_GRP "发行说明"
+t IDS_NEW_VERSION_DOWNLOAD_GRP "下载"
+t IDC_DOWNLOAD "下载"
+t IDCANCEL "取消"
+
+g IDD_ISO_EXTRACT
+t IDD_ISO_EXTRACT "复制ISO文件..."
+t IDC_ISO_FILENAME "打开ISO映像 - 请稍候..."
+t IDC_ISO_ABORT "取消"
+
+g IDD_MESSAGES
+t MSG_004 "更新方案和设置"
+t MSG_005 "你要允許此應用程序檢查更新?"
+t MSG_006 "关闭"
+t MSG_007 "撤消"
diff --git a/src/.msvc/rufus.vcxproj b/src/.msvc/rufus.vcxproj
index a47b2a1f..f19850d6 100644
--- a/src/.msvc/rufus.vcxproj
+++ b/src/.msvc/rufus.vcxproj
@@ -87,6 +87,7 @@
..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;..\getopt;%(AdditionalIncludeDirectories)
CompileAsC
true
+ false
setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies)
@@ -113,6 +114,7 @@
ProgramDatabase
CompileAsC
true
+ false
setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies)
@@ -135,6 +137,7 @@
..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;..\getopt;%(AdditionalIncludeDirectories)
CompileAsC
true
+ false
setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies)
@@ -160,6 +163,7 @@
..\msvc-missing;..\ms-sys\inc;..\syslinux\libinstaller;..\syslinux\libfat;..\libcdio;..\getopt;%(AdditionalIncludeDirectories)
CompileAsC
true
+ false
setupapi.lib;comctl32.lib;wininet.lib;%(AdditionalDependencies)
@@ -181,6 +185,7 @@
+
@@ -197,6 +202,8 @@
+
+
diff --git a/src/.msvc/rufus.vcxproj.filters b/src/.msvc/rufus.vcxproj.filters
index e77ebd51..f7d61035 100644
--- a/src/.msvc/rufus.vcxproj.filters
+++ b/src/.msvc/rufus.vcxproj.filters
@@ -60,6 +60,9 @@
Source Files
+
+ Source Files
+
@@ -101,6 +104,12 @@
Header Files
+
+ Header Files
+
+
+ Header Files
+
diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources
index c359e75c..f95c1bcc 100644
--- a/src/.msvc/rufus_sources
+++ b/src/.msvc/rufus_sources
@@ -36,6 +36,7 @@ SOURCES=rufus.c \
stdlg.c \
icon.c \
parser.c \
+ localization.c \
net.c \
iso.c \
dos.c \
diff --git a/src/Makefile.am b/src/Makefile.am
index decd2f84..2fbb05e5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,7 +9,7 @@ pkg_v_rc_0 = @echo " RC $@";
%_rc.o: %.rc
$(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@
-rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdfn.c stdlg.c rufus.c
+rufus_SOURCES = drive.c icon.c parser.c localization.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdfn.c stdlg.c rufus.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
diff --git a/src/Makefile.in b/src/Makefile.in
index 04bef641..46003ead 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -44,12 +44,13 @@ CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \
- rufus-parser.$(OBJEXT) rufus-iso.$(OBJEXT) rufus-net.$(OBJEXT) \
- rufus-dos.$(OBJEXT) rufus-dos_locale.$(OBJEXT) \
- rufus-badblocks.$(OBJEXT) rufus-syslinux.$(OBJEXT) \
- rufus-vhd.$(OBJEXT) rufus-format.$(OBJEXT) \
- rufus-stdio.$(OBJEXT) rufus-stdfn.$(OBJEXT) \
- rufus-stdlg.$(OBJEXT) rufus-rufus.$(OBJEXT)
+ rufus-parser.$(OBJEXT) rufus-localization.$(OBJEXT) \
+ rufus-iso.$(OBJEXT) rufus-net.$(OBJEXT) rufus-dos.$(OBJEXT) \
+ rufus-dos_locale.$(OBJEXT) rufus-badblocks.$(OBJEXT) \
+ rufus-syslinux.$(OBJEXT) rufus-vhd.$(OBJEXT) \
+ rufus-format.$(OBJEXT) rufus-stdio.$(OBJEXT) \
+ rufus-stdfn.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
+ rufus-rufus.$(OBJEXT)
rufus_OBJECTS = $(am_rufus_OBJECTS)
rufus_DEPENDENCIES = rufus_rc.o ms-sys/libmssys.a \
syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
@@ -184,7 +185,7 @@ SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/u
pkg_v_rc = $(pkg_v_rc_$(V))
pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY))
pkg_v_rc_0 = @echo " RC $@";
-rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdfn.c stdlg.c rufus.c
+rufus_SOURCES = drive.c icon.c parser.c localization.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c vhd.c format.c stdio.c stdfn.c stdlg.c rufus.c
rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
@@ -269,6 +270,14 @@ rufus-parser.obj: parser.c
$(AM_V_CC) @AM_BACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-parser.obj `if test -f 'parser.c'; then $(CYGPATH_W) 'parser.c'; else $(CYGPATH_W) '$(srcdir)/parser.c'; fi`
+rufus-localization.o: localization.c
+ $(AM_V_CC) @AM_BACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-localization.o `test -f 'localization.c' || echo '$(srcdir)/'`localization.c
+
+rufus-localization.obj: localization.c
+ $(AM_V_CC) @AM_BACKSLASH@
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-localization.obj `if test -f 'localization.c'; then $(CYGPATH_W) 'localization.c'; else $(CYGPATH_W) '$(srcdir)/localization.c'; fi`
+
rufus-iso.o: iso.c
$(AM_V_CC) @AM_BACKSLASH@
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.o `test -f 'iso.c' || echo '$(srcdir)/'`iso.c
diff --git a/src/badblocks.c b/src/badblocks.c
index b7d27334..dfc3807a 100644
--- a/src/badblocks.c
+++ b/src/badblocks.c
@@ -45,6 +45,8 @@
#include "badblocks.h"
#include "file.h"
#include "msapi_utf8.h"
+#include "resource.h"
+#include "localization.h"
FILE* log_fd = NULL;
static const char* abort_msg = "Too many bad blocks, aborting test\n";
@@ -326,12 +328,12 @@ static void print_status(void)
percent = calc_percent((unsigned long) currently_testing,
(unsigned long) num_blocks);
percent = (percent/2.0f) + ((cur_op==OP_READ)? 50.0f : 0.0f);
- PrintStatus(0, FALSE, "Bad Blocks: PASS %d/%d - %0.2f%% (%d/%d/%d errors)",
+ PrintStatus(0, FALSE, lmprintf(MSG_235,
cur_pattern, nr_pattern,
- percent,
+ percent,
num_read_errors,
num_write_errors,
- num_corruption_errors);
+ num_corruption_errors));
UpdateProgress(OP_BADBLOCKS, (((cur_pattern-1)*100.0f) + percent) / nr_pattern);
}
@@ -357,7 +359,7 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
for (ptr = buffer; ptr < buffer + n; ptr++) {
(*ptr) = rand() % (1 << (8 * sizeof(char)));
}
- PrintStatus(3500, FALSE, "Bad Blocks: Testing with random pattern.");
+ PrintStatus(3500, FALSE, lmprintf(MSG_236));
} else {
bpattern[0] = 0;
for (i = 0; i < sizeof(bpattern); i++) {
@@ -374,7 +376,7 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
else
i--;
}
- PrintStatus(3500, FALSE, "Bad Blocks: Testing with pattern 0x%02X.", bpattern[i]);
+ PrintStatus(3500, FALSE, lmprintf(MSG_237, bpattern[i]));
cur_pattern++;
}
}
@@ -427,7 +429,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size,
size_t blocks_at_once, int nb_passes)
{
unsigned char *buffer = NULL, *read_buffer;
- const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00};
+ const unsigned int pattern[] = BADBLOCK_PATTERNS;
int i, pat_idx;
unsigned int bb_count = 0;
blk_t got, tryout, recover_block = ~0, *blk_id;
diff --git a/src/drive.c b/src/drive.c
index 90368da8..dd44525e 100644
--- a/src/drive.c
+++ b/src/drive.c
@@ -30,6 +30,7 @@
#include "rufus.h"
#include "resource.h"
#include "sys_types.h"
+#include "localization.h"
/*
* Globals
@@ -625,7 +626,7 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
DWORD size;
LONGLONG size_in_sectors;
- PrintStatus(0, TRUE, "Partitioning (%s)...", PartitionTypeName[partition_style]);
+ PrintStatus(0, TRUE, lmprintf(MSG_238, PartitionTypeName[partition_style]));
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_EXTRA_PARTITION))) {
// Go with the MS 1 MB wastage at the beginning...
@@ -772,7 +773,7 @@ BOOL DeletePartitions(HANDLE hDrive)
DWORD size;
CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}};
- PrintStatus(0, TRUE, "Deleting partitions...");
+ PrintStatus(0, TRUE, lmprintf(MSG_239));
size = sizeof(CreateDisk);
r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK,
diff --git a/src/format.c b/src/format.c
index dd639df7..9a713fcf 100644
--- a/src/format.c
+++ b/src/format.c
@@ -43,6 +43,7 @@
#include "file.h"
#include "format.h"
#include "badblocks.h"
+#include "localization.h"
/*
* Globals
@@ -68,16 +69,16 @@ static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command,
switch(Command) {
case FCC_PROGRESS:
percent = (DWORD*)pData;
- PrintStatus(0, FALSE, "Formatting: %d%% completed.", *percent);
+ PrintStatus(0, FALSE, lmprintf(MSG_217, *percent));
UpdateProgress(OP_FORMAT, 1.0f * (*percent));
break;
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
- PrintStatus(0, TRUE, "Creating file system: Task %d/%d completed.", ++task_number, nb_steps[fs_index]);
+ PrintStatus(0, TRUE, lmprintf(MSG_218, ++task_number, nb_steps[fs_index]));
format_percent += 100.0f / (1.0f * nb_steps[fs_index]);
UpdateProgress(OP_CREATE_FS, format_percent);
break;
case FCC_DONE:
- PrintStatus(0, TRUE, "Creating file system: Task %d/%d completed.", nb_steps[fs_index], nb_steps[fs_index]);
+ PrintStatus(0, TRUE, lmprintf(MSG_218, nb_steps[fs_index], nb_steps[fs_index]));
UpdateProgress(OP_CREATE_FS, 100.0f);
if(*(BOOLEAN*)pData == FALSE) {
uprintf("Error while formatting.\n");
@@ -152,7 +153,7 @@ static BOOLEAN __stdcall ChkdskCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DW
case FCC_PROGRESS:
case FCC_CHECKDISK_PROGRESS:
percent = (DWORD*)pData;
- PrintStatus(0, FALSE, "NTFS Fixup: %d%% completed.", *percent);
+ PrintStatus(0, FALSE, lmprintf(MSG_219, *percent));
break;
case FCC_DONE:
if(*(BOOLEAN*)pData == FALSE) {
@@ -365,7 +366,8 @@ static BOOL FormatFAT32(DWORD DriveIndex)
// Debug temp vars
ULONGLONG FatNeeded, ClusterCount;
- PrintStatus(0, TRUE, "Formatting (Large FAT32)...");
+ // TODO: use another lmsg for Large FAT32
+ PrintStatus(0, TRUE, lmprintf(MSG_222, "Large FAT32"));
VolumeId = GetVolumeID();
// Open the drive and lock it
@@ -552,7 +554,7 @@ static BOOL FormatFAT32(DWORD DriveIndex)
if (GetTickCount() > LastRefresh + 25) {
LastRefresh = GetTickCount();
format_percent = (100.0f*i)/(1.0f*(SystemAreaSize+BurstSize));
- PrintStatus(0, FALSE, "Formatting: %0.1f%% completed.", format_percent);
+ PrintStatus(0, FALSE, lmprintf(MSG_217, format_percent));
UpdateProgress(OP_FORMAT, format_percent);
}
if (IS_ERROR(FormatStatus)) goto out; // For cancellation
@@ -577,7 +579,7 @@ static BOOL FormatFAT32(DWORD DriveIndex)
}
// Must do it here, as have issues when trying to write the PBR after a remount
- PrintStatus(0, TRUE, "Writing partition boot record...");
+ PrintStatus(0, TRUE, lmprintf(MSG_229));
if (!WritePBR(hLogicalVolume)) {
// Non fatal error, but the drive probably won't boot
uprintf("Could not write partition boot record - drive may not boot...\n");
@@ -586,7 +588,7 @@ static BOOL FormatFAT32(DWORD DriveIndex)
// Set the FAT32 volume label
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
ToValidLabel(wLabel, TRUE);
- PrintStatus(0, TRUE, "Setting Label (This may take while)...");
+ PrintStatus(0, TRUE, lmprintf(MSG_221));
// Handle must be closed for SetVolumeLabel to work
safe_closehandle(hLogicalVolume);
VolumeName = GetLogicalName(DriveIndex, TRUE, TRUE);
@@ -617,17 +619,16 @@ static BOOL FormatDrive(DWORD DriveIndex)
{
BOOL r = FALSE;
PF_DECL(FormatEx);
- char FSType[32], format_status[64];
+ char FSType[32];
char *locale, *VolumeName = NULL;
WCHAR* wVolumeName = NULL;
- WCHAR wFSType[32];
+ WCHAR wFSType[64];
WCHAR wLabel[64];
ULONG ulClusterSize;
size_t i;
- GetWindowTextA(hFileSystem, FSType, ARRAYSIZE(FSType));
- safe_sprintf(format_status, ARRAYSIZE(format_status), "Formatting (%s)...", FSType);
- PrintStatus(0, TRUE, format_status);
+ GetWindowTextU(hFileSystem, FSType, ARRAYSIZE(FSType));
+ PrintStatus(0, TRUE, lmprintf(MSG_222, FSType));
VolumeName = GetLogicalName(DriveIndex, FALSE, TRUE);
wVolumeName = utf8_to_wchar(VolumeName);
if (wVolumeName == NULL) {
@@ -689,7 +690,7 @@ static BOOL CheckDisk(char DriveLetter)
size_t i;
wDriveRoot[0] = (WCHAR)DriveLetter;
- PrintStatus(0, TRUE, "NTFS Fixup (Checkdisk)...");
+ PrintStatus(0, TRUE, lmprintf(MSG_223));
PF_INIT_OR_OUT(Chkdsk, fmifs);
@@ -781,7 +782,7 @@ static BOOL ClearMBRGPT(HANDLE hPhysicalDrive, LONGLONG DiskSize, DWORD SectorSi
uint64_t i, last_sector = DiskSize/SectorSize;
unsigned char* pBuf = (unsigned char*) calloc(SectorSize, 1);
- PrintStatus(0, TRUE, "Clearing MBR/PBR/GPT structures...");
+ PrintStatus(0, TRUE, lmprintf(MSG_224));
if (pBuf == NULL) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
goto out;
@@ -1166,9 +1167,8 @@ DWORD WINAPI FormatThread(LPVOID param)
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
SYSTEMTIME lt;
- char* guid_volume = NULL;
+ char *bb_msg, *guid_volume = NULL;
char drive_name[] = "?:\\";
- char bb_msg[512];
char logfile[MAX_PATH], *userdir;
char wim_image[] = "?:\\sources\\install.wim";
char efi_dst[] = "?:\\efi\\boot\\bootx64.efi";
@@ -1180,7 +1180,7 @@ DWORD WINAPI FormatThread(LPVOID param)
bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
use_large_fat32 = (fs == FS_FAT32) && ((SelectedDrive.DiskSize > LARGE_FAT32_SIZE) || (force_large_fat32));
- PrintStatus(0, TRUE, "Requesting disk access...\n");
+ PrintStatus(0, TRUE, lmprintf(MSG_225));
hPhysicalDrive = GetPhysicalHandle(DriveIndex, TRUE, TRUE);
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
@@ -1217,7 +1217,7 @@ DWORD WINAPI FormatThread(LPVOID param)
}
CHECK_FOR_USER_CANCEL;
- PrintStatus(0, TRUE, "Analyzing existing boot records...\n");
+ PrintStatus(0, TRUE, lmprintf(MSG_226));
AnalyzeMBR(hPhysicalDrive);
if ((hLogicalVolume != NULL) && (hLogicalVolume != INVALID_HANDLE_VALUE)) {
AnalyzePBR(hLogicalVolume);
@@ -1267,19 +1267,15 @@ DWORD WINAPI FormatThread(LPVOID param)
report.num_read_errors, report.num_write_errors, report.num_corruption_errors);
r = IDOK;
if (report.bb_count) {
- safe_sprintf(bb_msg, sizeof(bb_msg), "Check completed: %u bad block%s found.\n"
- " %d read errors\n %d write errors\n %d corruption errors\n",
- report.bb_count, (report.bb_count==1)?"":"s",
- report.num_read_errors, report.num_write_errors,
+ bb_msg = lmprintf(MSG_011, report.num_read_errors, report.num_write_errors,
report.num_corruption_errors);
- fprintf(log_fd, "%s", bb_msg);
+ fprintf(log_fd, bb_msg);
GetLocalTime(<);
fprintf(log_fd, APPLICATION_NAME " bad blocks check ended on: %04d.%02d.%02d %02d:%02d:%02d\n",
lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
fclose(log_fd);
- safe_sprintf(&bb_msg[strlen(bb_msg)], sizeof(bb_msg)-strlen(bb_msg)-1,
- "\nA more detailed report can be found in:\n%s\n", logfile);
- r = MessageBoxU(hMainDialog, bb_msg, "Bad blocks found", MB_ABORTRETRYIGNORE|MB_ICONWARNING);
+ r = MessageBoxU(hMainDialog, lmprintf(MSG_012, bb_msg, logfile),
+ lmprintf(MSG_010), MB_ABORTRETRYIGNORE|MB_ICONWARNING);
} else {
// We didn't get any errors => delete the log file
fclose(log_fd);
@@ -1293,7 +1289,7 @@ DWORD WINAPI FormatThread(LPVOID param)
}
// Close the (unmounted) volume before formatting
if ((hLogicalVolume != NULL) && (hLogicalVolume != INVALID_HANDLE_VALUE)) {
- PrintStatus(0, TRUE, "Closing existing volume...\n");
+ PrintStatus(0, TRUE, lmprintf(MSG_227));
if (!CloseHandle(hLogicalVolume)) {
uprintf("Could not close volume: %s\n", WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
@@ -1339,7 +1335,7 @@ DWORD WINAPI FormatThread(LPVOID param)
// Thanks to Microsoft, we must fix the MBR AFTER the drive has been formatted
if (pt == PARTITION_STYLE_MBR) {
- PrintStatus(0, TRUE, "Writing master boot record...");
+ PrintStatus(0, TRUE, lmprintf(MSG_228));
if (!WriteMBR(hPhysicalDrive)) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
@@ -1386,7 +1382,7 @@ DWORD WINAPI FormatThread(LPVOID param)
}
// NB: if you unmount the logical volume here, XP will report error:
// [0x00000456] The media in the drive may have changed
- PrintStatus(0, TRUE, "Writing partition boot record...");
+ PrintStatus(0, TRUE, lmprintf(MSG_229));
if (!WritePBR(hLogicalVolume)) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
@@ -1415,7 +1411,7 @@ DWORD WINAPI FormatThread(LPVOID param)
if (IsChecked(IDC_BOOT)) {
if ((dt == DT_WINME) || (dt == DT_FREEDOS)) {
UpdateProgress(OP_DOS, -1.0f);
- PrintStatus(0, TRUE, "Copying DOS files...");
+ PrintStatus(0, TRUE, lmprintf(MSG_230));
if (!ExtractDOS(drive_name)) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
@@ -1424,7 +1420,7 @@ DWORD WINAPI FormatThread(LPVOID param)
} else if (dt == DT_ISO) {
if (iso_path != NULL) {
UpdateProgress(OP_DOS, 0.0f);
- PrintStatus(0, TRUE, "Copying ISO files...");
+ PrintStatus(0, TRUE, lmprintf(MSG_231));
drive_name[2] = 0;
if (!ExtractISO(iso_path, drive_name, FALSE)) {
if (!IS_ERROR(FormatStatus))
@@ -1433,7 +1429,7 @@ DWORD WINAPI FormatThread(LPVOID param)
}
if ((bt == BT_UEFI) && (!iso_report.has_efi) && (iso_report.has_win7_efi)) {
// TODO: (v1.4.0) check ISO with EFI only
- PrintStatus(0, TRUE, "Win7 EFI boot setup (this may take a while)...");
+ PrintStatus(0, TRUE, lmprintf(MSG_232));
wim_image[0] = drive_name[0];
efi_dst[0] = drive_name[0];
efi_dst[sizeof(efi_dst) - sizeof("\\bootx64.efi")] = 0;
@@ -1456,7 +1452,7 @@ DWORD WINAPI FormatThread(LPVOID param)
}
}
UpdateProgress(OP_FINALIZE, -1.0f);
- PrintStatus(0, TRUE, "Finalizing, please wait...");
+ PrintStatus(0, TRUE, lmprintf(MSG_233));
if (IsChecked(IDC_SET_ICON))
SetAutorun(drive_name);
// Issue another complete remount before we exit, to ensure we're clean
diff --git a/src/iso.c b/src/iso.c
index ada677f3..33364e11 100644
--- a/src/iso.c
+++ b/src/iso.c
@@ -41,6 +41,7 @@
#include "rufus.h"
#include "msapi_utf8.h"
#include "resource.h"
+#include "localization.h"
// How often should we update the progress bar (in 2K blocks) as updating
// the progress bar for every block will bring extraction to a crawl
@@ -77,16 +78,15 @@ static __inline char* size_to_hr(int64_t size)
{
int suffix = 0;
static char str_size[24];
- const char* sizes[] = { "", "KB", "MB", "GB", "TB" };
double hr_size = (double)size;
- while ((suffix < ARRAYSIZE(sizes)) && (hr_size >= 1024.0)) {
+ while ((suffix < MAX_SIZE_SUFFIXES) && (hr_size >= 1024.0)) {
hr_size /= 1024.0;
suffix++;
}
if (suffix == 0) {
- safe_sprintf(str_size, sizeof(str_size), " (%d bytes)", (int)hr_size);
+ safe_sprintf(str_size, sizeof(str_size), " (%d %s)", (int)hr_size, lmprintf(MSG_020));
} else {
- safe_sprintf(str_size, sizeof(str_size), " (%0.1f %s)", hr_size, sizes[suffix]);
+ safe_sprintf(str_size, sizeof(str_size), " (%0.1f %s)", hr_size, lmprintf(MSG_020+suffix));
}
return str_size;
}
@@ -419,7 +419,6 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
LONG progress_style;
char* tmp;
char path[64];
- const char* scan_text = "Scanning ISO image...";
const char* basedir[] = { "i386", "minint" };
const char* tmp_sif = ".\\txtsetup.sif~";
iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
@@ -437,14 +436,14 @@ BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
// String array of all isolinux/syslinux locations
StrArrayCreate(&config_path, 8);
// Change the Window title and static text
- SetWindowTextU(hISOProgressDlg, scan_text);
- SetWindowTextU(hISOFileName, scan_text);
+ SetWindowTextU(hISOProgressDlg, lmprintf(MSG_202));
+ SetWindowTextU(hISOFileName, lmprintf(MSG_202));
// Change progress style to marquee for scanning
SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style | PBS_MARQUEE);
SendMessage(hISOProgressBar, PBM_SETMARQUEE, TRUE, 0);
} else {
uprintf("Extracting files...\n");
- SetWindowTextU(hISOProgressDlg, "Copying ISO files...");
+ SetWindowTextU(hISOProgressDlg, lmprintf(MSG_231));
if (total_blocks == 0) {
uprintf("Error: ISO has not been properly scanned.\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
@@ -506,7 +505,7 @@ out:
iso_blocking_status = -1;
if (scan_only) {
// Remove trailing spaces from the label
- for (j=(int)safe_strlen(iso_report.label)-1; ((j>=0)&&(isspace(iso_report.label[j]))); j--)
+ for (j=(int)safe_strlen(iso_report.label)-1; ((j>=0)&&(isspaceU(iso_report.label[j]))); j--)
iso_report.label[j] = 0;
// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
diff --git a/src/license.h b/src/license.h
index a9331698..ce3b475c 100644
--- a/src/license.h
+++ b/src/license.h
@@ -19,16 +19,17 @@
const char* about_blurb_format =
"{\\rtf1\\ansi\n"
-"{\\b\\fs20Rufus - The Reliable USB Formatting Utility}\\line\n"
-"\\fs18Version %d.%d.%d (Build %d)\\line\n"
+"{\\b\\fs20%s}\\line\n"
+"\\fs18%s\\line\n"
"\\line\n"
"Copyright © 2011-2013 Pete Batard / Akeo\\line\n"
RUFUS_URL "\\line\n"
+"%s\\line\n"
"\\line\n"
-"Report bugs or request enhancements at:\\line\n"
+"%s\\line\n"
"https://github.com/pbatard/rufus/issues\\line\n"
"\\line\n"
-"{\\b\\fs18Additional Copyrights:}}";
+"{\\b\\fs18 %s}}";
const char* additional_copyrights =
"{\\rtf1\\ansi\n"
@@ -90,17 +91,15 @@ const char* additional_copyrights =
const char* update_policy =
"{\\rtf1\\ansi{\\fonttbl{\\f0\\fnil\\fcharset0 Microsoft Sans Serif;}{\\f1\\fnil\\fcharset2 Symbol;}}\n"
-"\\fs16\\b Update Policy:\\b0\\line\n"
-"If you choose to allow this program to check for application updates, you agree that the following information may be collected on our server(s):\\par\n"
-"\\pard{\\pntext\\f1\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\fi-150\\li220 Your operating system's architecture and version\\par\n"
-"{\\pntext\\f1\\'B7\\tab}The version of the application you use\\par\n"
-"{\\pntext\\f1\\'B7\\tab}Your IP address\\line\\pard\n"
+"\\fs16\\b %s\\b0\\line\n"
+"%s:\\par\n"
+"\\pard{\\pntext\\f1\\'B7\\tab}{\\*\\pn\\pnlvlblt\\pnf2\\pnindent0{\\pntxtb\\'B7}}\\fi-150\\li220 %s\\par\n"
+"{\\pntext\\f1\\'B7\\tab}%s\\par\n"
+"{\\pntext\\f1\\'B7\\tab}%s\\line\\pard\n"
"\\line\n"
-"For the purpose of generating private usage statistics, we may keep the information collected, \n"
-"\\b for at most a year\\b0 . However, we will not willingly disclose any of this individual data to third parties.\\line\n\\line\n"
-"\\b Update Process:\\b0\\line\n"
-APPLICATION_NAME " does not install or run background services, therefore update checks are performed only when the main application is running.\\line\n"
-"Internet access is of course required when checking for updates.\\line\n"
+"%s\\line\n\\line\n"
+"\\b %s\\b0\\line\n"
+"%s\\line\n"
"}";
const char* gplv3 =
diff --git a/src/localization.c b/src/localization.c
new file mode 100644
index 00000000..d4aa9ea6
--- /dev/null
+++ b/src/localization.c
@@ -0,0 +1,368 @@
+/*
+ * Rufus: The Reliable USB Formatting Utility
+ * Localization functions, a.k.a. "Everybody is doing it wrong but me!"
+ * Copyright © 2013 Pete Batard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */
+#ifdef _CRTDBG_MAP_ALLOC
+#include
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include "rufus.h"
+#include "resource.h"
+#include "msapi_utf8.h"
+#include "localization.h"
+#include "localization_data.h"
+
+/*
+ * List of supported locale commands, with their parameter syntax:
+ * c control ID (no space, no quotes)
+ * s: quoted string
+ * i: 32 bit signed integer
+ * u: 32 bit unsigned CSV list
+ * Remember to update the size of the array in localization.h when adding/removing elements
+ */
+const loc_parse parse_cmd[9] = {
+ // Translation name and Windows LCIDs it should apply to
+ { 'l', LC_LOCALE, "ssu" }, // l "en_US" "English (US)" 0x0009,0x1009
+ // Base translation to add on top of (eg. "English (UK)" can be used to build on top of "English (US)"
+ { 'b', LC_BASE, "s" }, // b "en_US"
+ // Version to use for the localization commandset and API
+ { 'v', LC_VERSION, "ii" }, // v 1.0 // TODO: NOT IMPLEMENTED YET
+ // Translate the text control associated with an ID
+ { 't', LC_TEXT, "cs" }, // t IDC_CONTROL "Translation"
+ // Set the section/dialog to which the next commands should apply
+ { 'g', LC_GROUP, "c" }, // g IDD_DIALOG
+ // Resize a dialog (dx dy pixel increment)
+ { 's', LC_SIZE, "cii" }, // s IDC_CONTROL +10 +10
+ // Move a dialog (dx dy pixed displacement)
+ { 'm', LC_MOVE, "cii" }, // m IDC_CONTROL -5 0
+ // Set the font to use for the text controls that follow
+ // Use f "Default" 0 to reset the font
+ { 'f', LC_FONT, "si" }, // f "MS Dialog" 10
+ // Set the direction to use for the text controls that follow
+ // 0 = Left to right, 1 = Right to left
+ { 'd', LC_DIRECTION, "i" }, // d 1 // TODO: NOT IMPLEMENTED YET
+};
+
+/* Globals */
+int loc_line_nr;
+struct list_head locale_list = {NULL, NULL};
+char *loc_filename = NULL, *embedded_loc_filename = "[embedded] rufus.loc";
+
+/*
+ * Add a localization command to a dialog/section
+ */
+void add_dialog_command(int index, loc_cmd* lcmd)
+{
+ if ((lcmd == NULL) || (index < 0) || (index >= ARRAYSIZE(loc_dlg))) {
+ uprintf("add_dialog_command: invalid parameter\n");
+ return;
+ }
+ list_add(&lcmd->list, &loc_dlg[index].list);
+}
+
+void free_loc_cmd(loc_cmd* lcmd)
+{
+ if (lcmd == NULL)
+ return;
+ safe_free(lcmd->txt[0]);
+ safe_free(lcmd->txt[1]);
+ safe_free(lcmd->unum);
+ free(lcmd);
+}
+
+void free_dialog_list(void)
+{
+ size_t i = 0;
+ loc_cmd *lcmd, *next;
+
+ for (i=0; ilist);
+ free_loc_cmd(lcmd);
+ }
+ }
+}
+
+void free_locale_list(void)
+{
+ loc_cmd *lcmd, *next;
+
+ list_for_each_entry_safe(lcmd, next, &locale_list, loc_cmd, list) {
+ list_del(&lcmd->list);
+ free_loc_cmd(lcmd);
+ }
+}
+
+/*
+ * Init/destroy our various localization lists
+ */
+void init_localization(void) {
+ size_t i;
+ for (i=0; icommand <= LC_TEXT) {
+ // Any command up to LC_TEXT takes a control ID in text[0]
+ for (i=0; itxt[0], control_id[i].name) == 0) {
+ lcmd->ctrl_id = control_id[i].id;
+ break;
+ }
+ }
+ if (lcmd->ctrl_id < 0) {
+ luprintf("unknown control '%s'\n", lcmd->txt[0]);
+ goto err;
+ }
+ }
+
+ switch(lcmd->command) {
+ // NB: For commands that take an ID, ctrl_id is always a valid index at this stage
+ case LC_TEXT:
+ case LC_MOVE:
+ case LC_SIZE:
+ add_dialog_command(dlg_index, lcmd);
+ break;
+ case LC_GROUP:
+ if ((lcmd->ctrl_id-IDD_DIALOG) > ARRAYSIZE(loc_dlg)) {
+ luprintf("'%s' is not a group ID\n", lcmd->txt[0]);
+ goto err;
+ }
+ dlg_index = lcmd->ctrl_id - IDD_DIALOG;
+ free_loc_cmd(lcmd);
+ break;
+ case LC_VERSION:
+ luprintf("GOT VERSION: %d.%d\n", lcmd->num[0], lcmd->num[1]);
+ free_loc_cmd(lcmd);
+ break;
+ case LC_BASE:
+ base_locale = get_locale_from_name(lcmd->txt[0]);
+ if (base_locale != NULL) {
+ uprintf("localization: using locale base '%s'", lcmd->txt[0]);
+ get_loc_data_file(NULL, (long)base_locale->num[0], (long)base_locale->num[1], base_locale->line_nr);
+ } else {
+ uprintf("localization: locale base '%s' not found", lcmd->txt[0]);
+ }
+ free_loc_cmd(lcmd);
+ break;
+ default:
+ free_loc_cmd(lcmd);
+ break;
+ }
+ return TRUE;
+
+err:
+ free_loc_cmd(lcmd);
+ return FALSE;
+}
+
+/*
+ * Apply stored localization commands to a specific dialog
+ * If hDlg is NULL, apply the commands against an active Window
+ * TODO: if dlg_id is <0, apply all
+ */
+void apply_localization(int dlg_id, HWND hDlg)
+{
+ loc_cmd* lcmd;
+ HWND hCtrl = NULL;
+ int id_start = IDD_DIALOG, id_end = IDD_DIALOG + ARRAYSIZE(loc_dlg);
+ LONG_PTR style;
+ BOOL left_to_right = FALSE;
+
+ if ((dlg_id >= id_start) && (dlg_id < id_end)) {
+ // If we have a valid dialog_id, just process that one dialog
+ id_start = dlg_id;
+ id_end = dlg_id + 1;
+ if (hDlg != NULL) {
+ loc_dlg[dlg_id-IDD_DIALOG].hDlg = hDlg;
+ }
+ }
+
+ for (dlg_id = id_start; dlg_id < id_end; dlg_id++) {
+ hDlg = loc_dlg[dlg_id-IDD_DIALOG].hDlg;
+ if ((!IsWindow(hDlg)) || (list_empty(&loc_dlg[dlg_id-IDD_DIALOG].list)))
+ continue;
+
+ // TODO: storing the messages in an array indexed on the message ID - 3000 would be faster
+ list_for_each_entry(lcmd, &loc_dlg[dlg_id-IDD_DIALOG].list, loc_cmd, list) {
+ if (lcmd->command <= LC_TEXT) { // TODO: should always be the case
+ if (lcmd->ctrl_id == dlg_id) {
+ if ((dlg_id == IDD_DIALOG) && (lcmd->txt[1] != NULL) && (lcmd->txt[1][0] != 0)) {
+ loc_line_nr = lcmd->line_nr;
+ luprint("operation forbidden (main dialog title cannot be changed)");
+ continue;
+ }
+ hCtrl = hDlg;
+ } else {
+ hCtrl = GetDlgItem(hDlg, lcmd->ctrl_id);
+ }
+ if (hCtrl == NULL) {
+ loc_line_nr = lcmd->line_nr;
+ luprintf("control '%s' is not part of dialog '%s'\n",
+ lcmd->txt[0], control_id[dlg_id-IDD_DIALOG].name);
+ }
+ }
+
+ switch(lcmd->command) {
+ // NB: For commands that take an ID, ctrl_id is always a valid index at this stage
+ case LC_TEXT:
+ if (hCtrl != NULL) {
+ if ((lcmd->txt[1] != NULL) && (lcmd->txt[1][0] != 0))
+ SetWindowTextU(hCtrl, lcmd->txt[1]);
+ if (left_to_right) {
+ style = GetWindowLongPtr(hCtrl, GWL_EXSTYLE);
+ style |= WS_EX_LAYOUTRTL; // WS_EX_RIGHT | WS_EX_RTLREADING
+ SetWindowLongPtr(hCtrl, GWL_EXSTYLE, style);
+ InvalidateRect(hCtrl, NULL, TRUE);
+ }
+ }
+ break;
+ case LC_MOVE:
+ if (hCtrl != NULL) {
+ ResizeMoveCtrl(hDlg, hCtrl, lcmd->num[0], lcmd->num[1], 0, 0);
+ }
+ break;
+ case LC_SIZE:
+ if (hCtrl != NULL) {
+ ResizeMoveCtrl(hDlg, hCtrl, 0, 0, lcmd->num[0], lcmd->num[1]);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * This function should be called when a localized dialog is destroyed
+ * NB: we can't use isWindow() against our existing HWND to avoid this call
+ * as handles are recycled.
+ */
+void reset_localization(int dlg_id)
+{
+ loc_dlg[dlg_id-IDD_DIALOG].hDlg = NULL;
+}
+
+/*
+ * Produce a formatted localized message.
+ * Like printf, this call takes a variable number of argument, and uses
+ * the message ID to identify the formatted message to use.
+ * Uses a rolling list of buffers to allow concurrency
+ * TODO: use dynamic realloc'd buffer in case LOC_MESSAGE_SIZE is not enough
+ */
+char* lmprintf(int msg_id, ...)
+{
+ static int buf_id = 0;
+ static char buf[LOC_MESSAGE_NB][LOC_MESSAGE_SIZE];
+ char *format = NULL;
+ va_list args;
+ loc_cmd* lcmd;
+ buf_id %= LOC_MESSAGE_NB;
+ buf[buf_id][0] = 0;
+ list_for_each_entry(lcmd, &loc_dlg[IDD_MESSAGES-IDD_DIALOG].list, loc_cmd, list) {
+ if ((lcmd->command == LC_TEXT) && (lcmd->ctrl_id == msg_id) && (lcmd->txt[1] != NULL)) {
+ format = lcmd->txt[1];
+ }
+ }
+
+ if (format == NULL) {
+ safe_sprintf(buf[buf_id], LOC_MESSAGE_SIZE-1, "MSG_%03d UNTRANSLATED", msg_id - MSG_000);
+ } else {
+ va_start(args, msg_id);
+ safe_vsnprintf(buf[buf_id], LOC_MESSAGE_SIZE-1, format, args);
+ va_end(args);
+ buf[buf_id][LOC_MESSAGE_SIZE-1] = '\0';
+ }
+ return buf[buf_id++];
+}
+
+/*
+ * These 2 functions are used to set the current locale
+ */
+loc_cmd* get_locale_from_lcid(int lcid)
+{
+ loc_cmd* lcmd = NULL;
+ int i;
+
+ if (list_empty(&locale_list)) {
+ uprintf("localization: the locale list is empty!\n");
+ return NULL;
+ }
+
+ list_for_each_entry(lcmd, &locale_list, loc_cmd, list) {
+ for (i=0; iunum_size; i++) {
+ if (lcmd->unum[i] == lcid) {
+ return lcmd;
+ }
+ }
+ }
+
+ lcmd = list_entry(locale_list.next, loc_cmd, list);
+ // If we couldn't find a supported locale, just pick the first one (usually English)
+ uprintf("localization: could not find locale for LCID: 0x%04X. Will default to '%s'\n", lcid, lcmd->txt[0]);
+ return lcmd;
+}
+
+loc_cmd* get_locale_from_name(char* locale_name)
+{
+ loc_cmd* lcmd = NULL;
+
+ if (list_empty(&locale_list)) {
+ uprintf("localization: the locale list is empty!\n");
+ return NULL;
+ }
+
+ list_for_each_entry(lcmd, &locale_list, loc_cmd, list) {
+ if (safe_strcmp(lcmd->txt[0], locale_name) == 0)
+ return lcmd;
+ }
+
+ lcmd = list_entry(locale_list.next, loc_cmd, list);
+ uprintf("localization: could not find locale for name '%s'. Will default to '%s'\n", locale_name, lcmd->txt[0]);
+ return lcmd;
+}
diff --git a/src/localization.h b/src/localization.h
new file mode 100644
index 00000000..23d6919b
--- /dev/null
+++ b/src/localization.h
@@ -0,0 +1,158 @@
+/*
+ * Rufus: The Reliable USB Formatting Utility
+ * Localization functions, a.k.a. "Everybody is doing it wrong but me!"
+ * Copyright © 2013 Pete Batard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#pragma once
+
+// Number of concurrent localization messages. Must be a power of 2.
+#define LOC_MESSAGE_NB 8
+#define LOC_MESSAGE_SIZE 2048
+
+#define luprint(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr)
+#define luprintf(msg, ...) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr, __VA_ARGS__)
+
+/*
+ * List handling functions (stolen from libusb)
+ * NB: offsetof() requires '#include '
+ */
+struct list_head {
+ struct list_head *prev, *next;
+};
+
+/* Get an entry from the list
+ * ptr - the address of this list_head element in "type"
+ * type - the data type that contains "member"
+ * member - the list_head element in "type"
+ */
+#define list_entry(ptr, type, member) \
+ ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member)))
+
+/* Get each entry from a list
+ * pos - A structure pointer has a "member" element
+ * head - list head
+ * member - the list_head element in "pos"
+ * type - the type of the first parameter
+ */
+#define list_for_each_entry(pos, head, type, member) \
+ for (pos = list_entry((head)->next, type, member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, type, member))
+
+
+#define list_for_each_entry_safe(pos, n, head, type, member) \
+ for (pos = list_entry((head)->next, type, member), \
+ n = list_entry(pos->member.next, type, member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, type, member))
+
+#define list_empty(entry) ((entry)->next == (entry))
+
+static __inline void list_init(struct list_head *entry)
+{
+ entry->prev = entry->next = entry;
+}
+
+static __inline void list_add(struct list_head *entry, struct list_head *head)
+{
+ entry->next = head->next;
+ entry->prev = head;
+
+ head->next->prev = entry;
+ head->next = entry;
+}
+
+static __inline void list_add_tail(struct list_head *entry,
+ struct list_head *head)
+{
+ entry->next = head;
+ entry->prev = head->prev;
+
+ head->prev->next = entry;
+ head->prev = entry;
+}
+
+static __inline void list_del(struct list_head *entry)
+{
+ entry->next->prev = entry->prev;
+ entry->prev->next = entry->next;
+ entry->next = entry->prev = NULL;
+}
+
+// Commands that take a control ID *MUST* be at the top
+// The last command with a control ID *MUST* be LC_TEXT
+enum loc_command_type {
+ LC_GROUP,
+ LC_MOVE,
+ LC_SIZE,
+ LC_TEXT, // Delimits commands that take a Control ID and commands that don't
+ LC_VERSION,
+ LC_LOCALE,
+ LC_BASE,
+ LC_FONT,
+ LC_DIRECTION,
+};
+
+typedef struct loc_cmd_struct {
+ uint8_t command;
+ uint8_t unum_size;
+ uint16_t line_nr;
+ int ctrl_id;
+ int32_t num[2];
+ uint32_t* unum;
+ char* txt[2];
+ struct list_head list;
+} loc_cmd;
+
+typedef struct loc_parse_struct {
+ char c;
+ enum loc_command_type cmd;
+ char* arg_type;
+} loc_parse;
+
+typedef struct loc_control_id_struct {
+ const char* name;
+ const int id;
+} loc_control_id;
+
+typedef struct loc_dlg_list_struct {
+ const int dlg_id;
+ HWND hDlg;
+ struct list_head list;
+} loc_dlg_list;
+
+extern const loc_parse parse_cmd[9];
+extern struct list_head locale_list;
+int loc_line_nr;
+char *loc_filename, *embedded_loc_filename;
+
+void free_loc_cmd(loc_cmd* lcmd);
+BOOL dispatch_loc_cmd(loc_cmd* lcmd);
+void init_localization(void);
+void exit_localization(void);
+void apply_localization(int dlg_id, HWND hDlg);
+void reset_localization(int dlg_id);
+void free_dialog_list(void);
+char* lmprintf(int msg_id, ...);
+BOOL get_supported_locales(const char* filename);
+char* get_loc_data_file(const char* filename, long offset, long end_offset, int start_line);
+void free_locale_list(void);
+loc_cmd* get_locale_from_lcid(int lcid);
+loc_cmd* get_locale_from_name(char* locale_name);
diff --git a/src/localization_data.h b/src/localization_data.h
new file mode 100644
index 00000000..d449886c
--- /dev/null
+++ b/src/localization_data.h
@@ -0,0 +1,382 @@
+/*
+ * Rufus: The Reliable USB Formatting Utility
+ * Localization tables - autogenerated from resource.h
+ * Copyright © 2013 Pete Batard
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include "resource.h"
+#include "localization.h"
+
+#define LOC_CTRL(x) { #x, x }
+#define LOC_DLG(x) { x, NULL, {NULL, NULL} }
+
+// Control IDs
+const loc_control_id control_id[] = {
+ // The dialog IDs must come first
+ LOC_CTRL(IDD_DIALOG),
+ LOC_CTRL(IDD_ABOUTBOX),
+ LOC_CTRL(IDD_NOTIFICATION),
+ LOC_CTRL(IDD_LICENSE),
+ LOC_CTRL(IDD_ISO_EXTRACT),
+ LOC_CTRL(IDD_LOG),
+ LOC_CTRL(IDD_UPDATE_POLICY),
+ LOC_CTRL(IDD_NEW_VERSION),
+ LOC_CTRL(IDD_MESSAGES),
+ LOC_CTRL(IDC_DEVICE),
+ LOC_CTRL(IDC_FILESYSTEM),
+ LOC_CTRL(IDC_START),
+ LOC_CTRL(IDC_PARTITION_TYPE),
+ LOC_CTRL(IDC_CLUSTERSIZE),
+ LOC_CTRL(IDC_STATUS),
+ LOC_CTRL(IDC_ABOUT),
+ LOC_CTRL(IDC_LABEL),
+ LOC_CTRL(IDC_QUICKFORMAT),
+ LOC_CTRL(IDC_BOOT),
+ LOC_CTRL(IDC_BADBLOCKS),
+ LOC_CTRL(IDC_PROGRESS),
+ LOC_CTRL(IDC_BOOTTYPE),
+ LOC_CTRL(IDC_NBPASSES),
+ LOC_CTRL(IDC_TEST),
+ LOC_CTRL(IDC_SELECT_ISO),
+ LOC_CTRL(IDC_SET_ICON),
+ LOC_CTRL(IDC_RUFUS_MBR),
+ LOC_CTRL(IDC_ISO_FILENAME),
+ LOC_CTRL(IDC_ISO_ABORT),
+ LOC_CTRL(IDC_DISK_ID),
+ LOC_CTRL(IDC_EXTRA_PARTITION),
+ LOC_CTRL(IDC_ENABLE_FIXED_DISKS),
+ LOC_CTRL(IDC_ABOUT_LICENSE),
+ LOC_CTRL(IDC_ABOUT_ICON),
+ LOC_CTRL(IDC_ABOUT_UPDATES),
+ LOC_CTRL(IDC_ABOUT_COPYRIGHTS),
+ LOC_CTRL(IDC_ABOUT_BLURB),
+ LOC_CTRL(IDC_LICENSE_TEXT),
+ LOC_CTRL(IDC_NOTIFICATION_ICON),
+ LOC_CTRL(IDC_NOTIFICATION_TEXT),
+ LOC_CTRL(IDC_NOTIFICATION_LINE),
+ LOC_CTRL(IDC_ADVANCED),
+ LOC_CTRL(IDS_ADVANCED_OPTIONS_GRP),
+ LOC_CTRL(IDC_LOG),
+ LOC_CTRL(IDC_LOG_EDIT),
+ LOC_CTRL(IDC_LOG_SAVE),
+ LOC_CTRL(IDC_LOG_CLEAR),
+ LOC_CTRL(IDC_MORE_INFO),
+ LOC_CTRL(IDC_POLICY),
+ LOC_CTRL(IDC_UPDATE_FREQUENCY),
+ LOC_CTRL(IDC_INCLUDE_BETAS),
+ LOC_CTRL(IDC_RELEASE_NOTES),
+ LOC_CTRL(IDC_DOWNLOAD),
+ LOC_CTRL(IDC_CHECK_NOW),
+ LOC_CTRL(IDC_WEBSITE),
+ LOC_CTRL(IDC_YOUR_VERSION),
+ LOC_CTRL(IDC_LATEST_VERSION),
+ LOC_CTRL(IDC_DOWNLOAD_URL),
+ LOC_CTRL(IDS_DEVICE_TXT),
+ LOC_CTRL(IDS_PARTITION_TYPE_TXT),
+ LOC_CTRL(IDS_FILESYSTEM_TXT),
+ LOC_CTRL(IDS_CLUSTERSIZE_TXT),
+ LOC_CTRL(IDS_LABEL_TXT),
+ LOC_CTRL(IDS_FORMAT_OPTIONS_GRP),
+ LOC_CTRL(IDS_UPDATE_SETTINGS_GRP),
+ LOC_CTRL(IDS_UPDATE_FREQUENCY_TXT),
+ LOC_CTRL(IDS_INCLUDE_BETAS_TXT),
+ LOC_CTRL(IDS_NEW_VERSION_AVAIL_TXT),
+ LOC_CTRL(IDS_NEW_VERSION_DOWNLOAD_GRP),
+ LOC_CTRL(IDS_NEW_VERSION_NOTES_GRP),
+ LOC_CTRL(IDS_CHECK_NOW_GRP),
+ LOC_CTRL(MSG_000),
+ LOC_CTRL(MSG_001),
+ LOC_CTRL(MSG_002),
+ LOC_CTRL(MSG_003),
+ LOC_CTRL(MSG_004),
+ LOC_CTRL(MSG_005),
+ LOC_CTRL(MSG_006),
+ LOC_CTRL(MSG_007),
+ LOC_CTRL(MSG_008),
+ LOC_CTRL(MSG_009),
+ LOC_CTRL(MSG_010),
+ LOC_CTRL(MSG_011),
+ LOC_CTRL(MSG_012),
+ LOC_CTRL(MSG_013),
+ LOC_CTRL(MSG_014),
+ LOC_CTRL(MSG_015),
+ LOC_CTRL(MSG_016),
+ LOC_CTRL(MSG_017),
+ LOC_CTRL(MSG_018),
+ LOC_CTRL(MSG_019),
+ LOC_CTRL(MSG_020),
+ LOC_CTRL(MSG_021),
+ LOC_CTRL(MSG_022),
+ LOC_CTRL(MSG_023),
+ LOC_CTRL(MSG_024),
+ LOC_CTRL(MSG_025),
+ LOC_CTRL(MSG_026),
+ LOC_CTRL(MSG_027),
+ LOC_CTRL(MSG_028),
+ LOC_CTRL(MSG_029),
+ LOC_CTRL(MSG_030),
+ LOC_CTRL(MSG_031),
+ LOC_CTRL(MSG_032),
+ LOC_CTRL(MSG_033),
+ LOC_CTRL(MSG_034),
+ LOC_CTRL(MSG_035),
+ LOC_CTRL(MSG_036),
+ LOC_CTRL(MSG_037),
+ LOC_CTRL(MSG_038),
+ LOC_CTRL(MSG_039),
+ LOC_CTRL(MSG_040),
+ LOC_CTRL(MSG_041),
+ LOC_CTRL(MSG_042),
+ LOC_CTRL(MSG_043),
+ LOC_CTRL(MSG_044),
+ LOC_CTRL(MSG_045),
+ LOC_CTRL(MSG_046),
+ LOC_CTRL(MSG_047),
+ LOC_CTRL(MSG_048),
+ LOC_CTRL(MSG_049),
+ LOC_CTRL(MSG_050),
+ LOC_CTRL(MSG_051),
+ LOC_CTRL(MSG_052),
+ LOC_CTRL(MSG_053),
+ LOC_CTRL(MSG_054),
+ LOC_CTRL(MSG_055),
+ LOC_CTRL(MSG_056),
+ LOC_CTRL(MSG_057),
+ LOC_CTRL(MSG_058),
+ LOC_CTRL(MSG_059),
+ LOC_CTRL(MSG_060),
+ LOC_CTRL(MSG_061),
+ LOC_CTRL(MSG_062),
+ LOC_CTRL(MSG_063),
+ LOC_CTRL(MSG_064),
+ LOC_CTRL(MSG_065),
+ LOC_CTRL(MSG_066),
+ LOC_CTRL(MSG_067),
+ LOC_CTRL(MSG_068),
+ LOC_CTRL(MSG_069),
+ LOC_CTRL(MSG_070),
+ LOC_CTRL(MSG_071),
+ LOC_CTRL(MSG_072),
+ LOC_CTRL(MSG_073),
+ LOC_CTRL(MSG_074),
+ LOC_CTRL(MSG_075),
+ LOC_CTRL(MSG_076),
+ LOC_CTRL(MSG_077),
+ LOC_CTRL(MSG_078),
+ LOC_CTRL(MSG_079),
+ LOC_CTRL(MSG_080),
+ LOC_CTRL(MSG_081),
+ LOC_CTRL(MSG_082),
+ LOC_CTRL(MSG_083),
+ LOC_CTRL(MSG_084),
+ LOC_CTRL(MSG_085),
+ LOC_CTRL(MSG_086),
+ LOC_CTRL(MSG_087),
+ LOC_CTRL(MSG_088),
+ LOC_CTRL(MSG_089),
+ LOC_CTRL(MSG_090),
+ LOC_CTRL(MSG_091),
+ LOC_CTRL(MSG_092),
+ LOC_CTRL(MSG_093),
+ LOC_CTRL(MSG_094),
+ LOC_CTRL(MSG_095),
+ LOC_CTRL(MSG_096),
+ LOC_CTRL(MSG_097),
+ LOC_CTRL(MSG_098),
+ LOC_CTRL(MSG_099),
+ LOC_CTRL(MSG_100),
+ LOC_CTRL(MSG_101),
+ LOC_CTRL(MSG_102),
+ LOC_CTRL(MSG_103),
+ LOC_CTRL(MSG_104),
+ LOC_CTRL(MSG_105),
+ LOC_CTRL(MSG_106),
+ LOC_CTRL(MSG_107),
+ LOC_CTRL(MSG_108),
+ LOC_CTRL(MSG_109),
+ LOC_CTRL(MSG_110),
+ LOC_CTRL(MSG_111),
+ LOC_CTRL(MSG_112),
+ LOC_CTRL(MSG_113),
+ LOC_CTRL(MSG_114),
+ LOC_CTRL(MSG_115),
+ LOC_CTRL(MSG_116),
+ LOC_CTRL(MSG_117),
+ LOC_CTRL(MSG_118),
+ LOC_CTRL(MSG_119),
+ LOC_CTRL(MSG_120),
+ LOC_CTRL(MSG_121),
+ LOC_CTRL(MSG_122),
+ LOC_CTRL(MSG_123),
+ LOC_CTRL(MSG_124),
+ LOC_CTRL(MSG_125),
+ LOC_CTRL(MSG_126),
+ LOC_CTRL(MSG_127),
+ LOC_CTRL(MSG_128),
+ LOC_CTRL(MSG_129),
+ LOC_CTRL(MSG_130),
+ LOC_CTRL(MSG_131),
+ LOC_CTRL(MSG_132),
+ LOC_CTRL(MSG_133),
+ LOC_CTRL(MSG_134),
+ LOC_CTRL(MSG_135),
+ LOC_CTRL(MSG_136),
+ LOC_CTRL(MSG_137),
+ LOC_CTRL(MSG_138),
+ LOC_CTRL(MSG_139),
+ LOC_CTRL(MSG_140),
+ LOC_CTRL(MSG_141),
+ LOC_CTRL(MSG_142),
+ LOC_CTRL(MSG_143),
+ LOC_CTRL(MSG_144),
+ LOC_CTRL(MSG_145),
+ LOC_CTRL(MSG_146),
+ LOC_CTRL(MSG_147),
+ LOC_CTRL(MSG_148),
+ LOC_CTRL(MSG_149),
+ LOC_CTRL(MSG_150),
+ LOC_CTRL(MSG_151),
+ LOC_CTRL(MSG_152),
+ LOC_CTRL(MSG_153),
+ LOC_CTRL(MSG_154),
+ LOC_CTRL(MSG_155),
+ LOC_CTRL(MSG_156),
+ LOC_CTRL(MSG_157),
+ LOC_CTRL(MSG_158),
+ LOC_CTRL(MSG_159),
+ LOC_CTRL(MSG_160),
+ LOC_CTRL(MSG_161),
+ LOC_CTRL(MSG_162),
+ LOC_CTRL(MSG_163),
+ LOC_CTRL(MSG_164),
+ LOC_CTRL(MSG_165),
+ LOC_CTRL(MSG_166),
+ LOC_CTRL(MSG_167),
+ LOC_CTRL(MSG_168),
+ LOC_CTRL(MSG_169),
+ LOC_CTRL(MSG_170),
+ LOC_CTRL(MSG_171),
+ LOC_CTRL(MSG_172),
+ LOC_CTRL(MSG_173),
+ LOC_CTRL(MSG_174),
+ LOC_CTRL(MSG_175),
+ LOC_CTRL(MSG_176),
+ LOC_CTRL(MSG_177),
+ LOC_CTRL(MSG_178),
+ LOC_CTRL(MSG_179),
+ LOC_CTRL(MSG_180),
+ LOC_CTRL(MSG_181),
+ LOC_CTRL(MSG_182),
+ LOC_CTRL(MSG_183),
+ LOC_CTRL(MSG_184),
+ LOC_CTRL(MSG_185),
+ LOC_CTRL(MSG_186),
+ LOC_CTRL(MSG_187),
+ LOC_CTRL(MSG_188),
+ LOC_CTRL(MSG_189),
+ LOC_CTRL(MSG_190),
+ LOC_CTRL(MSG_191),
+ LOC_CTRL(MSG_192),
+ LOC_CTRL(MSG_193),
+ LOC_CTRL(MSG_194),
+ LOC_CTRL(MSG_195),
+ LOC_CTRL(MSG_196),
+ LOC_CTRL(MSG_197),
+ LOC_CTRL(MSG_198),
+ LOC_CTRL(MSG_199),
+ LOC_CTRL(MSG_200),
+ LOC_CTRL(MSG_201),
+ LOC_CTRL(MSG_202),
+ LOC_CTRL(MSG_203),
+ LOC_CTRL(MSG_204),
+ LOC_CTRL(MSG_205),
+ LOC_CTRL(MSG_206),
+ LOC_CTRL(MSG_207),
+ LOC_CTRL(MSG_208),
+ LOC_CTRL(MSG_209),
+ LOC_CTRL(MSG_210),
+ LOC_CTRL(MSG_211),
+ LOC_CTRL(MSG_212),
+ LOC_CTRL(MSG_213),
+ LOC_CTRL(MSG_214),
+ LOC_CTRL(MSG_215),
+ LOC_CTRL(MSG_216),
+ LOC_CTRL(MSG_217),
+ LOC_CTRL(MSG_218),
+ LOC_CTRL(MSG_219),
+ LOC_CTRL(MSG_220),
+ LOC_CTRL(MSG_221),
+ LOC_CTRL(MSG_222),
+ LOC_CTRL(MSG_223),
+ LOC_CTRL(MSG_224),
+ LOC_CTRL(MSG_225),
+ LOC_CTRL(MSG_226),
+ LOC_CTRL(MSG_227),
+ LOC_CTRL(MSG_228),
+ LOC_CTRL(MSG_229),
+ LOC_CTRL(MSG_230),
+ LOC_CTRL(MSG_231),
+ LOC_CTRL(MSG_232),
+ LOC_CTRL(MSG_233),
+ LOC_CTRL(MSG_234),
+ LOC_CTRL(MSG_235),
+ LOC_CTRL(MSG_236),
+ LOC_CTRL(MSG_237),
+ LOC_CTRL(MSG_238),
+ LOC_CTRL(MSG_239),
+ LOC_CTRL(MSG_240),
+ LOC_CTRL(MSG_241),
+ LOC_CTRL(MSG_242),
+ LOC_CTRL(MSG_243),
+ LOC_CTRL(MSG_244),
+ LOC_CTRL(MSG_245),
+ LOC_CTRL(MSG_246),
+ LOC_CTRL(MSG_247),
+ LOC_CTRL(MSG_248),
+ LOC_CTRL(MSG_249),
+ LOC_CTRL(MSG_250),
+ LOC_CTRL(MSG_251),
+ LOC_CTRL(MSG_252),
+ LOC_CTRL(MSG_253),
+ LOC_CTRL(MSG_254),
+ LOC_CTRL(MSG_255),
+ LOC_CTRL(MSG_256),
+ LOC_CTRL(MSG_257),
+ LOC_CTRL(MSG_258),
+ LOC_CTRL(IDOK),
+ LOC_CTRL(IDCANCEL),
+ LOC_CTRL(IDABORT),
+ LOC_CTRL(IDRETRY),
+ LOC_CTRL(IDIGNORE),
+ LOC_CTRL(IDYES),
+ LOC_CTRL(IDNO),
+ LOC_CTRL(IDCLOSE),
+ LOC_CTRL(IDHELP),
+};
+
+// Dialog data
+loc_dlg_list loc_dlg[] = {
+ LOC_DLG(IDD_DIALOG),
+ LOC_DLG(IDD_ABOUTBOX),
+ LOC_DLG(IDD_NOTIFICATION),
+ LOC_DLG(IDD_LICENSE),
+ LOC_DLG(IDD_ISO_EXTRACT),
+ LOC_DLG(IDD_LOG),
+ LOC_DLG(IDD_UPDATE_POLICY),
+ LOC_DLG(IDD_NEW_VERSION),
+ LOC_DLG(IDD_MESSAGES),
+};
diff --git a/src/localization_data.sh b/src/localization_data.sh
new file mode 100644
index 00000000..64f78465
--- /dev/null
+++ b/src/localization_data.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+echo This file recreates localization_data.c according resource.h
+echo
+
+# check that sed are available
+type -P sed &>/dev/null || { echo "sed command not found. Aborting." >&2; exit 1; }
+
+# Create the first sed command file
+cat > cmd.sed <<\_EOF
+# Insert header
+1i /*\
+ * Rufus: The Reliable USB Formatting Utility\
+ * Localization tables - autogenerated from resource.h\
+ * Copyright © 2013 Pete Batard \
+ *\
+ * This program is free software: you can redistribute it and/or modify\
+ * it under the terms of the GNU General Public License as published by\
+ * the Free Software Foundation, either version 3 of the License, or\
+ * (at your option) any later version.\
+ *\
+ * This program is distributed in the hope that it will be useful,\
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\
+ * GNU General Public License for more details.\
+ *\
+ * You should have received a copy of the GNU General Public License\
+ * along with this program. If not, see .\
+ */\
+\
+#include \
+#include "resource.h"\
+#include "localization.h"\
+\
+#define LOC_CTRL(x) { #x, x }\
+#define LOC_DLG(x) { x, NULL, {NULL, NULL} }\
+\
+// Control IDs\
+const loc_control_id control_id[] = {\
+ // The dialog IDs must come first
+
+# Add the control entries - must be in IDD_, IDC_, IDS_ or MSG_
+s/^#define \([I|M][D|S][D|C|S|G]_[^ ]*\) .*/\ LOC_CTRL(\1),/
+
+# Add standard IDs from windows.h and close table
+$a\
+ LOC_CTRL(IDOK),\
+ LOC_CTRL(IDCANCEL),\
+ LOC_CTRL(IDABORT),\
+ LOC_CTRL(IDRETRY),\
+ LOC_CTRL(IDIGNORE),\
+ LOC_CTRL(IDYES),\
+ LOC_CTRL(IDNO),\
+ LOC_CTRL(IDCLOSE),\
+ LOC_CTRL(IDHELP),\
+\};\
+
+# Remove everything else
+/^[#|\/]/d
+/^$/d
+_EOF
+
+# Run first part
+sed -f cmd.sed resource.h > localization_data.h
+
+# Create the second sed command file
+cat > cmd.sed <<\_EOF
+
+# Insert dialog table header
+1i // Dialog data\
+loc_dlg_list loc_dlg[] = {
+
+# Add the dialog entries - must start with IDD_
+s/^#define \(IDD_[^ ]*\) .*/\ LOC_DLG(\1),/
+
+# Close the table
+$a\
+};
+
+# Remove everything else
+/^[#|\/]/d
+/^$/d
+_EOF
+
+# Run second part
+sed -f cmd.sed resource.h >> localization_data.h
+
+rm cmd.sed
+echo Done.
diff --git a/src/msapi_utf8.h b/src/msapi_utf8.h
index 80dce69b..4a0d1ea9 100644
--- a/src/msapi_utf8.h
+++ b/src/msapi_utf8.h
@@ -1,6 +1,7 @@
/*
* MSAPI_UTF8: Common API calls using UTF-8 strings
* Compensating for what Microsoft should have done a long long time ago.
+ * Also see http://utf8everywhere.org/
*
* Copyright © 2010-2013 Pete Batard
*
@@ -53,6 +54,15 @@ extern "C" {
_ms_wlvi.pszText = utf8_to_wchar(pszText_); \
SNDMSG((hwndLV),LVM_SETITEMTEXTW,(WPARAM)(i),(LPARAM)&_ms_wlvi); sfree(_ms_wlvi.pszText);}
+// Never ever use isdigit() or isspace(), etc. on UTF-8 strings!
+// These calls take an int and char is signed so MS compilers will produce an assert error on anything that's > 0x80
+#define isasciiU(c) isascii((unsigned char)(c))
+#define iscntrlU(c) iscntrl((unsigned char)(c))
+#define isdigitU(c) isdigit((unsigned char)(c))
+#define isspaceU(c) isspace((unsigned char)(c))
+#define isxdigitU(c) isxdigit((unsigned char)(c))
+// NB: other issomething() calls are not implemented as they may require multibyte UTF-8 sequences to be converted
+
#define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
#define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p)
#define walloc(p, size) wchar_t* w ## p = (wchar_t*)calloc(size, sizeof(wchar_t))
@@ -354,6 +364,38 @@ static __inline DWORD GetCurrentDirectoryU(DWORD nBufferLength, char* lpBuffer)
return ret;
}
+static __inline DWORD GetTempPathU(DWORD nBufferLength, char* lpBuffer)
+{
+ DWORD ret = 0, err = ERROR_INVALID_DATA;
+ walloc(lpBuffer, nBufferLength);
+ ret = GetTempPathW(nBufferLength, wlpBuffer);
+ err = GetLastError();
+ if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferLength)) == 0)) {
+ err = GetLastError();
+ }
+ wfree(lpBuffer);
+ SetLastError(err);
+ return ret;
+}
+
+static __inline DWORD GetTempFileNameU(char* lpPathName, char* lpPrefixString, UINT uUnique, char* lpTempFileName)
+{
+ DWORD ret = 0, err = ERROR_INVALID_DATA;
+ wconvert(lpPathName);
+ wconvert(lpPrefixString);
+ walloc(lpTempFileName, MAX_PATH);
+ ret =GetTempFileNameW(wlpPathName, wlpPrefixString, uUnique, wlpTempFileName);
+ err = GetLastError();
+ if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpTempFileName, lpTempFileName, MAX_PATH)) == 0)) {
+ err = GetLastError();
+ }
+ wfree(lpTempFileName);
+ wfree(lpPrefixString);
+ wfree(lpPathName);
+ SetLastError(err);
+ return ret;
+}
+
static __inline DWORD GetModuleFileNameU(HMODULE hModule, char* lpFilename, DWORD nSize)
{
DWORD ret = 0, err = ERROR_INVALID_DATA;
diff --git a/src/net.c b/src/net.c
index cc83c9e4..e06c3a6a 100644
--- a/src/net.c
+++ b/src/net.c
@@ -34,6 +34,7 @@
#include "rufus.h"
#include "registry.h"
#include "resource.h"
+#include "localization.h"
/* Maximum download chunk size, in bytes */
#define DOWNLOAD_BUFFER_SIZE 10240
@@ -89,6 +90,7 @@ const char* WinInetErrorString(void)
if ((error_code < INTERNET_ERROR_BASE) || (error_code > INTERNET_ERROR_LAST))
return WindowsErrorString();
+ // TODO: These should be localized on an ad-hoc basis
switch(error_code) {
case ERROR_INTERNET_OUT_OF_HANDLES:
return "No more handles could be generated at this time.";
@@ -263,7 +265,7 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog)
SendMessage(hProgressDialog, UM_ISO_INIT, 0, 0);
}
- PrintStatus(0, FALSE, "Downloading %s: Connecting...\n", file);
+ PrintStatus(0, FALSE, lmprintf(MSG_240, file));
uprintf("Downloading %s from %s\n", file, url);
if (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) {
@@ -340,7 +342,7 @@ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog)
break;
dwSize += dwDownloaded;
SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
- PrintStatus(0, FALSE, "Downloading: %0.1f%%\n", (100.0f*dwSize)/(1.0f*dwTotalSize));
+ PrintStatus(0, FALSE, lmprintf(MSG_241, (100.0f*dwSize)/(1.0f*dwTotalSize)));
if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) {
uprintf("Error writing file '%s': %s\n", file, WinInetErrorString());
goto out;
@@ -362,10 +364,10 @@ out:
if (fd != NULL) fclose(fd);
if (!r) {
_unlink(file);
- PrintStatus(0, FALSE, "Failed to download file.");
+ PrintStatus(0, FALSE, lmprintf(MSG_242));
SetLastError(error_code);
- MessageBoxA(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus):WinInetErrorString(),
- "File download", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus):WinInetErrorString(),
+ lmprintf(MSG_044), MB_OK|MB_ICONERROR);
}
if (hRequest) InternetCloseHandle(hRequest);
if (hConnection) InternetCloseHandle(hConnection);
@@ -456,7 +458,7 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
}
}
- PrintStatus(3000, TRUE, "Checking for " APPLICATION_NAME " updates...\n");
+ PrintStatus(3000, TRUE, lmprintf(MSG_243));
status++; // 1
if (!GetVersionExA(&os_version)) {
@@ -600,15 +602,14 @@ out:
if (hSession) InternetCloseHandle(hSession);
switch(status) {
case 1:
- PrintStatus(3000, TRUE, "Updates: Unable to connect to the internet.\n");
+ PrintStatus(3000, TRUE, lmprintf(MSG_244));
break;
case 2:
- PrintStatus(3000, TRUE, "Updates: Unable to access version data.\n");
+ PrintStatus(3000, TRUE, lmprintf(MSG_245));
break;
case 3:
case 4:
- PrintStatus(3000, FALSE, "%s new version of " APPLICATION_NAME " %s\n",
- found_new_version?"A":"No", found_new_version?"is available!":"was found.");
+ PrintStatus(3000, FALSE, lmprintf(found_new_version?MSG_246:MSG_247));
default:
break;
}
diff --git a/src/parser.c b/src/parser.c
index 8d85afc5..2702f1c7 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -33,13 +33,415 @@
#include "rufus.h"
#include "msapi_utf8.h"
+#include "localization.h"
-// Parse a line of UTF-16 text and return the data if it matches the 'token'
-// The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is
-// modified by the parser
+static const char space[] = " \t";
+static const wchar_t wspace[] = L" \t";
+
+/*
+ * Fill a localization command buffer by parsing the line arguments
+ * The command is allocated and must be freed (by calling free_loc_cmd)
+ */
+static loc_cmd* get_loc_cmd(char c, char* line) {
+ size_t i, j, k, l, r, ti = 0, ii = 0;
+ char *endptr, *expected_endptr, *token;
+ loc_cmd* lcmd = NULL;
+
+ for (j=0; j= ARRAYSIZE(parse_cmd)) {
+ luprint("unknown command");
+ return NULL;
+ }
+
+ lcmd = (loc_cmd*)calloc(sizeof(loc_cmd), 1);
+ if (lcmd == NULL) {
+ luprint("could not allocate command");
+ return NULL;
+ }
+ lcmd->ctrl_id = -1;
+ lcmd->command = parse_cmd[j].cmd;
+ lcmd->line_nr = (uint16_t)loc_line_nr;
+
+ i = 0;
+ for (k = 0; parse_cmd[j].arg_type[k] != 0; k++) {
+ // Skip leading spaces
+ i += strspn(&line[i], space);
+ r = i;
+ if (line[i] == 0) {
+ luprintf("missing parameter for command '%c'", parse_cmd[j].c);
+ goto err;
+ }
+ switch(parse_cmd[j].arg_type[k]) {
+ case 's': // quoted string
+ // search leading quote
+ if (line[i++] != '"') {
+ luprint("no start quote");
+ goto err;
+ }
+ r = i;
+ // locate ending quote
+ while ((line[i] != 0) && ((line[i] != '"') || ((line[i] == '"') && (line[i-1] == '\\')))) {
+ if ((line[i] == '"') && (line[i-1] == '\\')) {
+ strcpy(&line[i-1], &line[i]);
+ } else {
+ i++;
+ }
+ }
+ if (line[i] == 0) {
+ luprint("no end quote");
+ goto err;
+ }
+ line[i++] = 0;
+ lcmd->txt[ti++] = safe_strdup(&line[r]);
+ break;
+ case 'c': // control ID (single word)
+ while ((line[i] != 0) && (line[i] != space[0]) && (line[i] != space[1]))
+ i++;
+ if (line[i] != 0)
+ line[i++] = 0;
+ lcmd->txt[ti++] = safe_strdup(&line[r]);
+ break;
+ case 'i': // 32 bit signed integer
+ // allow commas or dots between values
+ if ((line[i] == ',') || (line[i] == '.')) {
+ i += strspn(&line[i+1], space);
+ r = i;
+ }
+ while ((line[i] != 0) && (line[i] != space[0]) && (line[i] != space[1])
+ && (line[i] != ',') && (line[i] != '.'))
+ i++;
+ expected_endptr = &line[i];
+ if (line[i] != 0)
+ line[i++] = 0;
+ lcmd->num[ii++] = (int32_t)strtol(&line[r], &endptr, 0);
+ if (endptr != expected_endptr) {
+ luprint("invalid integer");
+ goto err;
+ }
+ break;
+ case 'u': // comma separated list of unsigned integers (to end of line)
+ // count the number of commas
+ lcmd->unum_size = 1;
+ for (l=i; line[l] != 0; l++) {
+ if (line[l] == ',')
+ lcmd->unum_size++;
+ }
+ lcmd->unum = (uint32_t*)malloc(lcmd->unum_size * sizeof(uint32_t));
+ token = strtok(&line[i], ",");
+ for (l=0; (lunum_size) && (token != NULL); l++) {
+ lcmd->unum[l] = (int32_t)strtol(token, &endptr, 0);
+ token = strtok(NULL, ",");
+ }
+ if ((token != NULL) || (l != lcmd->unum_size)) {
+ luprint("internal error (unexpected number of numeric values)");
+ goto err;
+ }
+ break;
+ default:
+ uprintf("localization: unhandled arg_type '%c'\n", parse_cmd[j].arg_type[k]);
+ goto err;
+ }
+ }
+
+ return lcmd;
+
+err:
+ free_loc_cmd(lcmd);
+ return NULL;
+}
+
+/*
+ * Parse an UTF-8 localization command line
+ */
+static void get_loc_data_line(char* line)
+{
+ size_t i;
+ loc_cmd* lcmd = NULL;
+ char t;
+
+ if ((line == NULL) || (line[0] == 0))
+ return;
+
+ // Skip leading spaces
+ i = strspn(line, space);
+
+ // Read token (NUL character will be read if EOL)
+ t = line[i++];
+ if (t == '#') // Comment
+ return;
+ if ((t == 0) || ((line[i] != space[0]) && (line[i] != space[1]))) {
+ luprintf("syntax error: '%s'", line);
+ return;
+ }
+
+ lcmd = get_loc_cmd(t, &line[i]);
+
+ if ((lcmd != NULL) && (lcmd->command != LC_LOCALE))
+ // TODO: check return value?
+ dispatch_loc_cmd(lcmd);
+ else
+ free_loc_cmd(lcmd);
+}
+
+/*
+ * Open a localization file and store its file name, with special case
+ * when dealing with the embedded loc file.
+ */
+FILE* open_loc_file(const char* filename)
+{
+ FILE* fd = NULL;
+ wchar_t *wfilename = NULL;
+ const char* tmp_ext = ".tmp";
+
+ if (filename == NULL)
+ return NULL;
+
+ if (loc_filename != embedded_loc_filename) {
+ safe_free(loc_filename);
+ }
+ if (safe_strcmp(tmp_ext, &filename[safe_strlen(filename)-4]) == 0) {
+ loc_filename = embedded_loc_filename;
+ } else {
+ loc_filename = safe_strdup(filename);
+ }
+ wfilename = utf8_to_wchar(filename);
+ if (wfilename == NULL) {
+ uprintf("localization: could not convert '%s' filename to UTF-16\n", filename);
+ goto out;
+ }
+ fd = _wfopen(wfilename, L"r");
+ if (fd == NULL) {
+ uprintf("localization: could not open '%s'\n", filename);
+ }
+
+out:
+ safe_free(wfilename);
+ return fd;
+}
+
+/*
+ * Parse a localization file, to construct the list of available locales.
+ * The locale file must be UTF-8 with NO BOM.
+ */
+BOOL get_supported_locales(const char* filename)
+{
+ FILE* fd = NULL;
+ BOOL r = FALSE;
+ char line[1024];
+ size_t i;
+ loc_cmd *lcmd = NULL, *last_lcmd = NULL;
+ long end_of_block;
+
+ fd = open_loc_file(filename);
+ if (fd == NULL)
+ goto out;
+
+ loc_line_nr = 0;
+ line[0] = 0;
+ free_locale_list();
+ do {
+ // adjust the last block
+ end_of_block = ftell(fd);
+ if (fgets(line, sizeof(line), fd) == NULL)
+ break;
+ loc_line_nr++;
+ // Skip leading spaces
+ i = strspn(line, space);
+ if (line[i] != 'l')
+ continue;
+ // line[i] is not NUL so i+1 is safe to access
+ lcmd = get_loc_cmd(line[i], &line[i+1]);
+ if ((lcmd == NULL) || (lcmd->command != LC_LOCALE)) {
+ free_loc_cmd(lcmd);
+ continue;
+ }
+ // we use num[0] and num[1] as block delimiter index for this locale in the file
+ if (last_lcmd != NULL) {
+ last_lcmd->num[1] = (int32_t)end_of_block;
+ }
+ lcmd->num[0] = (int32_t)ftell(fd);
+ // Add our locale command to the locale list
+ list_add_tail(&lcmd->list, &locale_list);
+ uprintf("localization: found locale '%s'\n", lcmd->txt[0]);
+ last_lcmd = lcmd;
+ } while (1);
+ if (last_lcmd != NULL)
+ last_lcmd->num[1] = (int32_t)ftell(fd);
+ r = !list_empty(&locale_list);
+ if (r == FALSE)
+ uprintf("localization: '%s' contains no locale sections\n", filename);
+
+out:
+ if (fd != NULL)
+ fclose(fd);
+ return r;
+}
+
+/*
+ * Parse a locale section in a localization file (UTF-8, no BOM)
+ * NB: this call is reentrant for the "base" command support
+ */
+char* get_loc_data_file(const char* filename, long offset, long end_offset, int start_line)
+{
+ size_t bufsize = 1024;
+ static FILE* fd = NULL;
+ char *ret = NULL, *buf = NULL;
+ size_t i = 0;
+ int r = 0, line_nr_incr = 1;
+ int c = 0, eol_char = 0;
+ int old_loc_line_nr;
+ BOOL eol = FALSE, escape_sequence = FALSE, reentrant = (fd != NULL);
+ long cur_offset = -1;
+
+ if (reentrant) {
+ // Called, from a 'b' command - no need to reopen the file,
+ // just save the current offset and current line number
+ cur_offset = ftell(fd);
+ old_loc_line_nr = loc_line_nr;
+ } else {
+ if ((filename == NULL) || (filename[0] == 0))
+ return NULL;
+ free_dialog_list();
+ fd = open_loc_file(filename);
+ if (fd == NULL)
+ goto out;
+ }
+ loc_line_nr = start_line;
+ buf = (char*) malloc(bufsize);
+ if (buf == NULL) {
+ uprintf("localization: could not allocate line buffer\n");
+ goto out;
+ }
+
+ fseek(fd, offset, SEEK_SET);
+
+ do { // custom readline handling for string collation, realloc, line numbers, etc.
+ c = getc(fd);
+ switch(c) {
+ case EOF:
+ buf[i] = 0;
+ if (!eol)
+ loc_line_nr += line_nr_incr;
+ get_loc_data_line(buf);
+ goto out;
+ case '\r':
+ case '\n':
+ if (escape_sequence) {
+ escape_sequence = FALSE;
+ break;
+ }
+ // This assumes that the EOL sequence is always the same throughout the file
+ if (eol_char == 0)
+ eol_char = c;
+ if (c == eol_char) {
+ if (eol) {
+ line_nr_incr++;
+ } else {
+ loc_line_nr += line_nr_incr;
+ line_nr_incr = 1;
+ }
+ }
+ buf[i] = 0;
+ if (!eol) {
+ // Strip trailing spaces (for string collation)
+ for (r = ((int)i)-1; (r>0) && ((buf[r]==space[0])||(buf[r]==space[1])); r--);
+ if (r < 0)
+ r = 0;
+ eol = TRUE;
+ }
+ break;
+ case ' ':
+ case '\t':
+ if (escape_sequence) {
+ escape_sequence = FALSE;
+ break;
+ }
+ if (!eol) {
+ buf[i++] = (char)c;
+ }
+ break;
+ case '\\':
+ if (!escape_sequence) {
+ escape_sequence = TRUE;
+ break;
+ }
+ // fall through on escape sequence
+ default:
+ if (escape_sequence) {
+ switch (c) {
+ case 'n': // \n -> CRLF
+ buf[i++] = '\r';
+ buf[i++] = '\n';
+ break;
+ case '"': // \" carried as is
+ buf[i++] = '\\';
+ buf[i++] = '"';
+ break;
+ case '\\':
+ buf[i++] = '\\';
+ break;
+ default: // ignore any other escape sequence
+ break;
+ }
+ escape_sequence = FALSE;
+ } else {
+ // Collate multiline strings
+ if ((eol) && (c == '"') && (buf[r] == '"')) {
+ i = r;
+ eol = FALSE;
+ break;
+ }
+ if (eol) {
+ get_loc_data_line(buf);
+ eol = FALSE;
+ i = 0;
+ r = 0;
+ }
+ buf[i++] = (char)c;
+ }
+ break;
+ }
+ if (ftell(fd) > end_offset)
+ goto out;
+ // Have at least 2 chars extra, for \r\n sequences
+ if (i >= bufsize-2) {
+ bufsize *= 2;
+ if (bufsize > 32768) {
+ uprintf("localization: requested line buffer is larger than 32K!\n");
+ goto out;
+ }
+ buf = (char*) _reallocf(buf, bufsize);
+ if (buf == NULL) {
+ uprintf("localization: could not grow line buffer\n");
+ goto out;
+ }
+ }
+ } while(1);
+
+out:
+ // Don't close on a reentrant call
+ if (reentrant) {
+ fseek(fd, cur_offset, SEEK_SET);
+ loc_line_nr = old_loc_line_nr;
+ } else if (fd != NULL) {
+ fclose(fd);
+ fd = NULL;
+ }
+ safe_free(buf);
+ return ret;
+}
+
+
+/*
+ * Parse a line of UTF-16 text and return the data if it matches the 'token'
+ * The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is
+ * modified by the parser
+ */
static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
{
- const wchar_t wspace[] = L" \t"; // The only whitespaces we recognize as such
size_t i, r;
BOOLEAN quoteth = FALSE;
@@ -90,8 +492,10 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
return (wline[r] == 0)?NULL:&wline[r];
}
-// Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurrence of 'token'
-// The returned string is UTF-8 and MUST be freed by the caller
+/*
+ * Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurrence of 'token'
+ * The returned string is UTF-8 and MUST be freed by the caller
+ */
char* get_token_data_file(const char* token, const char* filename)
{
wchar_t *wtoken = NULL, *wdata= NULL, *wfilename = NULL;
@@ -135,8 +539,10 @@ out:
return ret;
}
-// Parse a buffer (ANSI or UTF-8) and return the data for the 'n'th occurrence of 'token'
-// The returned string is UTF-8 and MUST be freed by the caller
+/*
+ * Parse a buffer (ANSI or UTF-8) and return the data for the 'n'th occurrence of 'token'
+ * The returned string is UTF-8 and MUST be freed by the caller
+ */
char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size)
{
unsigned int j, curly_count;
@@ -199,10 +605,12 @@ static __inline char* get_sanitized_token_data_buffer(const char* token, unsigne
return data;
}
-// Parse an update data file and populates a rufus_update structure.
-// NB: since this is remote data, and we're running elevated, it *IS* considered
-// potentially malicious, even if it comes from a supposedly trusted server.
-// len should be the size of the buffer, including the zero terminator
+/*
+ * Parse an update data file and populates a rufus_update structure.
+ * NB: since this is remote data, and we're running elevated, it *IS* considered
+ * potentially malicious, even if it comes from a supposedly trusted server.
+ * len should be the size of the buffer, including the zero terminator
+ */
void parse_update(char* buf, size_t len)
{
size_t i;
@@ -249,13 +657,14 @@ void parse_update(char* buf, size_t len)
update.release_notes = get_sanitized_token_data_buffer("release_notes", 1, buf, len);
}
-// Insert entry 'data' under section 'section' of a config file
-// Section must include the relevant delimitors (eg '[', ']') if needed
+/*
+ * Insert entry 'data' under section 'section' of a config file
+ * Section must include the relevant delimitors (eg '[', ']') if needed
+ */
char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix)
{
const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" };
wchar_t *wsection = NULL, *wfilename = NULL, *wtmpname = NULL, *wdata = NULL, bom = 0;
- wchar_t wspace[] = L" \t";
wchar_t buf[1024];
FILE *fd_in = NULL, *fd_out = NULL;
size_t i, size;
@@ -316,7 +725,7 @@ char* insert_section_data(const char* filename, const char* section, const char*
fd_out = _wfopen(wtmpname, outmode[mode]);
if (fd_out == NULL) {
- uprintf("Could not open temporary output file %s~\n", filename);
+ uprintf("Could not open temporary output file '%s~'\n", filename);
goto out;
}
@@ -360,7 +769,7 @@ out:
fclose(fd_in);
fclose(fd_out);
} else {
- uprintf("Could not write %s - original file has been left unmodifiedn", filename);
+ uprintf("Could not write '%s' - original file has been left unmodified\n", filename);
ret = NULL;
if (fd_in != NULL) fclose(fd_in);
if (fd_out != NULL) fclose(fd_out);
@@ -375,15 +784,16 @@ out:
return ret;
}
-// Search for a specific 'src' substring data for all occurrences of 'token', and replace
-// it with 'rep'. File can be ANSI or UNICODE and is overwritten. Parameters are UTF-8.
-// The parsed line is of the form: [ ]token[ ]data
-// Returns a pointer to rep if replacement occurred, NULL otherwise
+/*
+ * Search for a specific 'src' substring data for all occurrences of 'token', and replace
+ * it with 'rep'. File can be ANSI or UNICODE and is overwritten. Parameters are UTF-8.
+ * The parsed line is of the form: [ ]token[ ]data
+ * Returns a pointer to rep if replacement occurred, NULL otherwise
+ */
char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep, BOOL dos2unix)
{
const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" };
wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wsrc = NULL, *wrep = NULL, bom = 0;
- wchar_t wspace[] = L" \t";
wchar_t buf[1024], *torep;
FILE *fd_in = NULL, *fd_out = NULL;
size_t i, size;
@@ -451,7 +861,7 @@ char* replace_in_token_data(const char* filename, const char* token, const char*
fd_out = _wfopen(wtmpname, outmode[mode]);
if (fd_out == NULL) {
- uprintf("Could not open temporary output file %s~\n", filename);
+ uprintf("Could not open temporary output file '%s~'\n", filename);
goto out;
}
@@ -506,7 +916,7 @@ out:
fclose(fd_in);
fclose(fd_out);
} else {
- uprintf("Could not write %s - original file has been left unmodified.\n", filename);
+ uprintf("Could not write '%s' - original file has been left unmodified.\n", filename);
ret = NULL;
if (fd_in != NULL) fclose(fd_in);
if (fd_out != NULL) fclose(fd_out);
diff --git a/src/resource.h b/src/resource.h
index ef97e598..1b238dc9 100644
--- a/src/resource.h
+++ b/src/resource.h
@@ -3,17 +3,17 @@
// Used by rufus.rc
//
#define IDD_DIALOG 101
-#define IDI_ICON 102
-#define IDD_ABOUTBOX 103
-#define IDD_NOTIFICATION 104
-#define IDD_LICENSE 105
-#define IDD_ISO_EXTRACT 106
-#define IDD_LOG 107
-#define IDS_VERSION 108
-#define IDI_UP 109
-#define IDI_DOWN 110
-#define IDD_UPDATE_POLICY 111
-#define IDD_NEW_VERSION 112
+#define IDD_ABOUTBOX 102
+#define IDD_NOTIFICATION 103
+#define IDD_LICENSE 104
+#define IDD_ISO_EXTRACT 105
+#define IDD_LOG 106
+#define IDD_UPDATE_POLICY 107
+#define IDD_NEW_VERSION 108
+#define IDD_MESSAGES 109
+#define IDI_ICON 110
+#define IDI_UP 111
+#define IDI_DOWN 112
#define IDR_BR_MBR_BIN 200
#define IDR_FD_COMMAND_COM 300
#define IDR_FD_KERNEL_SYS 301
@@ -46,10 +46,11 @@
#define IDR_SL_LDLINUX_V4_SYS 401
#define IDR_SL_LDLINUX_V5_BSS 402
#define IDR_SL_LDLINUX_V5_SYS 403
+#define IDR_LC_RUFUS_LOC 500
#define IDC_DEVICE 1001
#define IDC_FILESYSTEM 1002
#define IDC_START 1003
-#define IDC_PARTITION_SCHEME 1004
+#define IDC_PARTITION_TYPE 1004
#define IDC_CLUSTERSIZE 1005
#define IDC_STATUS 1006
#define IDC_ABOUT 1007
@@ -79,7 +80,7 @@
#define IDC_NOTIFICATION_TEXT 1041
#define IDC_NOTIFICATION_LINE 1042
#define IDC_ADVANCED 1043
-#define IDC_ADVANCED_GROUP 1044
+#define IDS_ADVANCED_OPTIONS_GRP 1044
#define IDC_LOG 1045
#define IDC_LOG_EDIT 1050
#define IDC_LOG_SAVE 1051
@@ -95,15 +96,287 @@
#define IDC_YOUR_VERSION 1068
#define IDC_LATEST_VERSION 1069
#define IDC_DOWNLOAD_URL 1070
+#define IDS_DEVICE_TXT 2000
+#define IDS_PARTITION_TYPE_TXT 2001
+#define IDS_FILESYSTEM_TXT 2002
+#define IDS_CLUSTERSIZE_TXT 2003
+#define IDS_LABEL_TXT 2004
+#define IDS_FORMAT_OPTIONS_GRP 2005
+#define IDS_UPDATE_SETTINGS_GRP 2006
+#define IDS_UPDATE_FREQUENCY_TXT 2007
+#define IDS_INCLUDE_BETAS_TXT 2008
+#define IDS_NEW_VERSION_AVAIL_TXT 2009
+#define IDS_NEW_VERSION_DOWNLOAD_GRP 2010
+#define IDS_NEW_VERSION_NOTES_GRP 2011
+#define IDS_CHECK_NOW_GRP 2012
+#define MSG_000 3000
+#define MSG_001 3001
+#define MSG_002 3002
+#define MSG_003 3003
+#define MSG_004 3004
+#define MSG_005 3005
+#define MSG_006 3006
+#define MSG_007 3007
+#define MSG_008 3008
+#define MSG_009 3009
+#define MSG_010 3010
+#define MSG_011 3011
+#define MSG_012 3012
+#define MSG_013 3013
+#define MSG_014 3014
+#define MSG_015 3015
+#define MSG_016 3016
+#define MSG_017 3017
+#define MSG_018 3018
+#define MSG_019 3019
+#define MSG_020 3020
+#define MSG_021 3021
+#define MSG_022 3022
+#define MSG_023 3023
+#define MSG_024 3024
+#define MSG_025 3025
+#define MSG_026 3026
+#define MSG_027 3027
+#define MSG_028 3028
+#define MSG_029 3029
+#define MSG_030 3030
+#define MSG_031 3031
+#define MSG_032 3032
+#define MSG_033 3033
+#define MSG_034 3034
+#define MSG_035 3035
+#define MSG_036 3036
+#define MSG_037 3037
+#define MSG_038 3038
+#define MSG_039 3039
+#define MSG_040 3040
+#define MSG_041 3041
+#define MSG_042 3042
+#define MSG_043 3043
+#define MSG_044 3044
+#define MSG_045 3045
+#define MSG_046 3046
+#define MSG_047 3047
+#define MSG_048 3048
+#define MSG_049 3049
+#define MSG_050 3050
+#define MSG_051 3051
+#define MSG_052 3052
+#define MSG_053 3053
+#define MSG_054 3054
+#define MSG_055 3055
+#define MSG_056 3056
+#define MSG_057 3057
+#define MSG_058 3058
+#define MSG_059 3059
+#define MSG_060 3060
+#define MSG_061 3061
+#define MSG_062 3062
+#define MSG_063 3063
+#define MSG_064 3064
+#define MSG_065 3065
+#define MSG_066 3066
+#define MSG_067 3067
+#define MSG_068 3068
+#define MSG_069 3069
+#define MSG_070 3070
+#define MSG_071 3071
+#define MSG_072 3072
+#define MSG_073 3073
+#define MSG_074 3074
+#define MSG_075 3075
+#define MSG_076 3076
+#define MSG_077 3077
+#define MSG_078 3078
+#define MSG_079 3079
+#define MSG_080 3080
+#define MSG_081 3081
+#define MSG_082 3082
+#define MSG_083 3083
+#define MSG_084 3084
+#define MSG_085 3085
+#define MSG_086 3086
+#define MSG_087 3087
+#define MSG_088 3088
+#define MSG_089 3089
+#define MSG_090 3090
+#define MSG_091 3091
+#define MSG_092 3092
+#define MSG_093 3093
+#define MSG_094 3094
+#define MSG_095 3095
+#define MSG_096 3096
+#define MSG_097 3097
+#define MSG_098 3098
+#define MSG_099 3099
+#define MSG_100 3100
+#define MSG_101 3101
+#define MSG_102 3102
+#define MSG_103 3103
+#define MSG_104 3104
+#define MSG_105 3105
+#define MSG_106 3106
+#define MSG_107 3107
+#define MSG_108 3108
+#define MSG_109 3109
+#define MSG_110 3110
+#define MSG_111 3111
+#define MSG_112 3112
+#define MSG_113 3113
+#define MSG_114 3114
+#define MSG_115 3115
+#define MSG_116 3116
+#define MSG_117 3117
+#define MSG_118 3118
+#define MSG_119 3119
+#define MSG_120 3120
+#define MSG_121 3121
+#define MSG_122 3122
+#define MSG_123 3123
+#define MSG_124 3124
+#define MSG_125 3125
+#define MSG_126 3126
+#define MSG_127 3127
+#define MSG_128 3128
+#define MSG_129 3129
+#define MSG_130 3130
+#define MSG_131 3131
+#define MSG_132 3132
+#define MSG_133 3133
+#define MSG_134 3134
+#define MSG_135 3135
+#define MSG_136 3136
+#define MSG_137 3137
+#define MSG_138 3138
+#define MSG_139 3139
+#define MSG_140 3140
+#define MSG_141 3141
+#define MSG_142 3142
+#define MSG_143 3143
+#define MSG_144 3144
+#define MSG_145 3145
+#define MSG_146 3146
+#define MSG_147 3147
+#define MSG_148 3148
+#define MSG_149 3149
+#define MSG_150 3150
+#define MSG_151 3151
+#define MSG_152 3152
+#define MSG_153 3153
+#define MSG_154 3154
+#define MSG_155 3155
+#define MSG_156 3156
+#define MSG_157 3157
+#define MSG_158 3158
+#define MSG_159 3159
+#define MSG_160 3160
+#define MSG_161 3161
+#define MSG_162 3162
+#define MSG_163 3163
+#define MSG_164 3164
+#define MSG_165 3165
+#define MSG_166 3166
+#define MSG_167 3167
+#define MSG_168 3168
+#define MSG_169 3169
+#define MSG_170 3170
+#define MSG_171 3171
+#define MSG_172 3172
+#define MSG_173 3173
+#define MSG_174 3174
+#define MSG_175 3175
+#define MSG_176 3176
+#define MSG_177 3177
+#define MSG_178 3178
+#define MSG_179 3179
+#define MSG_180 3180
+#define MSG_181 3181
+#define MSG_182 3182
+#define MSG_183 3183
+#define MSG_184 3184
+#define MSG_185 3185
+#define MSG_186 3186
+#define MSG_187 3187
+#define MSG_188 3188
+#define MSG_189 3189
+#define MSG_190 3190
+#define MSG_191 3191
+#define MSG_192 3192
+#define MSG_193 3193
+#define MSG_194 3194
+#define MSG_195 3195
+#define MSG_196 3196
+#define MSG_197 3197
+#define MSG_198 3198
+#define MSG_199 3199
+#define MSG_200 3200
+#define MSG_201 3201
+#define MSG_202 3202
+#define MSG_203 3203
+#define MSG_204 3204
+#define MSG_205 3205
+#define MSG_206 3206
+#define MSG_207 3207
+#define MSG_208 3208
+#define MSG_209 3209
+#define MSG_210 3210
+#define MSG_211 3211
+#define MSG_212 3212
+#define MSG_213 3213
+#define MSG_214 3214
+#define MSG_215 3215
+#define MSG_216 3216
+#define MSG_217 3217
+#define MSG_218 3218
+#define MSG_219 3219
+#define MSG_220 3220
+#define MSG_221 3221
+#define MSG_222 3222
+#define MSG_223 3223
+#define MSG_224 3224
+#define MSG_225 3225
+#define MSG_226 3226
+#define MSG_227 3227
+#define MSG_228 3228
+#define MSG_229 3229
+#define MSG_230 3230
+#define MSG_231 3231
+#define MSG_232 3232
+#define MSG_233 3233
+#define MSG_234 3234
+#define MSG_235 3235
+#define MSG_236 3236
+#define MSG_237 3237
+#define MSG_238 3238
+#define MSG_239 3239
+#define MSG_240 3240
+#define MSG_241 3241
+#define MSG_242 3242
+#define MSG_243 3243
+#define MSG_244 3244
+#define MSG_245 3245
+#define MSG_246 3246
+#define MSG_247 3247
+#define MSG_248 3248
+#define MSG_249 3249
+#define MSG_250 3250
+#define MSG_251 3251
+#define MSG_252 3252
+#define MSG_253 3253
+#define MSG_254 3254
+#define MSG_255 3255
+#define MSG_256 3256
+#define MSG_257 3257
+#define MSG_258 3258
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
-#define _APS_NEXT_RESOURCE_VALUE 113
+#define _APS_NEXT_RESOURCE_VALUE 404
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1071
-#define _APS_NEXT_SYMED_VALUE 101
+#define _APS_NEXT_SYMED_VALUE 4000
#endif
#endif
diff --git a/src/rufus.c b/src/rufus.c
index a2e791b9..09c597cb 100644
--- a/src/rufus.c
+++ b/src/rufus.c
@@ -40,6 +40,7 @@
#include "resource.h"
#include "rufus.h"
#include "registry.h"
+#include "localization.h"
/* Redefinitions for WDK and MinGW */
#ifndef PBM_SETSTATE
@@ -88,12 +89,6 @@ struct {
const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "UDF", "exFAT" };
// Number of steps for each FS for FCC_STRUCTURE_PROGRESS
const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 };
-// Don't ask me - just following the MS "standard" here
-// We hijack 256 as a "Default" for UDF, since we can't set clustersize there
-static const char* ClusterSizeLabel[] = { "Default", "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes",
- "16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes",
- "1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
-static const char* BiosTypeLabel[BT_MAX] = { "BIOS", "UEFI" };
static const char* PartitionTypeLabel[2] = { "MBR", "GPT" };
static BOOL existing_key = FALSE; // For LGP set/restore
static BOOL size_check = TRUE;
@@ -101,6 +96,8 @@ static BOOL log_displayed = FALSE;
static BOOL iso_provided = FALSE;
extern BOOL force_large_fat32, enable_joliet, enable_rockridge;
static int selection_default;
+static loc_cmd* selected_locale = NULL;
+char ClusterSizeLabel[MAX_CLUSTER_SIZES][64];
char msgbox[1024], msgbox_title[32];
/*
@@ -148,6 +145,23 @@ static float previous_end;
#define MB 1048576LL
#define GB 1073741824LL
#define TB 1099511627776LL
+
+/*
+ * Fill in the cluster size names
+ */
+static void SetClusterSizeLabels(void)
+{
+ unsigned int i, j, k;
+ safe_sprintf(ClusterSizeLabel[0], 64, lmprintf(MSG_029));
+ for (i=512, j=1, k=MSG_026; j 8192) {
+ i /= 1024;
+ k++;
+ }
+ safe_sprintf(ClusterSizeLabel[j], 64, "%d %s", i, lmprintf(k));
+ }
+}
+
/*
* Set cluster size values according to http://support.microsoft.com/kb/140365
* this call will return FALSE if we can't find a supportable FS for the drive
@@ -157,7 +171,7 @@ static BOOL DefineClusterSizes(void)
LONGLONG i;
int fs;
BOOL r = FALSE;
- char tmp[64] = "";
+ char tmp[64] = "", *entry;
default_fs = FS_UNKNOWN;
memset(&SelectedDrive.ClusterSize, 0, sizeof(SelectedDrive.ClusterSize));
@@ -278,11 +292,13 @@ out:
safe_strcat(tmp, sizeof(tmp), "Large ");
safe_strcat(tmp, sizeof(tmp), FileSystemLabel[fs]);
if (default_fs == FS_UNKNOWN) {
- safe_strcat(tmp, sizeof(tmp), " (Default)");
+ entry = lmprintf(MSG_030, tmp);
default_fs = fs;
+ } else {
+ entry = tmp;
}
IGNORE_RETVAL(ComboBox_SetItemData(hFileSystem,
- ComboBox_AddStringU(hFileSystem, tmp), fs));
+ ComboBox_AddStringU(hFileSystem, entry), fs));
r = TRUE;
}
}
@@ -299,7 +315,7 @@ out:
*/
static BOOL SetClusterSizes(int FSType)
{
- char szClustSize[64];
+ char* szClustSize;
int i, k, default_index = 0;
ULONG j;
@@ -317,10 +333,11 @@ static BOOL SetClusterSizes(int FSType)
for(i=0,j=0x100,k=0;j<0x10000000;i++,j<<=1) {
if (j & SelectedDrive.ClusterSize[FSType].Allowed) {
- safe_sprintf(szClustSize, sizeof(szClustSize), "%s", ClusterSizeLabel[i]);
if (j == SelectedDrive.ClusterSize[FSType].Default) {
- safe_strcat(szClustSize, sizeof(szClustSize), " (Default)");
+ szClustSize = lmprintf(MSG_030, ClusterSizeLabel[i]);
default_index = k;
+ } else {
+ szClustSize = ClusterSizeLabel[i];
}
IGNORE_RETVAL(ComboBox_SetItemData(hClusterSize, ComboBox_AddStringU(hClusterSize, szClustSize), j));
k++;
@@ -470,15 +487,12 @@ static void SetPartitionSchemeTooltip(void)
bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
if (bt == BT_BIOS) {
- CreateTooltip(hPartitionScheme, "Usually the safest choice. If you have an UEFI computer and want to install "
- "an OS in EFI mode however, you should select one of the options below", 15000);
+ CreateTooltip(hPartitionScheme, lmprintf(MSG_150), 15000);
} else {
if (pt == PARTITION_STYLE_MBR) {
- CreateTooltip(hPartitionScheme, "Use this if you want to install an OS in EFI mode, but need to access "
- "the USB content from Windows XP", 15000);
+ CreateTooltip(hPartitionScheme, lmprintf(MSG_151), 15000);
} else {
- CreateTooltip(hPartitionScheme, "The preferred option to install an OS in EFI mode and when "
- "USB access is not required for Windows XP", 15000);
+ CreateTooltip(hPartitionScheme, lmprintf(MSG_152), 15000);
}
}
}
@@ -489,8 +503,6 @@ static void SetPartitionSchemeTooltip(void)
static BOOL PopulateProperties(int ComboIndex)
{
double HumanReadableSize;
- char capacity[64];
- static char* suffix[] = { "B", "KB", "MB", "GB", "TB", "PB"};
char no_label[] = STR_NO_LABEL;
int i, j, pt, bt;
@@ -510,7 +522,7 @@ static BOOL PopulateProperties(int ComboIndex)
EnableBootOptions(TRUE);
HumanReadableSize = (double)SelectedDrive.DiskSize;
- for (i=1; i= ARRAYSIZE(suffix))
+ if (i >= MAX_SIZE_SUFFIXES)
uprintf("Could not populate partition scheme data\n");
if (SelectedDrive.PartitionType == PARTITION_STYLE_GPT) {
j = 2;
@@ -548,10 +560,10 @@ static BOOL PopulateProperties(int ComboIndex)
// If we're beneath the tolerance, round proposed label to an integer, if not, show two decimal point
if (fabs(HumanReadableSize / ceil(HumanReadableSize) - 1.0) < PROPOSEDLABEL_TOLERANCE) {
safe_sprintf(SelectedDrive.proposed_label, sizeof(SelectedDrive.proposed_label),
- "%0.0f%s", ceil(HumanReadableSize), suffix[i]);
+ "%0.0f%s", ceil(HumanReadableSize), lmprintf(MSG_020+i));
} else {
safe_sprintf(SelectedDrive.proposed_label, sizeof(SelectedDrive.proposed_label),
- "%0.2f%s", HumanReadableSize, suffix[i]);
+ "%0.2f%s", HumanReadableSize, lmprintf(MSG_020+i));
}
// If no existing label is available and no ISO is selected, propose one according to the size (eg: "256MB", "8GB")
@@ -584,9 +596,8 @@ static BOOL GetUSBDevices(DWORD devnum)
LONG maxwidth = 0;
RECT rect;
char drive_letter;
- char *label, entry[MAX_PATH], buffer[MAX_PATH];
+ char *label, *entry, buffer[MAX_PATH];
const char* usbstor_name = "USBSTOR";
- const char* generic_friendly_name = "USB Storage Device (Generic)";
GUID _GUID_DEVINTERFACE_DISK = // only known to some...
{ 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} };
@@ -617,7 +628,7 @@ static BOOL GetUSBDevices(DWORD devnum)
&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString());
// We can afford a failure on this call - just replace the name
- safe_strcpy(buffer, sizeof(buffer), generic_friendly_name);
+ safe_strcpy(buffer, sizeof(buffer), lmprintf(MSG_045));
}
uprintf("Found device '%s'\n", buffer);
@@ -684,7 +695,7 @@ static BOOL GetUSBDevices(DWORD devnum)
StrArrayAdd(&DriveLabel, label);
// Drive letter ' ' is returned for drives that don't have a volume assigned yet
if (drive_letter == ' ') {
- safe_sprintf(entry, sizeof(entry), "%s (Disk %d)", label, device_number.DeviceNumber);
+ entry = lmprintf(MSG_046, label, device_number.DeviceNumber);
} else {
if (drive_letter == app_dir[0]) {
uprintf("Removing %c: from the list: This is the disk from which " APPLICATION_NAME " is running!\n", drive_letter);
@@ -692,7 +703,7 @@ static BOOL GetUSBDevices(DWORD devnum)
safe_free(devint_detail_data);
break;
}
- safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter);
+ entry = lmprintf(MSG_047, label, drive_letter);
}
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry),
device_number.DeviceNumber + DRIVE_INDEX_MIN));
@@ -850,7 +861,7 @@ void UpdateProgress(int op, float percent)
static void EnableControls(BOOL bEnable)
{
EnableWindow(GetDlgItem(hMainDialog, IDC_DEVICE), bEnable);
- EnableWindow(GetDlgItem(hMainDialog, IDC_PARTITION_SCHEME), bEnable);
+ EnableWindow(GetDlgItem(hMainDialog, IDC_PARTITION_TYPE), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_FILESYSTEM), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_CLUSTERSIZE), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_LABEL), bEnable);
@@ -864,7 +875,7 @@ static void EnableControls(BOOL bEnable)
EnableWindow(GetDlgItem(hMainDialog, IDC_SET_ICON), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_ADVANCED), bEnable);
EnableWindow(GetDlgItem(hMainDialog, IDC_ENABLE_FIXED_DISKS), bEnable);
- SetDlgItemTextA(hMainDialog, IDCANCEL, bEnable?"Close":"Cancel");
+ SetDlgItemTextU(hMainDialog, IDCANCEL, lmprintf(bEnable?MSG_006:MSG_007));
}
/* Callback for the log window */
@@ -878,6 +889,7 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (message) {
case WM_INITDIALOG:
+ apply_localization(IDD_LOG, hDlg);
hLog = GetDlgItem(hDlg, IDC_LOG_EDIT);
// Increase the size of our log textbox to MAX_LOG_SIZE (unsigned word)
PostMessage(hLog, EM_LIMITTEXT, MAX_LOG_SIZE , 0);
@@ -907,7 +919,7 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
log_size = GetDlgItemTextU(hDlg, IDC_LOG_EDIT, log_buffer, log_size);
if (log_size != 0) {
log_size--; // remove NUL terminator
- filepath = FileDialog(TRUE, app_dir, "rufus.log", "log", "Rufus log");
+ filepath = FileDialog(TRUE, app_dir, "rufus.log", "log", lmprintf(MSG_108));
if (filepath != NULL) {
FileIO(TRUE, filepath, &log_buffer, &log_size);
}
@@ -920,6 +932,7 @@ BOOL CALLBACK LogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
break;
case WM_CLOSE:
ShowWindow(hDlg, SW_HIDE);
+ reset_localization(IDD_LOG);
log_displayed = FALSE;
return TRUE;
}
@@ -960,14 +973,7 @@ static void CALLBACK BlockingTimer(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD
// A write or close operation hasn't made any progress since our last check
user_notified = TRUE;
uprintf("Blocking I/O operation detected\n");
- MessageBoxU(hMainDialog,
- APPLICATION_NAME " detected that Windows is still flushing its internal buffers\n"
- "onto the USB device.\n\n"
- "Depending on the speed of your USB device, this operation may\n"
- "take a long time to complete, especially for large files.\n\n"
- "We recommend that you let Windows finish, to avoid corruption.\n"
- "But if you grow tired of waiting, you can just unplug the device...",
- RUFUS_BLOCKING_IO_TITLE, MB_OK|MB_ICONINFORMATION);
+ MessageBoxU(hMainDialog, lmprintf(MSG_080), lmprintf(MSG_048), MB_OK|MB_ICONINFORMATION);
} else {
last_iso_blocking_status = iso_blocking_status;
}
@@ -979,6 +985,7 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_INITDIALOG:
+ apply_localization(IDD_ISO_EXTRACT, hDlg);
hISOProgressBar = GetDlgItem(hDlg, IDC_PROGRESS);
hISOFileName = GetDlgItem(hDlg, IDC_ISO_FILENAME);
// Use maximum granularity for the progress bar
@@ -999,7 +1006,7 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
switch (LOWORD(wParam)) {
case IDC_ISO_ABORT:
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
- PrintStatus(0, FALSE, "Cancelling - Please wait...");
+ PrintStatus(0, FALSE, lmprintf(MSG_201));
uprintf("Cancelling (from ISO proc.)\n");
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE);
if (format_thid != NULL)
@@ -1027,10 +1034,10 @@ DWORD WINAPI ISOScanThread(LPVOID param)
if (iso_path == NULL)
goto out;
- PrintStatus(0, TRUE, "Scanning ISO image...\n");
+ PrintStatus(0, TRUE, lmprintf(MSG_202));
if (!ExtractISO(iso_path, "", TRUE)) {
SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0);
- PrintStatus(0, TRUE, "Failed to scan ISO image.");
+ PrintStatus(0, TRUE, lmprintf(MSG_203));
safe_free(iso_path);
goto out;
}
@@ -1047,9 +1054,7 @@ DWORD WINAPI ISOScanThread(LPVOID param)
}
}
if ((!iso_report.has_bootmgr) && (!iso_report.has_isolinux) && (!IS_WINPE(iso_report.winpe)) && (!iso_report.has_efi)) {
- MessageBoxU(hMainDialog, "This version of " APPLICATION_NAME " only supports bootable ISOs\n"
- "based on bootmgr/WinPE, isolinux or EFI.\n"
- "This ISO doesn't appear to use either...", "Unsupported ISO", MB_OK|MB_ICONINFORMATION);
+ MessageBoxU(hMainDialog, lmprintf(MSG_082), lmprintf(MSG_081), MB_OK|MB_ICONINFORMATION);
safe_free(iso_path);
SetMBRProps();
} else if (!iso_report.has_syslinux_v5) { // This check is for Syslinux v4.x or earlier
@@ -1063,18 +1068,10 @@ DWORD WINAPI ISOScanThread(LPVOID param)
fclose(fd);
use_own_c32[i] = TRUE;
} else {
- PrintStatus(0, FALSE, "Obsolete %s detected", old_c32_name[i]);
- safe_sprintf(msgbox, sizeof(msgbox), "This ISO image seems to use an obsolete version of '%s'.\n"
- "Boot menus may not may not display properly because of this.\n\n"
- "A newer version can be downloaded by " APPLICATION_NAME " to fix this issue:\n"
- "- Choose 'Yes' to connect to the internet and download the file\n"
- "- Choose 'No' to leave the existing ISO file unmodified\n"
- "If you don't know what to do, you should select 'Yes'.\n\n"
- "Note: The new file will be downloaded in the current directory and once a "
- "'%s' exists there, it will be reused automatically.\n", old_c32_name[i], old_c32_name[i]);
- safe_sprintf(msgbox_title, sizeof(msgbox_title), "Replace %s?", old_c32_name[i]);
- if (MessageBoxU(hMainDialog, msgbox, msgbox_title, MB_YESNO|MB_ICONWARNING) == IDYES) {
- SetWindowTextU(hISOProgressDlg, "Downloading file");
+ PrintStatus(0, FALSE, lmprintf(MSG_204, old_c32_name[i]));
+ if (MessageBoxU(hMainDialog, lmprintf(MSG_084, old_c32_name[i], old_c32_name[i]),
+ lmprintf(MSG_083, old_c32_name[i]), MB_YESNO|MB_ICONWARNING) == IDYES) {
+ SetWindowTextU(hISOProgressDlg, lmprintf(MSG_085, old_c32_name[i]));
SetWindowTextU(hISOFileName, new_c32_url[i]);
if (DownloadFile(new_c32_url[i], old_c32_name[i], hISOProgressDlg))
use_own_c32[i] = TRUE;
@@ -1088,7 +1085,7 @@ DWORD WINAPI ISOScanThread(LPVOID param)
SetFSFromISO();
SetMBRProps();
for (i=(int)safe_strlen(iso_path); (i>0)&&(iso_path[i]!='\\'); i--);
- PrintStatus(0, TRUE, "Using ISO: %s\n", &iso_path[i+1]);
+ PrintStatus(0, TRUE, lmprintf(MSG_205, &iso_path[i+1]));
// Some Linux distros, such as Arch Linux, require the USB drive to have
// a specific label => copy the one we got from the ISO image
if (iso_report.label[0] != 0) {
@@ -1105,28 +1102,17 @@ out:
ExitThread(0);
}
-void MoveControl(HWND hDlg, int nID, float vertical_shift)
-{
- RECT rect;
- POINT point;
- HWND hControl;
-
- hControl = GetDlgItem(hDlg, nID);
- GetWindowRect(hControl, &rect);
- point.x = rect.left;
- point.y = rect.top;
- ScreenToClient(hDlg, &point);
- GetClientRect(hControl, &rect);
- MoveWindow(hControl, point.x, point.y + (int)(fScale*(advanced_mode?vertical_shift:-vertical_shift)),
- (rect.right - rect.left), (rect.bottom - rect.top), TRUE);
+// Move a control along the Y axis according to the advanced mode setting
+void MoveCtrlY(HWND hDlg, int nID, float vertical_shift) {
+ ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, nID), 0,
+ (int)(advanced_mode?vertical_shift:-vertical_shift), 0, 0);
}
void SetPassesTooltip(void)
{
- char passes_tooltip[32];
- safe_strcpy(passes_tooltip, sizeof(passes_tooltip), "Pattern: 0x55, 0xAA, 0xFF, 0x00");
- passes_tooltip[13 + ComboBox_GetCurSel(hNBPasses)*6] = 0;
- CreateTooltip(hNBPasses, passes_tooltip, -1);
+ const unsigned char pattern[] = BADBLOCK_PATTERNS;
+ CreateTooltip(hNBPasses, lmprintf(MSG_153 + ComboBox_GetCurSel(hNBPasses),
+ pattern[0], pattern[1], pattern[2], pattern[3]), -1);
}
// Toggle "advanced" mode
@@ -1147,14 +1133,14 @@ void ToggleAdvanced(void)
point.y + (int)(fScale*(advanced_mode?dialog_shift:-dialog_shift)), TRUE);
// Move the status bar up or down
- MoveControl(hMainDialog, IDC_STATUS, dialog_shift);
- MoveControl(hMainDialog, IDC_START, dialog_shift);
- MoveControl(hMainDialog, IDC_PROGRESS, dialog_shift);
- MoveControl(hMainDialog, IDC_ABOUT, dialog_shift);
- MoveControl(hMainDialog, IDC_LOG, dialog_shift);
- MoveControl(hMainDialog, IDCANCEL, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_STATUS, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_START, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_PROGRESS, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_ABOUT, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_LOG, dialog_shift);
+ MoveCtrlY(hMainDialog, IDCANCEL, dialog_shift);
#ifdef RUFUS_TEST
- MoveControl(hMainDialogm, IDC_TEST, dialog_shift);
+ MoveCtrlY(hMainDialog, IDC_TEST, dialog_shift);
#endif
// And do the same for the log dialog while we're at it
@@ -1163,9 +1149,9 @@ void ToggleAdvanced(void)
point.y = (rect.bottom - rect.top);
MoveWindow(hLogDlg, rect.left, rect.top, point.x,
point.y + (int)(fScale*(advanced_mode?dialog_shift:-dialog_shift)), TRUE);
- MoveControl(hLogDlg, IDC_LOG_CLEAR, dialog_shift);
- MoveControl(hLogDlg, IDC_LOG_SAVE, dialog_shift);
- MoveControl(hLogDlg, IDCANCEL, dialog_shift);
+ MoveCtrlY(hLogDlg, IDC_LOG_CLEAR, dialog_shift);
+ MoveCtrlY(hLogDlg, IDC_LOG_SAVE, dialog_shift);
+ MoveCtrlY(hLogDlg, IDCANCEL, dialog_shift);
GetWindowRect(hLog, &rect);
point.x = (rect.right - rect.left);
point.y = (rect.bottom - rect.top) + (int)(fScale*(advanced_mode?dialog_shift:-dialog_shift));
@@ -1179,7 +1165,7 @@ void ToggleAdvanced(void)
ShowWindow(GetDlgItem(hMainDialog, IDC_EXTRA_PARTITION), toggle);
ShowWindow(GetDlgItem(hMainDialog, IDC_RUFUS_MBR), toggle);
ShowWindow(GetDlgItem(hMainDialog, IDC_DISK_ID), toggle);
- ShowWindow(GetDlgItem(hMainDialog, IDC_ADVANCED_GROUP), toggle);
+ ShowWindow(GetDlgItem(hMainDialog, IDS_ADVANCED_OPTIONS_GRP), toggle);
// Toggle the up/down icon
SendMessage(GetDlgItem(hMainDialog, IDC_ADVANCED), BCM_SETIMAGELIST, 0, (LPARAM)(advanced_mode?&bi_up:&bi_down));
@@ -1189,89 +1175,67 @@ static BOOL BootCheck(void)
{
int fs, bt, dt, r;
FILE* fd;
- const char* ldlinux_c32 = "ldlinux.c32";
+ const char* ldlinux_name = "ldlinux.c32";
dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
if (dt == DT_ISO) {
if (iso_path == NULL) {
- MessageBoxU(hMainDialog, "Please click on the disc button to select a bootable ISO,\n"
- "or uncheck the \"Create a bootable disk...\" checkbox.",
- "No ISO image selected", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_087), lmprintf(MSG_086), MB_OK|MB_ICONERROR);
return FALSE;
}
if ((size_check) && (iso_report.projected_size > (uint64_t)SelectedDrive.DiskSize)) {
- MessageBoxU(hMainDialog, "This ISO image is too big "
- "for the selected target.", "ISO image too big", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_089), lmprintf(MSG_088), MB_OK|MB_ICONERROR);
return FALSE;
}
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
if (bt == BT_UEFI) {
if (!IS_EFI(iso_report)) {
- MessageBoxU(hMainDialog, "When using UEFI Target Type, only EFI bootable ISO images are supported. "
- "Please select an EFI bootable ISO or set the Target Type to BIOS.", "Unsupported ISO", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR);
return FALSE;
} else if (fs > FS_FAT32) {
- MessageBoxU(hMainDialog, "When using UEFI Target Type, only FAT/FAT32 is supported. "
- "Please select FAT/FAT32 as the File system or set the Target Type to BIOS.", "Unsupported filesystem", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_093), lmprintf(MSG_092), MB_OK|MB_ICONERROR);
return FALSE;
} else if (iso_report.has_4GB_file) {
// Who the heck decided that using FAT32 for UEFI boot was a great idea?!?
- MessageBoxU(hMainDialog, "This ISO image contains a file larger than 4 GB and cannot be used to create an EFI bootable USB.\r\n"
- "This is a limitation from UEFI/FAT32, not from " APPLICATION_NAME ".",
- "Non UEFI compatible ISO", MB_OK|MB_ICONINFORMATION);
+ MessageBoxU(hMainDialog, lmprintf(MSG_095), lmprintf(MSG_094), MB_OK|MB_ICONINFORMATION);
return FALSE;
}
} else if ((fs == FS_NTFS) && (!iso_report.has_bootmgr) && (!IS_WINPE(iso_report.winpe))) {
if (iso_report.has_isolinux) {
- MessageBoxU(hMainDialog, "Only FAT/FAT32 is supported for this type of ISO. "
- "Please select FAT/FAT32 as the File system.", "Unsupported filesystem", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_096), lmprintf(MSG_092), MB_OK|MB_ICONERROR);
} else {
- MessageBoxU(hMainDialog, "Only 'bootmgr' or 'WinPE' based ISO "
- "images can currently be used with NTFS.", "Unsupported ISO", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_097), lmprintf(MSG_090), MB_OK|MB_ICONERROR);
}
return FALSE;
} else if (((fs == FS_FAT16)||(fs == FS_FAT32)) && (!iso_report.has_isolinux)) {
- MessageBoxU(hMainDialog, "FAT/FAT32 can only be used for isolinux based ISO images "
- "or when the Target Type is UEFI.", "Unsupported ISO", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_098), lmprintf(MSG_090), MB_OK|MB_ICONERROR);
return FALSE;
} else if (((fs == FS_FAT16)||(fs == FS_FAT32)) && (iso_report.has_4GB_file)) {
- MessageBoxU(hMainDialog, "This iso image contains a file larger than 4GB file, which is more than the "
- "maximum size allowed for a FAT or FAT32 file system.", "Filesystem limitation", MB_OK|MB_ICONERROR);
+ MessageBoxU(hMainDialog, lmprintf(MSG_100), lmprintf(MSG_099), MB_OK|MB_ICONERROR);
return FALSE;
}
if ((bt == BT_UEFI) && (iso_report.has_win7_efi) && (!WimExtractCheck())) {
- if (MessageBoxU(hMainDialog, "Your platform cannot extract files from WIM archives. WIM extraction "
- "is required to create EFI bootable Windows 7 and Windows Vista USB drives. You can fix that "
- "by installing a recent version of 7-Zip.\r\nDo you want to visit the 7-zip download page?",
- "Missing WIM support", MB_YESNO|MB_ICONERROR) == IDYES)
+ if (MessageBoxU(hMainDialog, lmprintf(MSG_102), lmprintf(MSG_101), MB_YESNO|MB_ICONERROR) == IDYES)
ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL);
return FALSE;
}
} else if (dt == DT_SYSLINUX_V5) {
_chdirU(app_dir);
- fd = fopen(ldlinux_c32, "rb");
+ fd = fopen(ldlinux_name, "rb");
if (fd != NULL) {
- uprintf("Will reuse '%s' for Syslinux v5\n", ldlinux_c32);
+ uprintf("Will reuse '%s' for Syslinux v5\n", ldlinux_name);
fclose(fd);
} else {
- PrintStatus(0, FALSE, "Missing '%s' file", ldlinux_c32);
- safe_sprintf(msgbox, sizeof(msgbox), "Syslinux v5.0 or later requires a '%s' file to be installed.\n"
- "Because this file is more than 100 KB in size, and always present on Syslinux v5+ ISO images, "
- "it is not embedded in " APPLICATION_NAME ".\n\n"
- APPLICATION_NAME " can download the missing file for you:\n"
- "- Select 'Yes' to connect to the internet and download the file\n"
- "- Select 'No' if you want to manually copy this file on the drive later\n\n"
- "Note: The file will be downloaded in the current directory and once a "
- "'%s' exists there, it will be reused automatically.\n", ldlinux_c32, ldlinux_c32);
- safe_sprintf(msgbox_title, sizeof(msgbox_title), "Download %s?", ldlinux_c32);
- r = MessageBoxU(hMainDialog, msgbox, msgbox_title, MB_YESNOCANCEL|MB_ICONWARNING);
+ PrintStatus(0, FALSE, lmprintf(MSG_206, ldlinux_name));
+ r = MessageBoxU(hMainDialog, lmprintf(MSG_104, ldlinux_name, ldlinux_name),
+ lmprintf(MSG_103, ldlinux_name), MB_YESNOCANCEL|MB_ICONWARNING);
if (r == IDCANCEL)
return FALSE;
if (r == IDYES) {
- SetWindowTextU(hISOProgressDlg, "Downloading file...");
- SetWindowTextU(hISOFileName, ldlinux_c32);
- DownloadFile(LDLINUX_C32_URL, ldlinux_c32, hISOProgressDlg);
+ SetWindowTextU(hISOProgressDlg, lmprintf(MSG_085, ldlinux_name));
+ SetWindowTextU(hISOFileName, LDLINUX_C32_URL);
+ DownloadFile(LDLINUX_C32_URL, ldlinux_name, hISOProgressDlg);
}
}
}
@@ -1295,7 +1259,7 @@ void InitDialog(HWND hDlg)
// Quite a burden to carry around as parameters
hMainDialog = hDlg;
hDeviceList = GetDlgItem(hDlg, IDC_DEVICE);
- hPartitionScheme = GetDlgItem(hDlg, IDC_PARTITION_SCHEME);
+ hPartitionScheme = GetDlgItem(hDlg, IDC_PARTITION_TYPE);
hFileSystem = GetDlgItem(hDlg, IDC_FILESYSTEM);
hClusterSize = GetDlgItem(hDlg, IDC_CLUSTERSIZE);
hLabel = GetDlgItem(hDlg, IDC_LABEL);
@@ -1344,6 +1308,11 @@ void InitDialog(HWND hDlg)
}
uprintf("Windows version: %s %d-bit\n", PrintWindowsVersion(nWindowsVersion), is_x64?64:32);
+ // Detect the LCID
+ uprintf("LCID: 0x%04X\n", GetUserDefaultLCID());
+
+ SetClusterSizeLabels();
+
// Prefer FreeDOS to MS-DOS
selection_default = DT_FREEDOS;
// Create the status line and initialize the taskbar icon for progress overlay
@@ -1355,21 +1324,19 @@ void InitDialog(HWND hDlg)
SendMessage(hProgress, PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000);
// Fill up the passes
for (i=0; i<4; i++) {
- safe_sprintf(tmp, sizeof(tmp), "%d Pass%s", i+1, (i==0)?"":"es");
- IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, tmp));
+ IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, lmprintf((i==0)?MSG_034:MSG_035, i+1)));
}
IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 1));
SetPassesTooltip();
// Fill up the DOS type dropdown
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "MS-DOS"), DT_WINME));
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "FreeDOS"), DT_FREEDOS));
- IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "ISO Image"), DT_ISO));
+ IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, lmprintf(MSG_036)), DT_ISO));
IGNORE_RETVAL(ComboBox_SetCurSel(hBootType, selection_default));
// Fill up the MBR masqueraded disk IDs ("8 disks should be enough for anybody")
- IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, "0x80 (default)"), 0x80));
+ IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_030, "0x80")), 0x80));
for (i=1; i<=7; i++) {
- sprintf(tmp, "0x%02x (%d%s disk)", 0x80+i, i+1, (i==1)?"nd":((i==2)?"rd":"th"));
- IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, tmp), 0x80+i));
+ IGNORE_RETVAL(ComboBox_SetItemData(hDiskID, ComboBox_AddStringU(hDiskID, lmprintf(MSG_109, 0x80+i, i+1)), 0x80+i));
}
IGNORE_RETVAL(ComboBox_SetCurSel(hDiskID, 0));
@@ -1413,26 +1380,23 @@ void InitDialog(HWND hDlg)
SendMessage(GetDlgItem(hDlg, IDC_ADVANCED), BCM_SETIMAGELIST, 0, (LPARAM)&bi_down);
// Set the various tooltips
- CreateTooltip(hFileSystem, "Sets the target filesystem", -1);
- CreateTooltip(hClusterSize, "Minimum size that each data block occupies", -1);
- CreateTooltip(hLabel, "Use this field to set the drive label\nInternational characters are accepted", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_ADVANCED), "Toggle advanced options", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_BADBLOCKS), "Test the device for bad blocks using a byte pattern", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_QUICKFORMAT), "Unchek this box to use the \"slow\" format method", -1);
- CreateTooltip(hBoot, "Check this box to make the USB drive bootable", -1);
- CreateTooltip(hBootType, "Boot method", -1);
- CreateTooltip(hSelectISO, "Click to select an ISO...", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_SET_ICON), "Check this box to allow the display of international labels "
- "and set a device icon (creates an autorun.inf)", 10000);
- CreateTooltip(GetDlgItem(hDlg, IDC_RUFUS_MBR), "Install an MBR that allows boot selection and can masquerade the BIOS USB drive ID", 10000);
- CreateTooltip(hDiskID, "Try to masquerade first bootable USB drive (usually 0x80) as a different disk.\n"
- "This should only be necessary for XP installation" , 10000);
- CreateTooltip(GetDlgItem(hDlg, IDC_EXTRA_PARTITION), "Create an extra hidden partition and try to align partitions boundaries.\n"
- "This can improve boot detection for older BIOSes", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_ENABLE_FIXED_DISKS), "Enable detection for disks not normally detected by " APPLICATION_NAME ". "
- "USE AT YOUR OWN RISKS!!!", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_START), "Start the formatting operation.\nThis will DESTROY any data on the target!", -1);
- CreateTooltip(GetDlgItem(hDlg, IDC_ABOUT), "Licensing information and credits", -1);
+ CreateTooltip(hFileSystem, lmprintf(MSG_157), -1);
+ CreateTooltip(hClusterSize, lmprintf(MSG_158), -1);
+ CreateTooltip(hLabel, lmprintf(MSG_159), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_ADVANCED), lmprintf(MSG_160), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_BADBLOCKS), lmprintf(MSG_161), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_QUICKFORMAT), lmprintf(MSG_162), -1);
+ CreateTooltip(hBoot, lmprintf(MSG_163), -1);
+ CreateTooltip(hBootType, lmprintf(MSG_164), -1);
+ CreateTooltip(hSelectISO, lmprintf(MSG_165), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_SET_ICON), lmprintf(MSG_166), 10000);
+ CreateTooltip(GetDlgItem(hDlg, IDC_RUFUS_MBR), lmprintf(MSG_167), 10000);
+ CreateTooltip(hDiskID, lmprintf(MSG_168), 10000);
+ CreateTooltip(GetDlgItem(hDlg, IDC_EXTRA_PARTITION), lmprintf(MSG_169), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_ENABLE_FIXED_DISKS), lmprintf(MSG_170), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_START), lmprintf(MSG_171), -1);
+ CreateTooltip(GetDlgItem(hDlg, IDC_ABOUT), lmprintf(MSG_172), -1);
+ // TODO: add new tooltips
ToggleAdvanced(); // We start in advanced mode => go to basic mode
@@ -1445,9 +1409,10 @@ void InitDialog(HWND hDlg)
static void PrintStatus2000(const char* str, BOOL val)
{
- PrintStatus(2000, FALSE, "%s %s.", str, (val)?"enabled":"disabled");
+ PrintStatus(2000, FALSE, (lmprintf((val)?MSG_250:MSG_251, str)));
}
+
/*
* Main dialog callback
*/
@@ -1456,9 +1421,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
DRAWITEMSTRUCT* pDI;
POINT Point;
RECT DialogRect, DesktopRect;
- int nDeviceIndex, fs, bt, i, nWidth, nHeight;
+ int nDeviceIndex, fs, bt, i, nWidth, nHeight, nb_devices;
static DWORD DeviceNum = 0, LastRefresh = 0;
- char tmp[128], str[MAX_PATH];
+ char tmp[128];
static UINT uBootChecked = BST_CHECKED, uQFChecked;
static BOOL first_log_display = TRUE, user_changed_label = FALSE;
@@ -1497,9 +1462,10 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break;
case WM_INITDIALOG:
+ apply_localization(IDD_DIALOG, hDlg);
SetUpdateCheck();
// Create the log window (hidden)
- hLogDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_LOG), hDlg, (DLGPROC)LogProc);
+ hLogDlg = CreateDialogW(hMainInstance, MAKEINTRESOURCEW(IDD_LOG), hDlg, (DLGPROC)LogProc);
InitDialog(hDlg);
GetUSBDevices(0);
CheckForUpdates(FALSE);
@@ -1533,13 +1499,12 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE);
EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
if (format_thid != NULL) {
- if (MessageBoxU(hMainDialog, "Cancelling may leave the device in an UNUSABLE state.\r\n"
- "If you are sure you want to cancel, click YES. Otherwise, click NO.",
- RUFUS_CANCELBOX_TITLE, MB_YESNO|MB_ICONWARNING) == IDYES) {
+ if (MessageBoxU(hMainDialog, lmprintf(MSG_105), lmprintf(MSG_049),
+ MB_YESNO|MB_ICONWARNING) == IDYES) {
// Operation may have completed in the meantime
if (format_thid != NULL) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
- PrintStatus(0, FALSE, "Cancelling - Please wait...");
+ PrintStatus(0, FALSE, lmprintf(MSG_201));
uprintf("Cancelling (from main app)\n");
// Start a timer to detect blocking operations during ISO file extraction
if (iso_blocking_status >= 0) {
@@ -1606,8 +1571,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case IDC_DEVICE:
if (HIWORD(wParam) != CBN_SELCHANGE)
break;
- PrintStatus(0, TRUE, "%d device%s found.", ComboBox_GetCount(hDeviceList),
- (ComboBox_GetCount(hDeviceList)!=1)?"s":"");
+ nb_devices = ComboBox_GetCount(hDeviceList);
+ PrintStatus(0, TRUE, lmprintf((nb_devices==1)?MSG_208:MSG_209, nb_devices));
PopulateProperties(ComboBox_GetCurSel(hDeviceList));
SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM,
ComboBox_GetCurSel(hFileSystem));
@@ -1617,7 +1582,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break;
SetPassesTooltip();
break;
- case IDC_PARTITION_SCHEME:
+ case IDC_PARTITION_TYPE:
if (HIWORD(wParam) != CBN_SELCHANGE)
break;
SetPartitionSchemeTooltip();
@@ -1673,7 +1638,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "MS-DOS"), DT_WINME));
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "FreeDOS"), DT_FREEDOS));
}
- IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "ISO Image"), DT_ISO));
+ IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, lmprintf(MSG_036)), DT_ISO));
// If needed (advanced mode) also append a Syslinux option
if ( (bt == BT_BIOS) && (((fs == FS_FAT16) || (fs == FS_FAT32)) && (advanced_mode)) ) {
IGNORE_RETVAL(ComboBox_SetItemData(hBootType, ComboBox_AddStringU(hBootType, "Syslinux 4"), DT_SYSLINUX_V4));
@@ -1729,9 +1694,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
iso_provided = FALSE; // One off thing...
} else {
safe_free(iso_path);
- iso_path = FileDialog(FALSE, NULL, "*.iso", "iso", "ISO Image");
+ iso_path = FileDialog(FALSE, NULL, "*.iso", "iso", lmprintf(MSG_036));
if (iso_path == NULL) {
- CreateTooltip(hSelectISO, "Click to select...", -1);
+ CreateTooltip(hSelectISO, lmprintf(MSG_173), -1);
break;
}
}
@@ -1750,7 +1715,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case IDC_ENABLE_FIXED_DISKS:
if ((HIWORD(wParam)) == BN_CLICKED) {
enable_fixed_disks = !enable_fixed_disks;
- PrintStatus2000("Fixed disks detection", enable_fixed_disks);
+ PrintStatus2000(lmprintf(MSG_253), enable_fixed_disks);
GetUSBDevices(0);
}
break;
@@ -1773,9 +1738,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break;
}
GetWindowTextU(hDeviceList, tmp, ARRAYSIZE(tmp));
- _snprintf(str, ARRAYSIZE(str), "WARNING: ALL DATA ON DEVICE '%s'\r\nWILL BE DESTROYED.\r\n"
- "To continue with this operation, click OK. To quit click CANCEL.", tmp);
- if (MessageBoxU(hMainDialog, str, APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL) {
+ if (MessageBoxU(hMainDialog, lmprintf(MSG_003, tmp),
+ APPLICATION_NAME, MB_OKCANCEL|MB_ICONWARNING) == IDCANCEL) {
format_op_in_progress = FALSE;
break;
}
@@ -1818,7 +1782,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// You'd think that Windows would let you instantiate a modeless dialog wherever
// but you'd be wrong. It must be done in the main callback, hence the custom message.
if (!IsWindow(hISOProgressDlg)) {
- hISOProgressDlg = CreateDialogA(hMainInstance, MAKEINTRESOURCEA(IDD_ISO_EXTRACT),
+ hISOProgressDlg = CreateDialogW(hMainInstance, MAKEINTRESOURCEW(IDD_ISO_EXTRACT),
hDlg, (DLGPROC)ISOProc);
// The window is not visible by default but takes focus => restore it
SetFocus(hDlg);
@@ -1830,8 +1794,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// Stop the timer
KillTimer(hMainDialog, TID_APP_TIMER);
// Close the cancel MessageBox and Blocking notification if active
- SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_CANCELBOX_TITLE), WM_COMMAND, IDNO, 0);
- SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), RUFUS_BLOCKING_IO_TITLE), WM_COMMAND, IDYES, 0);
+ SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), lmprintf(MSG_049)), WM_COMMAND, IDNO, 0);
+ SendMessage(FindWindowA(MAKEINTRESOURCEA(32770), lmprintf(MSG_049)), WM_COMMAND, IDYES, 0);
EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), TRUE);
EnableWindow(GetDlgItem(hMainDialog, IDCANCEL), TRUE);
EnableControls(TRUE);
@@ -1843,17 +1807,17 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SendMessage(hProgress, PBM_SETPOS, (MAX_PROGRESS+1), 0);
SendMessage(hProgress, PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000);
SetTaskbarProgressState(TASKBAR_NOPROGRESS);
- PrintStatus(0, FALSE, "DONE");
+ PrintStatus(0, FALSE, lmprintf(MSG_210));
} else if (SCODE_CODE(FormatStatus) == ERROR_CANCELLED) {
SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_PAUSED, 0);
SetTaskbarProgressState(TASKBAR_PAUSED);
- PrintStatus(0, FALSE, "Cancelled");
- Notification(MSG_INFO, NULL, "Cancelled", "Operation cancelled by the user.");
+ PrintStatus(0, FALSE, lmprintf(MSG_211));
+ Notification(MSG_INFO, NULL, lmprintf(MSG_211), lmprintf(MSG_041));
} else {
SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0);
SetTaskbarProgressState(TASKBAR_ERROR);
- PrintStatus(0, FALSE, "FAILED");
- Notification(MSG_ERROR, NULL, "Error", "Error: %s", StrError(FormatStatus));
+ PrintStatus(0, FALSE, lmprintf(MSG_212));
+ Notification(MSG_ERROR, NULL, lmprintf(MSG_042), lmprintf(MSG_043), StrError(FormatStatus));
}
FormatStatus = 0;
format_op_in_progress = FALSE;
@@ -1912,10 +1876,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
const char* old_wait_option = "/W";
int i, opt, option_index = 0, argc = 0, si = 0;
BOOL attached_console = FALSE;
+ BYTE* loc_data;
+ DWORD loc_size, Size;
+ char tmp_path[MAX_PATH], loc_file[MAX_PATH] = "", *locale_name = NULL;
char** argv = NULL;
wchar_t **wenv, **wargv;
PF_DECL(__wgetmainargs);
- HANDLE mutex = NULL;
+ HANDLE mutex = NULL, hFile = NULL;
HWND hDlg = NULL;
MSG msg;
int wait_for_mutex = 0;
@@ -1938,7 +1905,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
printf("\n");
}
- // We have to process the arguments before we acquire the lock
+ // We have to process the arguments before we acquire the lock and process the locale
PF_INIT(__wgetmainargs, msvcrt);
if (pf__wgetmainargs != NULL) {
pf__wgetmainargs(&argc, &wargv, &wenv, 1, &si);
@@ -1950,7 +1917,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
wait_for_mutex = 150; // Try to acquire the mutex for 15 seconds
}
- while ((opt = getopt_long(argc, argv, "?fhi:w:", long_options, &option_index)) != EOF)
+ while ((opt = getopt_long(argc, argv, "?fhi:w:l:", long_options, &option_index)) != EOF)
switch (opt) {
case 'f':
enable_fixed_disks = TRUE;
@@ -1963,6 +1930,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
printf("Could not find ISO image '%s'\n", optarg);
}
break;
+ case 'l':
+ // TODO: accept a locale code such as 0x409
+ locale_name = optarg;
+ break;
case 'w':
wait_for_mutex = atoi(optarg);
break;
@@ -1976,6 +1947,44 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
uprintf("unable to access UTF-16 args");
}
+ // Retrieve the current application directory
+ GetCurrentDirectoryU(MAX_PATH, app_dir);
+
+ // Init localization
+ init_localization();
+ // Seek for a loc file in the current directory
+ if (GetFileAttributesU("rufus.loc") == INVALID_FILE_ATTRIBUTES) {
+ uprintf("loc file not found in current directory - embedded one will be used");
+
+ loc_data = (BYTE*)GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_LC_RUFUS_LOC), _RT_RCDATA, "rufus.loc", &loc_size, FALSE);
+ GetTempPathU(sizeof(tmp_path), tmp_path);
+ GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, loc_file);
+
+ hFile = CreateFileU(loc_file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, 0, 0);
+ if ((hFile == INVALID_HANDLE_VALUE)|| (!WriteFile(hFile, loc_data, loc_size, &Size, 0)) || (loc_size != Size)) {
+ safe_closehandle(hFile);
+ uprintf("localization: unable to extract '%s': %s.\n", loc_file, WindowsErrorString());
+ } else {
+ safe_closehandle(hFile);
+ uprintf("localization: extracted data to '%s'\n", loc_file);
+ }
+ } else {
+ safe_sprintf(loc_file, sizeof(loc_file), "%s\\rufus.loc", app_dir);
+ uprintf("using external loc file '%s'", loc_file);
+ }
+
+ if ( (!get_supported_locales(loc_file))
+ || ((selected_locale = ((locale_name == NULL)?get_locale_from_lcid(GetUserDefaultLCID()):get_locale_from_name(locale_name))) == NULL) ) {
+ uprintf("FATAL: Could not access locale!\n");
+ MessageBoxU(NULL, "The locale data is missing. This application will now exit.",
+ "Fatal error", MB_ICONSTOP);
+ goto out;
+ }
+ uprintf("localization: using locale '%s'\n", selected_locale->txt[0]);
+ get_loc_data_file(loc_file, (long)selected_locale->num[0], (long)selected_locale->num[1], selected_locale->line_nr);
+
+
// Prevent 2 applications from running at the same time, unless "/W" is passed as an option
// in which case we wait for the mutex to be relinquished
if ((safe_strlen(lpCmdLine)==2) && (lpCmdLine[0] == '/') && (lpCmdLine[1] == 'W'))
@@ -1987,9 +1996,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
mutex = CreateMutexA(NULL, TRUE, "Global/" APPLICATION_NAME);
}
if ((mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
- MessageBoxU(NULL, "Another " APPLICATION_NAME " application is running.\n"
- "Please close the first application before running another one.",
- "Other instance detected", MB_ICONSTOP);
+ MessageBoxU(NULL, lmprintf(MSG_002), lmprintf(MSG_001), MB_ICONSTOP);
goto out;
}
@@ -2004,9 +2011,6 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
uprintf("Could not load RichEdit library - some dialogs may not display: %s\n", WindowsErrorString());
}
- // Retrieve the current application directory
- GetCurrentDirectoryU(MAX_PATH, app_dir);
-
// Set the Windows version
nWindowsVersion = DetectWindowsVersion();
@@ -2015,7 +2019,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
SetLGP(FALSE, &existing_key, "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", "NoDriveTypeAutorun", 0x9e);
// Create the main Window
- if ( (hDlg = CreateDialogA(hInstance, MAKEINTRESOURCEA(IDD_DIALOG), NULL, MainCallback)) == NULL ) {
+ hDlg = CreateDialogW(hInstance, MAKEINTRESOURCEW(IDD_DIALOG), NULL, MainCallback);
+ if (hDlg == NULL) {
MessageBoxU(NULL, "Could not create Window", "DialogBox failure", MB_ICONSTOP);
goto out;
}
@@ -2031,7 +2036,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// the target USB drive. If this is enabled, the size check is disabled.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'S')) {
size_check = !size_check;
- PrintStatus2000("Size checks", size_check);
+ PrintStatus2000(lmprintf(MSG_252), size_check);
GetUSBDevices(0);
continue;
}
@@ -2041,20 +2046,20 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// drive instead of an USB key. If this is enabled, Rufus will allow fixed disk formatting.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'F')) {
enable_fixed_disks = !enable_fixed_disks;
- PrintStatus2000("Fixed disks detection", enable_fixed_disks);
+ PrintStatus2000(lmprintf(MSG_253), enable_fixed_disks);
GetUSBDevices(0);
continue;
}
// Alt-L => Force Large FAT32 format to be used on < 32 GB drives
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'L')) {
force_large_fat32 = !force_large_fat32;
- PrintStatus2000("Force large FAT32 usage", force_large_fat32);
+ PrintStatus2000(lmprintf(MSG_254), force_large_fat32);
continue;
}
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
// This key is used to disable Windows popup messages when an USB drive is plugged in.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) {
- PrintStatus(2000, FALSE, "NoDriveTypeAutorun will be deleted on exit.");
+ PrintStatus(2000, FALSE, lmprintf(MSG_255));
existing_key = FALSE;
continue;
}
@@ -2064,13 +2069,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// a file name). This option allows users to ignore Joliet when using such images.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'J')) {
enable_joliet = !enable_joliet;
- PrintStatus2000("Joliet support", enable_joliet);
+ PrintStatus2000(lmprintf(MSG_257), enable_joliet);
continue;
}
- // Alt K => Toggle Rock Ridge support for ISO9660 image
+ // Alt K => Toggle Rock Ridge support for ISO9660 images
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'K')) {
enable_rockridge = !enable_rockridge;
- PrintStatus2000("Rock Ridge support", enable_rockridge);
+ PrintStatus2000(lmprintf(MSG_258), enable_rockridge);
continue;
}
// Alt L => Toggle fake drive detection during bad blocks check
@@ -2080,13 +2085,12 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
// it back during the bad block check.
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'L')) {
detect_fakes = !detect_fakes;
- PrintStatus2000("Fake drive detection", detect_fakes);
+ PrintStatus2000(lmprintf(MSG_256), detect_fakes);
continue;
}
// Alt-R => Remove all the registry keys created by Rufus
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'R')) {
- PrintStatus(2000, FALSE, "Application registry key %s deleted.",
- DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME)?"successfully":"could not be");
+ PrintStatus(2000, FALSE, lmprintf(DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME "\\" APPLICATION_NAME)?MSG_248:MSG_249));
// Also try to delete the upper key (company name) if it's empty (don't care about the result)
DeleteRegistryKey(REGKEY_HKCU, COMPANY_NAME);
continue;
@@ -2097,7 +2101,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
}
out:
+ if (loc_file[0] != 0)
+ DeleteFileU(loc_file);
DestroyAllTooltips();
+ exit_localization();
safe_free(iso_path);
safe_free(update.download_url);
safe_free(update.release_notes);
diff --git a/src/rufus.h b/src/rufus.h
index b0ba811a..3d969187 100644
--- a/src/rufus.h
+++ b/src/rufus.h
@@ -17,6 +17,7 @@
*/
#include
#include // for DISK_GEOMETRY
+#include
#include
#if defined(_MSC_VER)
@@ -29,19 +30,19 @@
/* Program options */
#define RUFUS_DEBUG // print debug info to Debug facility
/* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */
-//#define RUFUS_TEST
+// #define RUFUS_TEST
#define APPLICATION_NAME "Rufus"
#define COMPANY_NAME "Akeo Consulting"
#define STR_NO_LABEL "NO_LABEL"
-#define RUFUS_CANCELBOX_TITLE APPLICATION_NAME " - Cancellation"
-#define RUFUS_BLOCKING_IO_TITLE APPLICATION_NAME " - Flushing buffers"
#define DRIVE_ACCESS_TIMEOUT 15000 // How long we should retry drive access (in ms)
#define DRIVE_ACCESS_RETRIES 60 // How many times we should retry
#define DRIVE_INDEX_MIN 0x00000080
#define DRIVE_INDEX_MAX 0x000000C0
#define MAX_DRIVES (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN)
-#define MAX_TOOLTIPS 32
+#define MAX_TOOLTIPS 128
+#define MAX_SIZE_SUFFIXES 6 // bytes, KB, MB, GB, TB, PB
+#define MAX_CLUSTER_SIZES 18
#define MAX_PROGRESS (0xFFFF-1) // leave room for 1 more for insta-progress workaround
#define MAX_LOG_SIZE 0x7FFFFFFE
#define MAX_GUID_STRING_LENGTH 40
@@ -50,6 +51,7 @@
#define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword
#define PROPOSEDLABEL_TOLERANCE 0.10
#define FS_DEFAULT FS_FAT32
+#define BADBLOCK_PATTERNS {0xaa, 0x55, 0xff, 0x00}
#define LARGE_FAT32_SIZE (32*1073741824LL) // Size at which we need to use fat32format
#define MAX_FAT32_SIZE 2.0f // Threshold above which we disable FAT32 formatting (in TB)
#define WHITE RGB(255,255,255)
@@ -283,12 +285,13 @@ extern enum WindowsVersion DetectWindowsVersion(void);
extern const char* PrintWindowsVersion(enum WindowsVersion version);
extern const char *WindowsErrorString(void);
extern void DumpBufferHex(void *buf, size_t size);
-extern void PrintStatus(unsigned int duration, BOOL debug, const char *format, ...);
+extern void PrintStatus(unsigned int duration, BOOL debug, const char* message);
extern void UpdateProgress(int op, float percent);
extern const char* StrError(DWORD error_code);
extern char* GuidToString(const GUID* guid);
extern char* SizeToHumanReadable(LARGE_INTEGER size);
extern void CenterDialog(HWND hDlg);
+extern void ResizeMoveCtrl(HWND hDlg, HWND hCtrl, int dx, int dy, int dw, int dh);
extern void CreateStatusBar(void);
extern void SetTitleBarIcon(HWND hDlg);
extern BOOL CreateTaskbarList(void);
@@ -342,12 +345,20 @@ extern void parse_update(char* buf, size_t len);
extern BOOL WimExtractCheck(void);
extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst);
-__inline static BOOL UnlockDrive(HANDLE hDrive)
+static __inline BOOL UnlockDrive(HANDLE hDrive)
{
DWORD size;
return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
}
+static __inline void *_reallocf(void *ptr, size_t size)
+{
+ void *ret = realloc(ptr, size);
+ if (!ret)
+ free(ptr);
+ return ret;
+}
+
/* Basic String Array */
typedef struct {
char** Table;
diff --git a/src/rufus.rc b/src/rufus.rc
index e8dedcf5..b91d7f6b 100644
--- a/src/rufus.rc
+++ b/src/rufus.rc
@@ -30,48 +30,48 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 206, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
-CAPTION "Rufus v1.4.0.280"
+CAPTION "Rufus v1.4.0.281"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
PUSHBUTTON "Close",IDCANCEL,148,291,50,14
- COMBOBOX IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- CONTROL "Device",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,9,6,22,8
- COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "File system",IDC_STATIC,9,64,51,10
- COMBOBOX IDC_PARTITION_SCHEME,8,46,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "Partition scheme and target system type",IDC_STATIC,9,35,176,8
- COMBOBOX IDC_CLUSTERSIZE,8,104,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "Cluster size",IDC_STATIC,9,93,105,10
PUSHBUTTON "About...",IDC_ABOUT,8,291,50,14
- GROUPBOX "Format Options ",IDC_STATIC,7,149,192,66
+ PUSHBUTTON "Log",IDC_LOG,62,291,18,14
+ PUSHBUTTON "T",IDC_TEST,80,291,12,14,NOT WS_VISIBLE
+ COMBOBOX IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Device",IDS_DEVICE_TXT,9,6,186,8
+ COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "File system",IDS_FILESYSTEM_TXT,9,64,186,10
+ COMBOBOX IDC_PARTITION_TYPE,8,46,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Partition scheme and target system type",IDS_PARTITION_TYPE_TXT,9,35,186,8
+ COMBOBOX IDC_CLUSTERSIZE,8,104,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Cluster size",IDS_CLUSTERSIZE_TXT,9,93,186,10
+ GROUPBOX "Format Options ",IDS_FORMAT_OPTIONS_GRP,7,149,192,66
+ LTEXT "New volume label",IDS_LABEL_TXT,9,121,186,10
EDITTEXT IDC_LABEL,7,131,190,13,ES_AUTOHSCROLL
CONTROL "Check device for bad blocks:",IDC_BADBLOCKS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,161,101,10
- CONTROL "Quick format",IDC_QUICKFORMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,173,55,10
+ CONTROL "Quick format",IDC_QUICKFORMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,173,181,10
CONTROL "Create a bootable disk using:",IDC_BOOT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,185,104,10
CONTROL "Create extended label and icon files",IDC_SET_ICON,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,198,131,10
- LTEXT "New volume label",IDC_STATIC,9,121,105,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,198,181,10
CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,8,272,189,9
COMBOBOX IDC_NBPASSES,119,159,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
COMBOBOX IDC_BOOTTYPE,119,183,49,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "...",IDC_SELECT_ISO,171,182,22,14,BS_ICON
- PUSHBUTTON "T",IDC_TEST,80,291,12,14,NOT WS_VISIBLE
- CONTROL "Use Rufus MBR with BIOS ID:",IDC_RUFUS_MBR,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,13,248,106,10
+ CONTROL "Use Rufus MBR with BIOS ID:",IDC_RUFUS_MBR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,248,106,10
PUSHBUTTON "",IDC_ADVANCED,63,148,14,10,BS_TOP | BS_FLAT
- GROUPBOX "Advanced Options",IDC_ADVANCED_GROUP,7,210,192,54,NOT WS_VISIBLE
- COMBOBOX IDC_DISK_ID,119,246,73,30,CBS_DROPDOWNLIST | NOT WS_VISIBLE | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Advanced Options",IDS_ADVANCED_OPTIONS_GRP,7,210,192,54
+ COMBOBOX IDC_DISK_ID,119,246,73,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "Add fixes for old BIOSes (extra partition, align, etc.)",IDC_EXTRA_PARTITION,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,235,184,10
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,235,181,10
CONTROL "List fixed (non-flash) or unpartitioned USB disks",IDC_ENABLE_FIXED_DISKS,
- "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,222,185,10
- PUSHBUTTON "Log",IDC_LOG,62,291,18,14
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,222,181,10
END
IDD_ABOUTBOX DIALOGEX 0, 0, 287, 201
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About Rufus"
-FONT 8, "Microsoft Sans Serif", 400, 0, 0x0
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
ICON IDI_ICON,IDC_ABOUT_ICON,11,8,20,20
DEFPUSHBUTTON "OK",IDOK,231,181,50,14,WS_GROUP
@@ -128,36 +128,35 @@ END
IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Update policy and settings"
-FONT 8, "Microsoft Sans Serif", 400, 0, 0x0
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
- ICON IDI_ICON,IDC_ABOUT_ICON,11,8,21,20
+ ICON IDI_ICON,IDC_ABOUT_ICON,11,8,20,20
DEFPUSHBUTTON "Close",IDCANCEL,221,172,50,14,WS_GROUP
CONTROL "",IDC_POLICY,"RichEdit20W",WS_VSCROLL | 0x804,46,8,235,130,WS_EX_STATICEDGE
COMBOBOX IDC_UPDATE_FREQUENCY,133,155,66,12,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "Check for updates:",IDC_STATIC,52,157,72,11
- LTEXT "Include beta versions:",IDC_STATIC,52,173,93,11
+ LTEXT "Check for updates:",IDS_UPDATE_FREQUENCY_TXT,52,157,80,11
+ LTEXT "Include beta versions:",IDS_INCLUDE_BETAS_TXT,52,173,80,11
COMBOBOX IDC_INCLUDE_BETAS,133,171,36,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- GROUPBOX "Settings",IDC_STATIC,45,145,161,46
+ GROUPBOX "Settings",IDS_UPDATE_SETTINGS_GRP,45,145,161,46
PUSHBUTTON "Check Now",IDC_CHECK_NOW,221,154,50,14
- GROUPBOX "",IDC_STATIC,210,145,71,46
+ GROUPBOX "",IDS_CHECK_NOW_GRP,210,145,71,46
END
IDD_NEW_VERSION DIALOGEX 0, 0, 384, 268
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Check For Updates - Rufus"
-FONT 8, "Microsoft Sans Serif", 400, 0, 0x0
+FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
PUSHBUTTON "Close",IDCANCEL,167,244,50,14,WS_GROUP
- CONTROL "",IDC_RELEASE_NOTES,"RichEdit20W",WS_VSCROLL | 0x804,15,77,352,88,WS_EX_STATICEDGE
+ CONTROL "",IDC_RELEASE_NOTES,"RichEdit20W",ES_MULTILINE | ES_READONLY | WS_VSCROLL,15,77,352,88,WS_EX_STATICEDGE
DEFPUSHBUTTON "Download",IDC_DOWNLOAD,293,211,74,14,WS_GROUP
CONTROL "",IDC_PROGRESS,"msctls_progress32",WS_BORDER,15,212,270,11
- GROUPBOX "Release Notes",IDC_STATIC,8,63,367,111
- LTEXT "A newer version is available. Please download the latest version!",IDC_STATIC,10,32,229,8
+ GROUPBOX "Release Notes",IDS_NEW_VERSION_NOTES_GRP,8,63,367,111
+ LTEXT "A newer version is available. Please download the latest version!",IDS_NEW_VERSION_AVAIL_TXT,10,32,229,8
LTEXT "[...]",IDC_YOUR_VERSION,10,8,124,8
LTEXT "[...]",IDC_LATEST_VERSION,10,19,129,8
- CONTROL "Click here to go to the website",IDC_WEBSITE,
- "SysLink",WS_TABSTOP,143,49,96,9
- GROUPBOX "Download",IDC_STATIC,8,177,367,58
+ LTEXT " Click here to go to the website",IDC_WEBSITE,138,49,108,9,SS_NOTIFY
+ GROUPBOX "Download",IDS_NEW_VERSION_DOWNLOAD_GRP,8,177,367,58
EDITTEXT IDC_DOWNLOAD_URL,15,191,351,13,ES_AUTOHSCROLL | ES_READONLY
END
@@ -185,6 +184,7 @@ END
3 TEXTINCLUDE
BEGIN
"\r\n"
+ "IDR_LC_RUFUS_LOC RCDATA ""../res/localization/rufus.loc""\r\n"
"IDR_SL_LDLINUX_V4_BSS RCDATA ""../res/syslinux/ldlinux_v4.bss""\r\n"
"IDR_SL_LDLINUX_V4_SYS RCDATA ""../res/syslinux/ldlinux_v4.sys""\r\n"
"IDR_SL_LDLINUX_V5_BSS RCDATA ""../res/syslinux/ldlinux_v5.bss""\r\n"
@@ -278,8 +278,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,4,0,280
- PRODUCTVERSION 1,4,0,280
+ FILEVERSION 1,4,0,281
+ PRODUCTVERSION 1,4,0,281
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -296,13 +296,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
- VALUE "FileVersion", "1.4.0.280"
+ VALUE "FileVersion", "1.4.0.281"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", " 2011-2013 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
- VALUE "ProductVersion", "1.4.0.280"
+ VALUE "ProductVersion", "1.4.0.281"
END
END
BLOCK "VarFileInfo"
@@ -333,6 +333,7 @@ IDI_DOWN ICON "../res/down.ico"
// Generated from the TEXTINCLUDE 3 resource.
//
+IDR_LC_RUFUS_LOC RCDATA "../res/localization/rufus.loc"
IDR_SL_LDLINUX_V4_BSS RCDATA "../res/syslinux/ldlinux_v4.bss"
IDR_SL_LDLINUX_V4_SYS RCDATA "../res/syslinux/ldlinux_v4.sys"
IDR_SL_LDLINUX_V5_BSS RCDATA "../res/syslinux/ldlinux_v5.bss"
diff --git a/src/stdfn.c b/src/stdfn.c
index 7b1f21a6..da666421 100644
--- a/src/stdfn.c
+++ b/src/stdfn.c
@@ -26,6 +26,8 @@
#include "msapi_utf8.h"
#include "rufus.h"
+#include "resource.h"
+#include "localization.h"
// Must be in the same order as enum WindowsVersion
static const char* WindowsVersionName[WINDOWS_MAX] = {
@@ -232,7 +234,7 @@ BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size)
goto out;
}
- PrintStatus(0, TRUE, "%s '%s'", save?"Saved":"Opened", path);
+ PrintStatus(0, TRUE, save?lmprintf(MSG_216, path):lmprintf(MSG_215, path));
ret = TRUE;
out:
diff --git a/src/stdio.c b/src/stdio.c
index bfc7bbef..2c32f3a4 100644
--- a/src/stdio.c
+++ b/src/stdio.c
@@ -31,6 +31,7 @@
#include "msapi_utf8.h"
#include "rufus.h"
#include "resource.h"
+#include "localization.h"
/*
* Globals
@@ -40,7 +41,8 @@ HWND hStatus;
#ifdef RUFUS_DEBUG
void _uprintf(const char *format, ...)
{
- char buf[4096], *p = buf;
+ static char buf[4096];
+ char* p = buf;
va_list args;
int n;
@@ -50,7 +52,7 @@ void _uprintf(const char *format, ...)
p += (n < 0)?sizeof(buf)-3:n;
- while((p>buf) && (isspace((unsigned char)p[-1])))
+ while((p>buf) && (isspaceU(p[-1])))
*--p = '\0';
*p++ = '\r';
@@ -145,23 +147,11 @@ static void CALLBACK PrintStatusTimeout(HWND hwnd, UINT uMsg, UINT_PTR idEvent,
KillTimer(hMainDialog, TID_MESSAGE);
}
-void PrintStatus(unsigned int duration, BOOL debug, const char *format, ...)
+void PrintStatus(unsigned int duration, BOOL debug, const char* message)
{
- char *p = szStatusMessage;
- va_list args;
- int n;
-
- va_start(args, format);
- n = safe_vsnprintf(p, sizeof(szStatusMessage)-1, format, args); // room for NUL
- va_end(args);
-
- p += (n < 0)?sizeof(szStatusMessage)-1:n;
-
- while((p>szStatusMessage) && (isspace(p[-1])))
- *--p = '\0';
-
- *p = '\0';
-
+ if (message == NULL)
+ return;
+ safe_strcpy(szStatusMessage, sizeof(szStatusMessage), message);
if (debug)
uprintf("%s\n", szStatusMessage);
@@ -192,17 +182,16 @@ char* GuidToString(const GUID* guid)
char* SizeToHumanReadable(LARGE_INTEGER size)
{
int suffix = 0;
- static char str_size[24];
- const char* sizes[] = { "", "KB", "MB", "GB", "TB" };
+ static char str_size[32];
double hr_size = (double)size.QuadPart;
- while ((suffix < ARRAYSIZE(sizes)) && (hr_size >= 1024.0)) {
+ while ((suffix < MAX_SIZE_SUFFIXES) && (hr_size >= 1024.0)) {
hr_size /= 1024.0;
suffix++;
}
if (suffix == 0) {
- safe_sprintf(str_size, sizeof(str_size), "%d bytes", (int)hr_size);
+ safe_sprintf(str_size, sizeof(str_size), "%d %s", (int)hr_size, lmprintf(MSG_020));
} else {
- safe_sprintf(str_size, sizeof(str_size), "%0.1f %s", hr_size, sizes[suffix]);
+ safe_sprintf(str_size, sizeof(str_size), "%0.1f %s", hr_size, lmprintf(MSG_020 + suffix));
}
return str_size;
}
@@ -210,7 +199,7 @@ char* SizeToHumanReadable(LARGE_INTEGER size)
const char* StrError(DWORD error_code)
{
if ( (!IS_ERROR(error_code)) || (SCODE_CODE(error_code) == ERROR_SUCCESS)) {
- return "Success";
+ return lmprintf(MSG_044);
}
if (SCODE_FACILITY(error_code) != FACILITY_STORAGE) {
uprintf("StrError: non storage - %08X (%X)\n", error_code, SCODE_FACILITY(error_code));
@@ -219,63 +208,61 @@ const char* StrError(DWORD error_code)
}
switch (SCODE_CODE(error_code)) {
case ERROR_GEN_FAILURE:
- return "Undetermined error while formatting.";
+ return lmprintf(MSG_051);
case ERROR_INCOMPATIBLE_FS:
- return "Cannot use the selected file system for this media.";
+ return lmprintf(MSG_052);
case ERROR_ACCESS_DENIED:
- return "Access to the device is denied.";
+ return lmprintf(MSG_053);
case ERROR_WRITE_PROTECT:
- return "Media is write protected.";
+ return lmprintf(MSG_054);
case ERROR_DEVICE_IN_USE:
- return "The device is in use by another process. "
- "Please close any other process that may be accessing the device.";
+ return lmprintf(MSG_055);
case ERROR_CANT_QUICK_FORMAT:
- return "Quick format is not available for this device.";
+ return lmprintf(MSG_056);
case ERROR_LABEL_TOO_LONG:
- return "The volume label is invalid.";
+ return lmprintf(MSG_057);
case ERROR_INVALID_HANDLE:
- return "The device handle is invalid.";
+ return lmprintf(MSG_058);
case ERROR_INVALID_CLUSTER_SIZE:
- return "The selected cluster size is not valid for this device.";
+ return lmprintf(MSG_059);
case ERROR_INVALID_VOLUME_SIZE:
- return "The volume size is invalid.";
+ return lmprintf(MSG_060);
case ERROR_NO_MEDIA_IN_DRIVE:
- return "Please insert a media in drive.";
+ return lmprintf(MSG_061);
case ERROR_NOT_SUPPORTED:
- return "An unsupported command was received.";
+ return lmprintf(MSG_062);
case ERROR_NOT_ENOUGH_MEMORY:
- return "Memory allocation error.";
+ return lmprintf(MSG_063);
case ERROR_READ_FAULT:
- return "Read error.";
+ return lmprintf(MSG_064);
case ERROR_WRITE_FAULT:
- return "Write error.";
+ return lmprintf(MSG_065);
case ERROR_INSTALL_FAILURE:
- return "Installation failure";
+ return lmprintf(MSG_066);
case ERROR_OPEN_FAILED:
- return "Could not open media. It may be in use by another process. "
- "Please re-plug the media and try again.";
+ return lmprintf(MSG_067);
case ERROR_PARTITION_FAILURE:
- return "Error while partitioning drive.";
+ return lmprintf(MSG_068);
case ERROR_CANNOT_COPY:
- return "Could not copy files to target drive.";
+ return lmprintf(MSG_069);
case ERROR_CANCELLED:
- return "Cancelled by user.";
+ return lmprintf(MSG_070);
case ERROR_CANT_START_THREAD:
- return "Unable to create formatting thread.";
+ return lmprintf(MSG_071);
case ERROR_BADBLOCKS_FAILURE:
- return "Bad blocks check didn't complete.";
+ return lmprintf(MSG_072);
case ERROR_ISO_SCAN:
- return "ISO image scan failure.";
+ return lmprintf(MSG_073);
case ERROR_ISO_EXTRACT:
- return "ISO image extraction failure.";
+ return lmprintf(MSG_074);
case ERROR_CANT_REMOUNT_VOLUME:
- return "Unable to remount volume.";
+ return lmprintf(MSG_075);
case ERROR_CANT_PATCH:
- return "Unable to patch/setup files for boot.";
+ return lmprintf(MSG_076);
case ERROR_CANT_ASSIGN_LETTER:
- return "Unable to assign a drive letter.";
+ return lmprintf(MSG_077);
case ERROR_CANT_MOUNT_VOLUME:
- return "Can't mount GUID volume.";
+ return lmprintf(MSG_078);
default:
uprintf("Unknown error: %08X\n", error_code);
SetLastError(error_code);
diff --git a/src/stdlg.c b/src/stdlg.c
index 08fb6118..7189afb0 100644
--- a/src/stdlg.c
+++ b/src/stdlg.c
@@ -39,6 +39,7 @@
#include "registry.h"
#include "resource.h"
#include "license.h"
+#include "localization.h"
/* The following is only available on Vista and later */
#if (_WIN32_WINNT >= 0x0600)
@@ -66,6 +67,7 @@ static const SETTEXTEX friggin_microsoft_unicode_amateurs = {ST_DEFAULT, CP_UTF8
static BOOL notification_is_question;
static const notification_info* notification_more_info;
static BOOL reg_commcheck = FALSE;
+static WNDPROC original_wndproc = NULL;
/*
* We need a sub-callback to read the content of the edit box on exit and update
@@ -222,7 +224,7 @@ fallback:
INIT_XP_SHELL32;
memset(&bi, 0, sizeof(BROWSEINFOW));
bi.hwndOwner = hMainDialog;
- bi.lpszTitle = L"Please select the installation folder:";
+ bi.lpszTitle = utf8_to_wchar(lmprintf(MSG_106));
bi.lpfn = BrowseInfoCallback;
// BIF_NONEWFOLDERBUTTON = 0x00000200 is unknown on MinGW
bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS |
@@ -231,6 +233,7 @@ fallback:
if (pidl != NULL) {
CoTaskMemFree(pidl);
}
+ safe_free(bi.lpszTitle);
dialog_showing--;
}
@@ -244,7 +247,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des
DWORD tmp;
OPENFILENAMEA ofn;
char selected_name[MAX_PATH];
- char* ext_string = NULL;
+ char *ext_string = NULL, *all_files = NULL;
size_t i, ext_strlen;
BOOL r;
char* filepath = NULL;
@@ -259,6 +262,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des
IShellItem *si_path = NULL; // Automatically freed
dialog_showing++;
+ memset(filter_spec, 0, sizeof(filter_spec));
INIT_VISTA_SHELL32;
if (IS_VISTA_SHELL32_AVAILABLE) {
// Setup the file extension filter table
@@ -269,7 +273,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des
safe_free(ext_filter);
filter_spec[0].pszName = utf8_to_wchar(ext_desc);
filter_spec[1].pszSpec = L"*.*";
- filter_spec[1].pszName = L"All files";
+ filter_spec[1].pszName = utf8_to_wchar(lmprintf(MSG_107));
}
hr = CoCreateInstance(save?&CLSID_FileSaveDialog:&CLSID_FileOpenDialog, NULL, CLSCTX_INPROC,
@@ -305,6 +309,7 @@ char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_des
safe_free(wfilename);
safe_free(filter_spec[0].pszSpec);
safe_free(filter_spec[0].pszName);
+ safe_free(filter_spec[1].pszName);
if (SUCCEEDED(hr)) {
// Obtain the result of the user's interaction with the dialog.
@@ -343,11 +348,12 @@ fallback:
ofn.lpstrFile = selected_name;
ofn.nMaxFile = MAX_PATH;
// Set the file extension filters
- ext_strlen = safe_strlen(ext_desc) + 2*safe_strlen(ext) + sizeof(" (*.)\0*.\0All Files (*.*)\0*.*\0\0");
+ all_files = lmprintf(MSG_107);
+ ext_strlen = safe_strlen(ext_desc) + 2*safe_strlen(ext) + sizeof(" (*.)\0*.\0 (*.*)\0*.*\0\0") + safe_strlen(all_files);
ext_string = (char*)malloc(ext_strlen);
if (ext_string == NULL)
return NULL;
- safe_sprintf(ext_string, ext_strlen, "%s (*.%s)\r*.%s\rAll Files (*.*)\r*.*\r\0", ext_desc, ext, ext);
+ safe_sprintf(ext_string, ext_strlen, "%s (*.%s)\r*.%s\r%s (*.*)\r*.*\r\0", ext_desc, ext, ext, all_files);
// Microsoft could really have picked a better delimiter!
for (i=0; iid),
+ DialogBoxW(hMainInstance, MAKEINTRESOURCEW(notification_more_info->id),
hDlg, notification_more_info->callback);
break;
}
@@ -937,17 +987,19 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l
HWND hPolicy;
static HWND hFrequency, hBeta;
int32_t freq;
+ char update_policy_text[4096];
switch (message) {
case WM_INITDIALOG:
+ apply_localization(IDD_UPDATE_POLICY, hDlg);
SetTitleBarIcon(hDlg);
CenterDialog(hDlg);
hFrequency = GetDlgItem(hDlg, IDC_UPDATE_FREQUENCY);
hBeta = GetDlgItem(hDlg, IDC_INCLUDE_BETAS);
- IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Disabled"), -1));
- IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Daily (Default)"), 86400));
- IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Weekly"), 604800));
- IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Monthly"), 2629800));
+ IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_013)), -1));
+ IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_030, lmprintf(MSG_014))), 86400));
+ IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_015)), 604800));
+ IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_016)), 2629800));
freq = ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL);
EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NOW), (freq != 0));
EnableWindow(hBeta, (freq >= 0));
@@ -966,16 +1018,19 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l
IGNORE_RETVAL(ComboBox_SetCurSel(hFrequency, 3));
break;
default:
- IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, "Custom"), freq));
+ IGNORE_RETVAL(ComboBox_SetItemData(hFrequency, ComboBox_AddStringU(hFrequency, lmprintf(MSG_017)), freq));
IGNORE_RETVAL(ComboBox_SetCurSel(hFrequency, 4));
break;
}
- IGNORE_RETVAL(ComboBox_AddStringU(hBeta, "Yes"));
- IGNORE_RETVAL(ComboBox_AddStringU(hBeta, "No"));
+ IGNORE_RETVAL(ComboBox_AddStringU(hBeta, lmprintf(MSG_008)));
+ IGNORE_RETVAL(ComboBox_AddStringU(hBeta, lmprintf(MSG_009)));
IGNORE_RETVAL(ComboBox_SetCurSel(hBeta, GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS)?0:1));
hPolicy = GetDlgItem(hDlg, IDC_POLICY);
SendMessage(hPolicy, EM_AUTOURLDETECT, 1, 0);
- SendMessageA(hPolicy, EM_SETTEXTEX, (WPARAM)&friggin_microsoft_unicode_amateurs, (LPARAM)update_policy);
+ safe_sprintf(update_policy_text, sizeof(update_policy_text), update_policy, lmprintf(MSG_179),
+ lmprintf(MSG_180), lmprintf(MSG_181), lmprintf(MSG_182), lmprintf(MSG_183), lmprintf(MSG_184),
+ lmprintf(MSG_185), lmprintf(MSG_186));
+ SendMessageA(hPolicy, EM_SETTEXTEX, (WPARAM)&friggin_microsoft_unicode_amateurs, (LPARAM)update_policy_text);
SendMessage(hPolicy, EM_SETSEL, -1, -1);
SendMessage(hPolicy, EM_SETEVENTMASK, 0, ENM_LINK);
SendMessageA(hPolicy, EM_SETBKGNDCOLOR, 0, (LPARAM)GetSysColor(COLOR_BTNFACE));
@@ -984,6 +1039,7 @@ INT_PTR CALLBACK UpdateCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM l
switch (LOWORD(wParam)) {
case IDCLOSE:
case IDCANCEL:
+ reset_localization(IDD_UPDATE_POLICY);
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
case IDC_CHECK_NOW:
@@ -1036,8 +1092,7 @@ BOOL SetUpdateCheck(void)
uprintf("Short name used - Disabling initial update policy prompt\n");
enable_updates = TRUE;
} else {
- enable_updates = Notification(MSG_QUESTION, &more_info, APPLICATION_NAME " update policy",
- "Do you want to allow " APPLICATION_NAME " to check for application updates?\n");
+ enable_updates = Notification(MSG_QUESTION, &more_info, lmprintf(MSG_004), lmprintf(MSG_005));
}
if (!enable_updates) {
WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, -1);
@@ -1051,6 +1106,48 @@ BOOL SetUpdateCheck(void)
return TRUE;
}
+static void CreateStaticFont(HDC dc, HFONT* hyperlink_font) {
+ TEXTMETRIC tm;
+ LOGFONT lf;
+
+ if (*hyperlink_font != NULL)
+ return;
+ GetTextMetrics(dc, &tm);
+ lf.lfHeight = tm.tmHeight;
+ lf.lfWidth = 0;
+ lf.lfEscapement = 0;
+ lf.lfOrientation = 0;
+ lf.lfWeight = tm.tmWeight;
+ lf.lfItalic = tm.tmItalic;
+ lf.lfUnderline = TRUE;
+ lf.lfStrikeOut = tm.tmStruckOut;
+ lf.lfCharSet = tm.tmCharSet;
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = tm.tmPitchAndFamily;
+ GetTextFace(dc, LF_FACESIZE, lf.lfFaceName);
+ *hyperlink_font = CreateFontIndirect(&lf);
+}
+
+/*
+ * Work around the limitations of edit control, to display a hand cursor for hyperlinks
+ * NB: The LTEXT control must have SS_NOTIFY attribute for this to work
+ */
+INT_PTR CALLBACK subclass_callback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch (message)
+ {
+ case WM_SETCURSOR:
+ if ((HWND)wParam == GetDlgItem(hDlg, IDC_WEBSITE)) {
+ SetCursor(LoadCursor(NULL, IDC_HAND));
+ return (INT_PTR)TRUE;
+ }
+ break;
+ }
+ return CallWindowProc(original_wndproc, hDlg, message, wParam, lParam);
+}
+
/*
* New version notification dialog
*/
@@ -1058,64 +1155,55 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
{
int i;
HWND hNotes;
- TEXTRANGEW tr;
- ENLINK* enl;
- wchar_t wUrl[256];
char tmp[128];
static char* filepath = NULL;
static int download_status = 0;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
+ HFONT hyperlink_font = NULL;
switch (message) {
case WM_INITDIALOG:
+ apply_localization(IDD_NEW_VERSION, hDlg);
download_status = 0;
SetTitleBarIcon(hDlg);
CenterDialog(hDlg);
+ // Subclass the callback so that we can change the cursor
+ original_wndproc = (WNDPROC)SetWindowLongPtr(hDlg, GWLP_WNDPROC, (LONG_PTR)subclass_callback);
hNotes = GetDlgItem(hDlg, IDC_RELEASE_NOTES);
SendMessage(hNotes, EM_AUTOURLDETECT, 1, 0);
SendMessageA(hNotes, EM_SETTEXTEX, (WPARAM)&friggin_microsoft_unicode_amateurs, (LPARAM)update.release_notes);
SendMessage(hNotes, EM_SETSEL, -1, -1);
SendMessage(hNotes, EM_SETEVENTMASK, 0, ENM_LINK);
- safe_sprintf(tmp, sizeof(tmp), "Your version: %d.%d.%d (Build %d)",
- rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
- SetWindowTextA(GetDlgItem(hDlg, IDC_YOUR_VERSION), tmp);
- safe_sprintf(tmp, sizeof(tmp), "Latest version: %d.%d.%d (Build %d)",
- update.version[0], update.version[1], update.version[2], update.version[3]);
- SetWindowTextA(GetDlgItem(hDlg, IDC_LATEST_VERSION), tmp);
- SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD_URL), update.download_url);
+ SetWindowTextU(GetDlgItem(hDlg, IDC_YOUR_VERSION), lmprintf(MSG_018,
+ rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]));
+ SetWindowTextU(GetDlgItem(hDlg, IDC_LATEST_VERSION), lmprintf(MSG_019,
+ update.version[0], update.version[1], update.version[2], update.version[3]));
+ SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD_URL), update.download_url);
SendMessage(GetDlgItem(hDlg, IDC_PROGRESS), PBM_SETRANGE, 0, (MAX_PROGRESS<<16) & 0xFFFF0000);
if (update.download_url == NULL)
EnableWindow(GetDlgItem(hDlg, IDC_DOWNLOAD), FALSE);
break;
- case WM_NOTIFY:
- switch (((LPNMHDR)lParam)->code) {
- case NM_CLICK:
- case NM_RETURN:
- if (LOWORD(wParam) == IDC_WEBSITE) {
- ShellExecuteA(hDlg, "open", RUFUS_URL, NULL, NULL, SW_SHOWNORMAL);
- }
- break;
- case EN_LINK:
- enl = (ENLINK*) lParam;
- if (enl->msg == WM_LBUTTONUP) {
- tr.lpstrText = wUrl;
- tr.chrg.cpMin = enl->chrg.cpMin;
- tr.chrg.cpMax = enl->chrg.cpMax;
- SendMessageW(enl->nmhdr.hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&tr);
- wUrl[ARRAYSIZE(wUrl)-1] = 0;
- ShellExecuteW(hDlg, L"open", wUrl, NULL, NULL, SW_SHOWNORMAL);
- }
- break;
- }
- break;
+ case WM_CTLCOLORSTATIC:
+ if ((HWND)lParam != GetDlgItem(hDlg, IDC_WEBSITE))
+ return FALSE;
+ // Change the font for the hyperlink
+ SetBkMode((HDC)wParam, TRANSPARENT);
+ CreateStaticFont((HDC)wParam, &hyperlink_font);
+ SelectObject((HDC)wParam, hyperlink_font);
+ SetTextColor((HDC)wParam, RGB(0,0,125)); // DARK_BLUE
+ return (INT_PTR)CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDCLOSE:
case IDCANCEL:
+ reset_localization(IDD_NEW_VERSION);
safe_free(filepath);
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
+ case IDC_WEBSITE:
+ ShellExecuteA(hDlg, "open", RUFUS_URL, NULL, NULL, SW_SHOWNORMAL);
+ break;
case IDC_DOWNLOAD: // Also doubles as abort and launch function
switch(download_status) {
case 1: // Abort
@@ -1130,17 +1218,17 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
if (!CreateProcessU(NULL, tmp, NULL, NULL, FALSE, 0, NULL, filepath, &si, &pi)) {
- PrintStatus(0, FALSE, "Failed to launch new application");
+ PrintStatus(0, FALSE, lmprintf(MSG_214));
uprintf("Failed to launch new application: %s\n", WindowsErrorString());
} else {
- PrintStatus(0, FALSE, "Launching new application...");
+ PrintStatus(0, FALSE, lmprintf(MSG_213));
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDCLOSE, 0);
PostMessage(hMainDialog, WM_CLOSE, 0, 0);
}
break;
default: // Download
for (i=(int)safe_strlen(update.download_url); (i>0)&&(update.download_url[i]!='/'); i--);
- filepath = FileDialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", "Application");
+ filepath = FileDialog(TRUE, app_dir, (char*)&update.download_url[i+1], "exe", lmprintf(MSG_037));
if (filepath != NULL)
DownloadFileThreaded(update.download_url, filepath, hDlg);
break;
@@ -1151,14 +1239,14 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
case UM_ISO_INIT:
FormatStatus = 0;
download_status = 1;
- SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Abort");
+ SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), lmprintf(MSG_038));
return (INT_PTR)TRUE;
case UM_ISO_EXIT:
if (wParam) {
- SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Launch");
+ SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), lmprintf(MSG_039));
download_status = 2;
} else {
- SetWindowTextA(GetDlgItem(hDlg, IDC_DOWNLOAD), "Download");
+ SetWindowTextU(GetDlgItem(hDlg, IDC_DOWNLOAD), lmprintf(MSG_040));
download_status = 0;
}
return (INT_PTR)TRUE;
@@ -1168,7 +1256,7 @@ INT_PTR CALLBACK NewVersionCallback(HWND hDlg, UINT message, WPARAM wParam, LPAR
void DownloadNewVersion(void)
{
- DialogBoxA(hMainInstance, MAKEINTRESOURCEA(IDD_NEW_VERSION), hMainDialog, NewVersionCallback);
+ DialogBoxW(hMainInstance, MAKEINTRESOURCEW(IDD_NEW_VERSION), hMainDialog, NewVersionCallback);
}
void SetTitleBarIcon(HWND hDlg)
diff --git a/src/syslinux.c b/src/syslinux.c
index f01f7984..b3b70cf7 100644
--- a/src/syslinux.c
+++ b/src/syslinux.c
@@ -28,6 +28,7 @@
#include "rufus.h"
#include "resource.h"
+#include "localization.h"
#include "syslinux.h"
#include "syslxfs.h"
@@ -91,7 +92,7 @@ BOOL InstallSyslinux(DWORD drive_index, char drive_letter)
int dt = (int)ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType));
BOOL use_v5 = (dt == DT_SYSLINUX_V5) || ((dt == DT_ISO) && (iso_report.has_syslinux_v5));
- PrintStatus(0, TRUE, "Installing Syslinux v%d...", use_v5?5:4);
+ PrintStatus(0, TRUE, lmprintf(MSG_234, use_v5?5:4));
ldlinux_path[0] = drive_letter;